【发布时间】:2019-03-17 15:31:44
【问题描述】:
考虑以下代码:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <tuple>
auto read_data(std::ifstream& training_file) {
if (!training_file) {
throw std::runtime_error{"Error: could not open one or more files"};
}
std::stringstream training{};
training << training_file.rdbuf();
std::cout << training.str() << '\n';
return std::tie(training);
}
int main() {
std::ifstream input{"input.txt"};
auto [train] = read_data(input);
std::cout << train.str() << '\n';
std::cout << "x" << '\n';
}
并且忽略我使用std::tie 返回单个元素的事实(最初我是tieing 两个std::stringstream 对象,但MCVE 不需要)。
input.txt 文件如下所示:
0,0,0,0, 0,0,0,0,
注意 - 第二行之后没有换行符。
这个程序的意外输出是:
0,0,0,0, 0,0,0,0, É$~ Ź , x
显然,É$~ Ź , 部分不应该存在。
请注意,我正在输出完全相同的文件内容。我不知道意外的部分是从哪里来的。
在玩代码时会变得更加陌生。如果我注释掉main() 中的std::cout << train.str() << '\n'; 并在read_data() 函数中复制std::cout << training.str() << '\n'; 行,则输出如预期:
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, x
所以这不是由两次调用std::stringstream::str 引起的。一定是使用了返回值造成的。
还有什么?从main() 执行std::cout << train.str() << '\n'; 行两次 会导致程序以code 3 终止。
GDB 报告:
gdb: unknown target exception 0x80000001 at 0x7ff909e845c0
Thread 1 received signal ?, Unknown signal.
0x00007ff909e845c0 in ?? ()
但它还没有到此结束。如果我将文件内容更改为包含:
0 0
或
0 0 0 0
0 0 0 0
输出再次符合预期(使用原始代码 - read_data() 中的一个 cout 和 main() 中的一个。
为了确保我没有被一些潜入我的文件的不可打印字符欺骗,我使用 PowerShell 输出其十六进制表示,这导致有关原始文件内容的以下序列:
30 20 30 20 30 20 30 0D 0A 30 20 30 20 30 20 30
如您所见,除了0s、空格和carriage-return + line-feed,我的文件中没有其他内容。
知道为什么会发生这种情况吗?有关完整信息,我使用的是 MinGW 的 GCC 8.2.0。
【问题讨论】:
标签: c++ stringstream stdtuple