在 getline 上检查 eof() 即 while(!getline().eof()) 和简单地检查 while(getline()) 有什么区别

What is difference in checking eof() on getline i.e. while(!getline().eof()) and checking simply while(getline())

提问人:Pravinkumar 提问时间:7/2/2019 更新时间:7/16/2022 访问量:582

问:

while(getline()) 和 while(!getline().eof()) 和有什么不一样?

正在解析输入字符串。 我已经尝试了两种条件检查,我看到了结果的差异。

std::string testStr = "CN=Test, OU=XYZ, O=ABC";
std::stringstream inpStrStream(testStr);
std::string tempStr;
getline(inpStrStream, tempStr, '=');
std::cout<<"Hello:"<<tempStr<<std::endl;

//Let's call this as "Ex A"
while(getline(inpStrStream, tempStr, '='))
{
   std::cout<<tempStr<<std::endl;
}
    (OR)
//Let's call this as "Ex B"
while(!getline(inpStrStream, tempStr, '=').eof())
{
   std::cout<<tempStr<<std::endl;
}

我期望两者的结果相同,但“Ex A”和“Ex B”的结果不同。我在“Ex B”的输出中没有看到字符串“ABC”:

Ex A 结果: 您好:CN 测试、OU XYZ,O 美国广播公司

Ex B 结果: 您好:CN 测试、OU XYZ,O

C++ 分隔符 EOF GetLine

评论

2赞 Marek R 7/2/2019
一个检查所有错误,另一个检查特定错误:尝试读取超出文件大小。
0赞 Eljay 7/2/2019
“Ex B”在成功解析到 后退出循环,但由于 EOF 被跳闸,因此不会打印最后的解析结果。ABCtempStr

答:

1赞 DevSolar 7/2/2019 #1

参考文献:CppReference.com,“碘酸盐”

getline()返回它所操作的流的引用,即 .inpStrStream

inpStrStream.operator bool()(或 / ) 将检查是否设置了流的 或。while ( inpStrStream )while ( getline( inpStrStream, tempStr, '=' ) )failbitbadbit

! inpStrStream.eof()将检查是否设置了流。(*)eofbit

CppReference 状态,

...在几乎所有情况下,如果被设置,也被设置。eofbitfailbit

您在这里遇到了一个例外。 检查 ,而不是 -- -- ant that of does set(当到达流的 EOF 时),但不检查 failbit(因为最后一个操作仍然成功)。这使得结束循环(不是打印),而将再进行一次迭代(打印),尝试另一次,但失败(因为没有更多可读取的内容),设置并结束循环。.operator!()failbiteofbitgetline()"ABC"eofbit.eof()"ABC".operator!()"ABC"getline()failbit

所以。。。 将仅显式测试 EOF,即即使底层流发生了一些令人讨厌的事情,并且确实设置了其他两个标志之一,也会尝试继续。.eof()


(*):请注意,还有更多测试。唯一对称的是 和 (它们测试相同的事物),以及它们的对称相反 。其他人-- , ,和--检查不同的东西!.fail().operator!().operator bool().good().bad().eof()

评论

0赞 Pravinkumar 7/3/2019
“而 .operator!() 将再进行一次迭代(打印“ABC”) “- 此语句令人困惑,因为对于 Ex B 情况,我们没有看到 ABC 打印。
0赞 DevSolar 7/3/2019
@Pravinkumar:我们没有看到 ABC 打印在 Ex. B 中,因为那不是(如在 Ex.A),但否定 .inpStrStream.operator!()inpStrStream.eof()
0赞 Pravinkumar 7/3/2019
所以我的理解是 getline() 检查流的 failbit 或 badbit 被设置,因为它没有设置,所以它打印 ABC,而 getline().eof 检查遇到的 eof,并且由于它遇到 eof,所以它返回 true & 因此 !true 是假的,因此 while 条件退出??
0赞 DevSolar 7/3/2019
@Pravinkumar:对不起,不是,是。我的错。不过,同样的道理。operator!()operator bool()
0赞 DevSolar 7/3/2019
@Pravinkumar:不是检查。 返回对流的引用。 期望布尔值。将流引用计算为布尔值对该流的调用。如果 .与此相反,如果 .getline()getline()while ().operator bool()! failbit && ! badbit! (/*stream*/).eof()! eofbit
1赞 Marek R 7/2/2019 #2

看看这个简单的测试代码:

#include <iostream>
#include <sstream>

#define LOG(x) std::cout << __LINE__ << ": " #x " = " << x << '\n'

void test(char termChar)
{

    std::stringstream input;
    input << "lets try this!";
    std::string s;
    std::getline(input, s, termChar);
    
    LOG(!!input);
    LOG(input.eof());
    LOG(input.tellg());
    char ch = '?';
    
    input >> ch;
    LOG(!!input);
    LOG(input.eof());
    LOG(input.tellg());
    LOG(ch);
}

int main()
{
    test('!');
    std::cout << '\n';
    test('#');
    
    return 0;
}

其输出:https://godbolt.org/z/f55eTjWK1

14: !!input = 1
15: input.eof() = 0
16: input.tellg() = 14
20: !!input = 0
21: input.eof() = 1
22: input.tellg() = -1
23: ch = ?

14: !!input = 1
15: input.eof() = 1
16: input.tellg() = -1
20: !!input = 0
21: input.eof() = 1
22: input.tellg() = -1
23: ch = ?
  1. 记住并不意味着您处于流的末尾,而是您尝试读取超出其大小的流。eof
  2. 现在在第二次运行中成功 (),但尝试读取超出流大小,因此返回。现在你的循环可以拒绝对你来说重要的事情,因为设置为,但阅读是成功的。testgetline!!inputeoftrueeofeoftrue
0赞 Vlad from Moscow 7/2/2019 #3

该类继承定义运算符的类std::stringstreamstd::basic_ios

explicit operator bool() const;

1 返回:!fail()。

此运算符用于 while 语句的条件

while(getline(inpStrStream, tempStr, '=')) 

在上下文中将调用 of 返回的对象转换为 bool 类型。std::getline

从 C++ 标准(C++ 17,7 标准转换)

4 某些语言结构要求转换表达式 设置为布尔值。在这样的上下文中出现的表达式 e 是 据说在上下文中转换为布尔值,并且格式良好,如果和 仅当声明 bool t(e);格式良好,对于一些发明的 临时变量 t (11.6)。