繁体   English   中英

C ++ istream :: read导致未定义的行为

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM