2009-10-09 13 views
7

मैं फ़ाइल में एक शून्य समाप्त नहीं किया गया चार सरणी आउटपुट करने का प्रयास कर रहा था।सी ++ गैर नल समाप्त हो गया चार सरणी आउटपुट

वास्तविक बात यह है कि, मैं पैकेट प्राप्त कर रहा हूं और फिर अपने क्षेत्रों को प्रिंट कर रहा हूं।

अब इन फ़ील्ड को निरस्त नहीं किया गया है, उदाहरण के लिए, डेटा सेगमेंट जिसमें 512 का आकार है लेकिन पूरी तरह से कब्जा नहीं किया जा सकता है या नहीं।

जब मैं एक फ़ाइल में यह डेटा लिखता हूं तो मैं सरल < < ओवरलोडेड फ़ंक्शन का उपयोग कर रहा हूं जो वास्तविक डेटा के बारे में कुछ भी नहीं जानता है और केवल डेटा सेगमेंट को समाप्त करने के लिए दिखता है।

तो, मैं आउटपुट फ़ंक्शन को केवल विशिष्ट बाइट्स लिखने के लिए कैसे कह सकता हूं?

enter code here 

bytescopied = strncpy(dest, src, maxbytes); 

if (bytescopied < 0) { // indicates no bytes copied, parameter error 

    throw(fit);   // error handler stuff here 

} else if (bytescopied == maxbytes) { 

    dest[maxbytes-1] = '\0'; // force null terminator 

} 

उत्तर

16

कि वास्तव में आप maxbytes बाइट्स डाल करने के लिए, write विधि

stream.write(buffer, maxbytes); 

आप बफर में कम बाइट्स हो सकते हैं का उपयोग करना चाहते हैं, तो आप कैसे पता उनमें से कितने अपने बफर शामिल करते हैं? '\0' निशान अंत बफ़र हैं, तो आप लिख सकते हैं:

stream.write(buffer, std::find(buffer, buffer+maxbytes, '\0') - buffer); 
+0

आपकी दूसरी कॉल में, पूरा दूसरा पैरामीटर सादे पुराने 'स्ट्रलेन' को कॉल करने का एक चौराहे वाला तरीका है। लेकिन उस स्थिति में, आप पूरे कथन के लिए और अधिक बेवकूफ तरीके का उपयोग कर सकते हैं: 'stream << buffer'। –

+0

संख्या स्ट्रेलन अधिकतम बाइट्स के बाद नहीं रुक जाएगी। –

+0

'strnlen' होगा। एक strnlen कॉल बहुत साफ दिखता है: 'strnlen (बफर, maxbytes) '। पॉइंटर्स या कुछ भी – gnud

3

एक सस्ता समाधान होगा एक बफर एक अतिरिक्त शून्य वर्ण के लिए जगह है कि करने के लिए और बस पर एक अशक्त चरित्र डाल:

इसके बजाय यह जो महंगा है की तरह कुछ का उपयोग कर हर बार कॉल करने के लिए की

बिंदु जब आप वास्तविक आकार को जानते हैं और उसके बाद नल-टर्मिनेटेड बफर आउटपुट करते हैं जैसा कि आप पहले से करते हैं। तेज़ और भरोसेमंद।

+0

हाँ, आप उस अतिरिक्त चरित्र को अस्थायी चर में सहेज सकते हैं। एक बार प्रिंटिंग हो जाने के बाद, बस इसे पुनर्स्थापित करें। –

3

यह काम करता है, लेकिन गलती से operator<< के मानक char* संस्करण बुला के खिलाफ सुरक्षित नहीं है:

#include <iostream> 

template <unsigned N> 
std::ostream& operator<< (std::ostream& out, const char (& data) [N]) 
{ 
    out.write (data, N); 
    // or out.write (data, strnlen (data, N)); 
    // if you want to stop at a '\0' in the data 
    return out; 
} 


struct Foo { 
    char one[5]; 
    char two[1]; 
    char three[5]; 
}; 

int main (void) 
{ 
    using namespace std; 

    Foo foo = { 
     { 'h', 'e', 'l', 'l', 'o' }, 
     { ' ' }, 
     {'w', 'o', 'r', 'l', 'd'} }; 

    cout << foo.one; 
    cout << foo.two; 
    cout << foo.three; 
    cout << endl; 
} 

यह सुरक्षित है, एक maxw प्रकार का उपयोग जो अगले char* उत्पादन की लंबाई सीमा:

struct maxw { 
    unsigned n; 
    maxw (unsigned n) : n (n) { } 
}; 

struct maxw_stream { 
    std::ostream& stream; 
    unsigned n; 
    maxw_stream (std::ostream& stream, unsigned n) : 
      stream (stream), 
      n (n) { 
    } 
}; 

maxw_stream operator<< (std::ostream& out, const maxw& m) 
{ 
    return maxw_stream (out, m.n); 
} 

std::ostream& operator<< (const maxw_stream& out, const char* data) 
{ 
    out.stream.write (data, strnlen (data, out.n)); 
    return out.stream; 
} 

// eg: 
cout << maxw(4) << "Hello World!" << endl; 
// Hell\n 
cout << maxw(100) << "Hello World!" << endl; 
// Hello World!\n 
+0

strnlen के साथ समस्या यह है कि AFAIK यह मानक नहीं है। और आपका टेम्पलेट फ़ंक्शन अच्छा है, लेकिन यदि एक बफर एक सादा सूचक के रूप में पारित किया जाता है, तो कोई सरणी नहीं, कोई चेतावनी नहीं होगी, केवल मानक सी-स्ट्रिंग आउटपुट फ़ंक्शन को कॉल किया जाएगा। –

+0

यह सी 99 में दस वर्षों से रहा है, और आईआईआरसी सी ++ 0 एक्स सभी सी 99 मानकों को लाएगा। –

+0

ठीक है, मैंने http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf खोजा और strnlen नहीं मिला। –

0

मैं मुख्य रूप से दो soluti देखना ऑन।

ASCII डेटा के मामले में:

memset(dest,0,destlength); 
bytescopied = strncpy(dest, src, maxbytes); 

तो तुम हमेशा buffor में स्पष्ट अशक्त-समाप्त स्ट्रिंग होगा।

ASCII डेटा के मामले में

दूसरा:

std::string yourASCII(src,maxbytes); 
yourASCII.c_str() // would be null terminated. 
0

आप पिछले बाइट के बारे में परवाह नहीं करते हैं, तो आप सिर्फ

buffer[buffersize-1] = 0; 

और उसके बाद आप चाहते हैं जो कुछ भी स्ट्रिंग कार्य करने के लिए बफर फ़ीड कर सकते हैं। यदि यह छोटा है, तो सब कुछ शून्य टर्मिनेटर पर चला जाएगा जो पहले से ही मौजूद है, और यदि कोई टर्मिनेटर नहीं था तो यह आपके द्वारा बनाए गए एक को चलाएगा।

और यह तेज़ है :)

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