[英]C++ istream::read causes undefined behaviour
我使用以下代码将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
可以请一个人帮我解释一下结果吗?
您的缓冲区没有终止-您需要分配一个额外的char并将其设置为'\\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>
。
请注意,这不能回答问题。 这是评论的跟进
一种解决方案是将缓冲区“存储”为[begin, end)
范围,而不是以null终止的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));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.