2009-10-09 25 views
7

我試圖輸出一個非空終止字符數組到文件。C++非空終止字符數組輸出

實際情況是,我正在接收數據包,然後打印它們的字段。

現在,因爲這些字段不是空終止的,例如,數據段的大小爲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

在你的第二個調用中,整個第二個參數只是簡單的調用普通的'strlen'。但是在這種情況下,你可能只是使用整個語句的更習慣的方式:'stream << buffer'。 – 2009-10-09 07:54:27

+0

編號strlen在最大字節後不會停止。 – 2009-10-09 08:04:17

+0

'strnlen'會。 strnlen調用看起來更清晰:'strnlen(buffer,maxbytes)'。不要使用指針或任何東西 – gnud 2009-10-09 08:33:27

3

一個廉價的解決辦法是有一個具有空間的額外空字符緩衝區,只是把一個空字符在當你知道實際的大小,然後按照你已經做的那樣輸出空字符結束的緩衝區。快速可靠。

+0

是的,您可以將該額外字符保存到臨時變量中。一旦打印完成,只需恢復它。 – 2009-10-09 10:32:00

3

這工作,但並不安全不會被意外調用標準char*operator<<

#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不是標準的。而且你的模板函數很好,但是如果一個緩衝區作爲一個普通指針傳遞,而不是一個數組,那麼就不會有警告,只會調用標準的c-string輸出函數。 – 2009-10-09 08:39:27

+0

它已經在C99中使用了十年,IIRC C++ 0x將帶來所有C99標準。 – 2009-10-09 08:47:29

+0

那麼,我搜索了http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf並找不到strnlen。 – 2009-10-09 09:52:18

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; 

再喂緩衝到任何你想要的字符串函數。如果更短,則所有內容都將運行到已存在的空終止符,並且如果沒有終結符,它將運行到剛創建的終結符。

而且速度很快:)