提取运算符在 istringstream 上达到 EOF,使用 int/char/string 进行行为更改

Extraction Operator reaching EOF on istringstream, behavioral change with int/char/string

提问人:DR. Palson_PH.d 提问时间:11/11/2021 更新时间:11/11/2021 访问量:167

问:

所以我在 c++ 中做一些简单的文件 I/O,我注意到了这种行为,不确定我是否忘记了提取运算符和字符

请注意,Unix 中的文件格式。

ifstream infile("test.txt");
string line;
while(getline(infile, line)){
  istringstream iss(line);
  
  **<type>** a;
  
  for(...){
     iss >> a;
  }

  if(iss.eof()) 
    cout << "FAIL" << endl;

}

假设输入文件test.txt如下所示,并且 a 的 <type> 是 int

$ 是换行符 (:set line)

100 100 100$
100 100 100$

我注意到的是,在读取第一行后,EOF 设置为 true;

如果输入文件是这样的,并且 <type> 是 char:

a b c$
a b c$

然后,代码将按预期完美地运行。

根据我对文件 I/O 和提取运算符的理解,前导空格被忽略,在输入从输入字符串流 iss 中取出后,托架落在字符上。因此,在这两种情况下,在每个字符串流的末尾,回车都落在换行符上,它不应该是 EOF。

将 a 的 <type> 更改为 string 的失败与 <type> = int 类似

顺便说一句,未设置故障位,
最后: 良好 = 0
失败 = 0
EOF = 1

C++ file-io eof istringstream

评论

0赞 user4581301 11/11/2021
我强烈建议制作一个最小的可重现示例,您似乎所描述的内容已经非常明显,因此我们需要一个具体的行为示例,以便我们可以重现和实验。
0赞 user4581301 11/11/2021
仔细观察,不是在看文件流的 EOF 位,而是在看可能已读到末尾的字符串流,并且合法地是第一行末尾的 EOF。为什么它不会报告该版本的 EOF,我还不知道。我们绝对需要一个完整的示例才能准确了解您遇到的问题。if(iss.eof())for(...)char
0赞 DR. Palson_PH.d 11/11/2021
for 循环设置为读取行中所有 3 个空格分隔值,将通过可重现的示例返回给您,谢谢。
0赞 user4581301 11/11/2021
100 100 100输入到寻找 3 个空格分隔令牌的代码将生成一个 EOF。 提供包含不带换行符的行,因此第一个将读取空格,第二个读取到下一个空格,第三个插入 .该版本只提取一个,因此它不会到达流的末尾。它读取 a ,跳过空格读取到下一个,跳过空格读取到下一个,然后停止,满意而不尝试读取到末尾。getlinestring>>stringstreamcharcharcharcharchar
0赞 DR. Palson_PH.d 11/11/2021
有趣的是,我明白了,所以 iss >> a(a 是 int)读作:100 >> 100 >> 100<EOF>,其中 iss >> a(a 是 char)读作:a >> b >> c,不接触 <EOF>。这是一个有趣的行为,让我陷入了困境。我在任何地方都找不到这方面的文档,你有来源吗?我认为你应该做一个正式的回答,这样就可以更好地记录在这里。我现在了解了机制(int/string 版本达到 <EOF>因为>>操作员不知道何时停止向下查看字符串流,因为除了 <EOF 之外,最后一项之后没有空格>

答:

2赞 user4581301 11/11/2021 #1

getline已提取并丢弃换行符,因此包含 100 100 100,而不是 100 100 100$,其中 $ 表示换行符。这意味着从 with a 读取所有三个令牌,运算符可能会到达 EOF 并生成 FAIL 消息。linelinestringstream>>

iss >> a;When is an 或 a 将跳过前面的所有空格,然后继续提取,直到它到达一个字符,该字符不可能是 OR 的空格或流的末尾。在流的第三个流上,流的末尾停止提取,并设置流的 EOF 标志。aintstringint>>

iss >> a;When is 将跳过前面的所有空格,然后只提取一个字符。在这种情况下,第三个将提取最后一个字符并在看到流的末尾之前停止,并且不设置 EOF 标志。achar>>