2012-03-08 25 views
6

मुझे आशा है कि इस सवाल का stackoverflow के लिए उपयुक्त है धारण करने के लिए ... एक std::string में कच्चे डेटा बाइट (8 बिट) के भंडारण के बजाय उन्हें std::vector<char> में भंडारण के बीच क्या अंतर है । मैं एक फ़ाइल से बाइनरी डेटा पढ़ रहा हूं और उन कच्चे बाइट्स को std::string में संग्रहीत कर रहा हूं। यह अच्छी तरह से काम करता है, ऐसा करने में कोई समस्या या समस्या नहीं है। मेरा कार्यक्रम अपेक्षित काम करता है। हालांकि, अन्य प्रोग्रामर std::vector<char> दृष्टिकोण पसंद करते हैं और सुझाव देते हैं कि मैं std::string का उपयोग करना बंद कर दूंगा क्योंकि यह कच्चे बाइट्स के लिए असुरक्षित है। तो मैं सोच रहा हूं कि कच्चे डेटा बाइट्स रखने के लिए std::string का उपयोग करना असुरक्षित क्यों हो सकता है? मुझे पता है std::string अक्सर ASCII पाठ को स्टोर करने के लिए उपयोग किया जाता है, लेकिन बाइट एक बाइट है, इसलिए मुझे std::vector<char> की वरीयता नहीं समझती है।std :: स्ट्रिंग या std :: वेक्टर <char> कच्चे डेटा

किसी भी सलाह के लिए धन्यवाद!

+3

ऐसा लगता था कि std :: स्ट्रिंग को संगत भंडारण प्रदान करने की गारंटी नहीं थी, जो महत्वपूर्ण है यदि आप डेटा के लिए गैर-कॉन्स्ट पॉइंटर प्राप्त करने के लिए '& s [0]' जैसी चीजें करते हैं। लेकिन यह अब सी ++ 11 के रूप में सच नहीं है। –

+1

[वेक्टर बाइनरी डेटा के लिए बनाम स्ट्रिंग] के संभावित डुप्लिकेट (http://stackoverflow.com/questions/1556229/vector-unsigned-char-vs-string-for-binary-data) –

उत्तर

12

समस्या वास्तव में यह नहीं है कि यह काम करता है या नहीं। समस्या यह है कि यह आपके कोड को पढ़ने वाले अगले व्यक्ति के लिए पूरी तरह उलझन में है। std::string टेक्स्ट प्रदर्शित करने के लिए है। आपका कोड पढ़ने वाला कोई भी उम्मीद करेगा। आप अपने इरादे को std::vector<char> के साथ बहुत बेहतर घोषित करेंगे।

यह कोड समीक्षाओं में आपके WTF/min को बढ़ाता है।

+0

मैंने कभी इस तरह से सोचा नहीं है। अच्छी बात। मैं एक कंटेनर होल्डिंग बाइट्स के रूप में std :: स्ट्रिंग के बारे में सोचता हूं। वे एएससीआईआई बाइट्स हो सकते हैं, लेकिन इन्हें होने की आवश्यकता नहीं है। मेरे दिमाग में, std :: string std :: बाइट्स है, लेकिन यह जानना अच्छा है कि अन्य अलग-अलग सोचते हैं। मैं देख सकता हूं कि यह भ्रमित कैसे होगा। – 01100110

+2

अधिक अंक देखने के लिए, जब मुझे लगता है कि "बाइट", मुझे लगता है कि 'uint8_t'। अधिकांश भाग के लिए, जब मैं वास्तव में * चरित्र * डेटा धारण कर रहा हूं, तो मैं केवल 'char' का उपयोग करता हूं, जब मैं बफर का उपयोग कर रहा हूं (उदाहरण के लिए' नया char [] 'का उपयोग करके स्मृति को आवंटित करने के लिए जिसमें मैं एक निर्माण करने जा रहा हूं ऑब्जेक्ट), या कुछ स्थापित एपीआई के साथ अच्छा खेलने के लिए जो 'char' का उपयोग करता है। कच्चे बाइट डेटा को स्टोर करने के लिए मैं आमतौर पर 'std :: vector ' रखना पसंद करूंगा। – Hurkyl

+0

Google स्नैपी में कच्चे बाइट्स को संग्रहीत करने के लिए std :: स्ट्रिंग का उपयोग करता है। – GameDeveloper

5

सी ++ 03 में, std::string का उपयोग करके बाइट डेटा की एक सरणी स्टोर करने के लिए एक अच्छा विचार नहीं था। मानक द्वारा, std::stringपर नहीं है जो डेटा को संगत रूप से संग्रहीत करने के लिए है। सी ++ 11 निश्चित है कि यह डेटा संगत होना चाहिए।

तो यह C++ 03 में ऐसा करने के लिए कार्यात्मक नहीं होगा। जब तक कि आप यह सुनिश्चित करने के लिए std::string के अपने सी ++ मानक लाइब्रेरी कार्यान्वयन को व्यक्तिगत रूप से सत्यापित नहीं करते हैं, यह सुनिश्चित करने के लिए कि यह संगत है।

किसी भी तरह से, मैं vector<char> का सुझाव दूंगा। आम तौर पर, जब आप string देखते हैं, तो आप इसे एक ... स्ट्रिंग होने की उम्मीद करते हैं। आप जानते हैं, कुछ प्रकार के एन्कोडिंग में वर्णों का अनुक्रम। एक vector<char> यह स्पष्ट करता है कि यह एक स्ट्रिंग नहीं है, लेकिन बाइट्स की एक सरणी है।

+0

धन्यवाद। हम सी ++ 11 का उपयोग करते हैं ताकि बाइट्स संगत हों। Std :: स्ट्रिंग का मेरा विचार सबसे अधिक व्यापक लगता है। मैं आपकी राय की सराहना करता हूं। यह समझना मेरे लिए अच्छा है कि दूसरों को यह भ्रमित क्यों लगता है, भले ही यह काम करता हो। – 01100110

3

संगत भंडारण और कोड-स्पष्टता के मुद्दों के अलावा, मैं कच्चे बाइट्स को पकड़ने के लिए std::string का उपयोग करने की कोशिश कर रहे कुछ निष्पक्ष त्रुटियों में भाग गया।

उनमें से अधिकतर char बाइट्स के सरणी को std::string में परिवर्तित करने की कोशिश कर रहे हैं, जब सी पुस्तकालयों के साथ इंटरफेसिंग करते हैं। उदाहरण के लिए:

std::string password = "pass\0word"; 
std::cout << password.length() << std::endl; // prints 4, not 9 

हो सकता है कि आपको लगता है कि ठीक कर सकते हैं लंबाई निर्दिष्ट द्वारा:

std::string password("pass\0word", 0, 9); 
std::cout << password.length() << std::endl; // nope! still 4! 

ऐसा इसलिए है क्योंकि निर्माता एक सी स्ट्रिंग, नहीं एक बाइट सरणी प्राप्त करने की उम्मीद है। एक बेहतर तरीका हो सकता है, लेकिन मैं इसके साथ समाप्त हुआ:

std::string password("pass0word", 0, 9); 
password[4] = '\0'; 
std::cout << password.length() << std::endl; // hurray! 9! 

थोड़ा गुंजाइश। शुक्र है कि मैंने इसे यूनिट परीक्षण में पाया, लेकिन अगर मेरे टेस्ट वैक्टरों में नल बाइट्स नहीं होते तो मैं इसे याद करता। यह कपटपूर्ण बात यह है कि उपर्युक्त दूसरा दृष्टिकोण तक ठीक काम करेगा, जिसमें सरणी में एक शून्य बाइट होता है।

अब तक std::vector<uint8_t> एक अच्छा विकल्प दिखता है (धन्यवाद जेएन।और Hurkyl):

char p[] = "pass\0word"; 
std::vector<uint8_t> password(p, p, p+9); // :) 

नोट: मैं std::string साथ इटरेटर निर्माता प्रयास नहीं किया है, लेकिन इस त्रुटि इतना आसान था कि यह और भी संभावना से बचने के लायक हो सकता है बनाने के लिए है।

सबक सीखा: अशक्त बाइट युक्त परीक्षण वेक्टर witih

  • टेस्ट बाइट संभाल-संचालन पद्धतियों।
  • कच्चे बाइट्स रखने के लिए std::string का उपयोग करके सावधान रहें (और मैं इससे बचूंगा)।
+0

क्या आप सी ++ 11 में स्ट्रिंग अक्षर से 'char' या 'uint8_t' के वेक्टर को प्रारंभ कर सकते हैं? –

संबंधित मुद्दे