C ++非null终止char数组输出

时间:2009-10-09 07:31:30

标签: c++ string file-io

我试图将一个非空终止的char数组输出到文件中。

实际情况是,我正在接收数据包,然后打印他们的字段。

现在因为这些字段不是以空值终止的,例如,一个大小为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

}

5 个答案:

答案 0 :(得分:16)

如果您想准确填写maxbytes个字节,请使用write方法

stream.write(buffer, maxbytes);

如果缓冲区中的字节数较少,您如何知道缓冲区中包含多少字节?如果'\0'标记缓冲区结束,则可以写:

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

答案 1 :(得分:3)

一个廉价的解决方案是拥有一个缓冲区,该缓冲区具有额外空字符的空间,并且当您知道实际大小时,只需在该点处放置一个空字符,然后像您已经那样输出空终止缓冲区。快速可靠。

答案 2 :(得分: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

答案 3 :(得分:0)

我主要看两种解决方案。

如果是ASCII数据:

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

然后你总是在buffor中有明确的以null结尾的字符串。

ASCII数据的第二个:

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

答案 4 :(得分:0)

如果你不关心最后一个字节,你可以

buffer[buffersize-1] = 0;

然后将缓冲区提供给您想要的任何字符串函数。如果它更短,一切都将运行到已存在的空终结器 ,如果没有终结器,它将运行到刚刚创建的终结器。

它很快:)