दिलचस्प पोस्ट
पॅक () क्या करता है? जीआईटी भंडार से उत्पन्न आंकड़े कीबोर्ड को खारिज करने का आसान तरीका? एक उपयोगकर्ता सत्र को अमान्य कैसे करें जब वह उसी क्रेडेंशियल के साथ दो बार लॉग करता है मेवेन-छाया-प्लगइन क्या उपयोग किया जाता है, और आप जावा पैकेजों को क्यों स्थानांतरित करना चाहते हैं? जावास्क्रिप्ट में सटीक टाइमर कैसे बनाएं? गतिशील रूप से लोड हो रहा है सीएसएस स्टाइलशीट IE पर काम नहीं करता है MySQL में उन सभी विशिष्ट कॉलम नामों के साथ तालिकाओं को कैसे खोजें? जावा से एक लिनक्स शेल कमांड खोलना चाहते हैं एंड्रॉइड – मेरे आवेदन में उपयोग किए जाने वाले वॉल्यूम बटन JAX-RS एप्लिकेशन को केवल एनोटेशन का उपयोग कैसे करें (कोई web.xml) नहीं है? लॉगआउट करने पर, गतिविधि इतिहास स्टैक साफ़ करें, केवल लॉग-इन-केवल गतिविधियां खोलने से "बैक" बटन को रोकना प्रिंट "हैलो वर्ल्ड" हर एक्स सेकेंड php वाक्य सीमाओं का पता लगाने घातक त्रुटि: बुलियन पर सदस्य फ़ंक्शन bind_param () पर कॉल करें

क्या आप एक एम्बेडेड नल के साथ एक std :: स्ट्रिंग का निर्माण करते हैं?

यदि मैं एक पंक्ति के साथ एक std :: string का निर्माण करना चाहता हूं:

std::string my_string("a\0b"); 

मैं जिसके परिणामस्वरूप स्ट्रिंग में तीन अक्षर चाहता हूँ (a, null, b), मुझे केवल एक मिलता है। उचित सिंटैक्स क्या है?

वेब के समाधान से एकत्रित समाधान "क्या आप एक एम्बेडेड नल के साथ एक std :: स्ट्रिंग का निर्माण करते हैं?"

सी ++ 14 के बाद से

हम वाकई std::string बनाने में सक्षम हैं

 #include <iostream> #include <string> int main() { using namespace std::string_literals; std::string s = "pl-\0-op"s; // <- Notice the "s" at the end // This is a std::string literal not // a C-String literal. std::cout << s << "\n"; } 

सी ++ 14 से पहले

समस्या std::string constructor है जो const char* लेता है const char* मानता है कि इनपुट एक सी स्ट्रिंग है सी-स्ट्रिंग \0 समाप्त हो गई हैं और इस तरह से \0

इसके लिए क्षतिपूर्ति करने के लिए, आपको कन्स्ट्रक्टर का उपयोग करना होगा जो चार सरणी से स्ट्रिंग बनाता है (C-String नहीं)। यह दो पैरामीटर लेता है – सरणी और लंबाई के लिए एक सूचक:

 std::string x("pq\0rs"); // Two characters because input assumed to be C-String std::string x("pq\0rs",5); // 5 Characters as the input is now a char array with 5 characters. 

नोट: सी + + std::string नहीं है \0 0- टर्मिनेटेड (जैसा कि अन्य पदों में सुझाया गया है) हालांकि, आप एक सूचक को एक आंतरिक बफर में निकालने के लिए कर सकते हैं जिसमें सी-स्ट्रिंग विधि c_str()

डैग टी के नीचे एक vector<char> का उपयोग करने के बारे में भी देखें।

सी ++ 14 समाधान के लिए भी रियाद की जांच करें।

यदि आप हेरफेर कर रहे हैं जैसे आप सी-स्टाइल स्ट्रिंग (वर्णों की सरणी) के साथ प्रयोग करने पर विचार करेंगे

 std::vector<char> 

आप इसे उसी तरह से एक सरणी के रूप में इलाज करने के लिए अधिक स्वतंत्रता प्राप्त कर रहे हैं जिससे आप सी-स्ट्रिंग का इलाज करेंगे। आप किसी स्ट्रिंग में कॉपी करने के लिए कॉपी () का उपयोग कर सकते हैं:

 std::vector<char> vec(100) strncpy(&vec[0], "blah blah blah", 100); std::string vecAsStr( vec.begin(), vec.end()); 

और आप इसका उपयोग उन कई स्थानों में कर सकते हैं, जिन्हें आप सी-स्ट्रिंग्स का उपयोग कर सकते हैं

 printf("%s" &vec[0]) vec[10] = '\0'; vec[11] = 'b'; 

स्वाभाविक रूप से, हालांकि, आप सी-स्ट्रिंग जैसी समस्याओं से पीड़ित हैं। आप अपने अशक्त टर्मिनल को भूल सकते हैं या आवंटित स्थान से पहले लिख सकते हैं।

मुझे नहीं पता है कि आप ऐसा क्यों करना चाहते हैं, लेकिन कोशिश करें:

 std::string my_string("a\0b", 3); 

उपयोगकर्ता-परिभाषित लिखे शब्द नई क्षमताओं को C ++ में जोड़ते हैं? एक सुरुचिपूर्ण उत्तर प्रस्तुत करता है: परिभाषित करें

 std::string operator "" _s(const char* str, size_t n) { return std::string(str, n); } 

तो आप अपनी स्ट्रिंग इस तरह से बना सकते हैं:

 std::string my_string("a\0b"_s); 

या यहां तक ​​कि:

 auto my_string = "a\0b"_s; 

एक "पुरानी शैली" तरीका है:

 #define S(s) s, sizeof s - 1 // trailing NUL does not belong to the string 

तो आप परिभाषित कर सकते हैं

 std::string my_string(S("a\0b")); 

निम्नलिखित काम करेंगे …

 std::string s; s.push_back('a'); s.push_back('\0'); s.push_back('b'); 

आपको इसके साथ सावधान रहना होगा यदि आप किसी भी संख्यात्मक वर्ण के साथ 'बी' को बदलते हैं, तो आप चुपचाप सबसे अधिक तरीकों का उपयोग कर गलत स्ट्रिंग बनाएंगे। देखें: सी ++ स्ट्रिंग लीटरल्स एस्केप वर्ण के लिए नियम ।

उदाहरण के लिए, मैंने एक प्रोग्राम के बीच में इस निर्दोष दिखने वाला स्निपेट छोड़ा

 // Create '\0' followed by '0' 40 times ;) std::string str("\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", 80); std::cerr << "Entering loop.\n"; for (char & c : str) { std::cerr << c; // 'Q' is way cooler than '\0' or '0' c = 'Q'; } std::cerr << "\n"; for (char & c : str) { std::cerr << c; } std::cerr << "\n"; 

मेरे लिए यह प्रोग्राम आउटपुट है:

 Entering loop. Entering loop. vector::_M_emplace_ba QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ 

यह मेरा पहला प्रिंट स्टेटमेंट दो बार था, कई नॉन-प्रिंटिंग वर्ण, एक नई लाइन के बाद, आंतरिक मेमोरी में कुछ के बाद, जिसे मैंने ओवरराइट किया (और फिर मुद्रित किया, दिखा रहा है कि इसे ओवरराइट किया गया है)। सबसे ज़रूरी, यहां तक ​​कि इसे पूरी तरह से और वर्बोस जीसीसी चेतावनियों से संकलित करने से मुझे कुछ गलत होने का कोई संकेत नहीं मिला, और वाल्ग्रिंड के माध्यम से कार्यक्रम चलाने से किसी भी अनुचित मेमोरी एक्सेस पैटर्न के बारे में शिकायत नहीं हुई। दूसरे शब्दों में, यह आधुनिक उपकरणों द्वारा पूरी तरह से undetectable है

आप बहुत ही सरल std::string("0", 100); साथ इस समस्या को प्राप्त कर सकते हैं std::string("0", 100); , लेकिन उपरोक्त उदाहरण थोड़ा जटिल है, और यह देखने के लिए कठिन है कि क्या गलत है।

सौभाग्य से, सी ++ 11 हमें प्रारंभिक सूची सिंटैक्स का उपयोग करके समस्या का एक अच्छा समाधान प्रदान करता है। यह आपको वर्णों की संख्या निर्दिष्ट करने से बचाता है (जो, जैसा कि मैंने उपरोक्त दिखाया, आप गलत तरीके से कर सकते हैं), और बच गए संख्याओं के संयोजन से बचा जाता है std::string str({'a', '\0', 'b'}) किसी भी स्ट्रिंग सामग्री के लिए सुरक्षित है, संस्करणों के विपरीत जो char ओर एक आकार और एक आकार लेते हैं।

सी ++ 14 में अब आप शाब्दिक इस्तेमाल कर सकते हैं

 using namespace std::literals::string_literals; std::string s = "a\0b"s; std::cout << s.size(); // 3 

यदि यह सवाल केवल शैक्षिक उद्देश्यों के लिए नहीं है तो std :: vector <char> का उपयोग करने के लिए बेहतर है

गुमनाम का उत्तर उत्कृष्ट है, लेकिन सी ++ 98 में एक गैर-मैक्रो समाधान भी है:

 template <size_t N> std::string RawString(const char (&ch)[N]) { return std::string(ch, N-1); // Again, exclude trailing `null` } 

इस फ़ंक्शन के साथ, RawString(/* literal */) S(/* literal */) के समान स्ट्रिंग उत्पन्न करेगा:

 std::string my_string_t(RawString("a\0b")); std::string my_string_m(S("a\0b")); std::cout << "Using template: " << my_string_t << std::endl; std::cout << "Using macro: " << my_string_m << std::endl; 

इसके अतिरिक्त, मैक्रो के साथ एक समस्या है: अभिव्यक्ति वास्तव में एक std::string रूप में लिखित नहीं है, और इसलिए उपयोग नहीं किया जा सकता है उदाहरण के लिए साधारण असाइनमेंट – आरंभीकरण:

 std::string s = S("a\0b"); // ERROR! 

… तो यह उपयोग करने के लिए बेहतर हो सकता है:

 #define std::string(s, sizeof s - 1) 

जाहिर है, आपको केवल अपनी परियोजना में एक या दूसरे समाधान का उपयोग करना चाहिए और उस पर कॉल करना जो आपको उपयुक्त लगता है।

मुझे पता है कि यह एक लंबा समय है इस सवाल से पूछा गया है। लेकिन जिन लोगों के पास ऐसी ही समस्या है, उनमें से निम्न कोड में रुचि हो सकती है।

 CComBSTR(20,"mystring1\0mystring2\0") 

स्टडी :: स्ट्रिंग्स के लगभग सभी क्रियान्वयन निरर्थक हैं, इसलिए आपको ऐसा नहीं करना चाहिए। ध्यान दें कि "a \ 0b" वास्तव में स्वत: नल टर्मिनेटर (a, null, b, null) की वजह से चार अक्षर लंबा है यदि आप वास्तव में ऐसा करना चाहते हैं और std :: string के अनुबंध को तोड़ना चाहते हैं, तो आप ऐसा कर सकते हैं:

 std::string s("aab"); s.at(1) = '\0'; 

लेकिन यदि आप करते हैं, तो आपके सभी मित्र आप पर हँसेंगे, आपको कभी सच्ची खुशी नहीं मिलेगी।