我使用以下代码将n
字符从二进制文件复制到char*
变量:
std::ifstream is ("write.abc", std::ifstream::binary);
if (is) {
// get length of file:
is.seekg (0, is.end);
int length = is.tellg();
is.seekg (0, is.beg);
char * buffer = new char [length];
std::cout << "Reading " << length << " characters... ";
// read data as a block:
is.read (buffer,length);
std::cout << "length of buffer: "<<strlen(buffer) <<endl;
std::cout << "Content of buffer: "<<buffer <<endl;
.......
我的文件内容:
这是编译的结果:
我的问题如下:我等着:
缓冲区长度:13
缓冲内容:abcdefghjklmn
有人可以帮我解释一下结果吗?
答案 0 :(得分:8)
您的缓冲区未终止 - 您需要分配一个额外的字符并将其设置为'\0'
,否则它只是一个未终止的C字符串,因此strlen
很可能会返回无效值,并尝试打印字符串通常会产生垃圾。
char * buffer = new char [length + 1]; // <<< allocate space for `length`
// characters + terminator
std::cout << "Reading " << length << " characters... ";
// read data as a block:
is.read (buffer,length);
buffer[length] = '\0'; // <<< terminate C-style string
请注意,使用正确的C ++风格的std::string
而不是旧式的C风格char *
字符串可以避免这个和其他常见问题,并且通常更简单,更强大。如果您正在阅读二进制数据而不是文本,请考虑使用std::vector<unsigned char>
。
答案 1 :(得分:1)
请注意,这不是回答问题。这是评论的后续内容
一种解决方案是将缓冲区“存储”为[begin, end)
范围而不是空终止的C字符串。这比null终止字符串有一个很大的优势 - 它可以与 STL算法一起使用,而无需调用strlen(...)
来查找end
元素。
举几个例子:
std::stringstream is("some text\n");
if (is)
{
// get length of file:
is.seekg (0, is.end);
auto length = is.tellg();
is.seekg (0, is.beg);
char* begin = new char [length];
char* end = begin + length;
std::cout<<"Reading "<<length<<" characters...\n";
// read data as a block:
is.read (begin,length);
//print the data:
std::copy(begin, end, std::ostream_iterator<char>(std::cout));
//print the data backwards:
std::copy(std::reverse_iterator<char*>(end), std::reverse_iterator<char*>(begin), std::ostream_iterator<char>(std::cout));
std::cout<<std::endl;
//create string from data:
std::string str(begin, end);
std::cout<<str;
//sum the characters
auto sum = std::accumulate(begin, end, 0);
std::cout<<sum<<std::endl;
//make them uppercase
std::transform(begin, end, begin, toupper);
std::copy(begin, end, std::ostream_iterator<char>(std::cout));
}