在getline上检查eof()(即while(!getline()。eof())和仅检查while(getline())

时间:2019-07-02 13:34:01

标签: c++ delimiter eof getline

while(getline())和while(!getline()。eof())之间有什么区别?

Am解析输入字符串。 我尝试了两种条件检查,但结果却有所不同。

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结果: 您好:CN 测试,OU XYZ,O ABC

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

3 个答案:

答案 0 :(得分:1)

参考号:CppReference.com, "iostate"

getline()返回对其进行操作的流的引用,即inpStrStream

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

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

CppReference状态,

  

...在几乎所有情况下,如果设置了eofbit,那么也设置了failbit

您在这里遇到了例外之一。 .operator!()检查failbit,对eofbit进行验证-getline()中的"ABC"确实设置了eofbit( (到达流的EOF时),但不failbit (因为最后一次操作仍然成功)。这使.eof()结束循环(不打印"ABC"),而.operator!()将再执行一次迭代(打印"ABC"),尝试执行另一个getline(),但失败(因为没有更多内容可供阅读),设置failbit并结束循环。

所以... .eof()明确地测试EOF,仅 ,即即使基础流发生了令人讨厌的事情,它也会尝试继续得到另外两个标志之一。


(*):请注意,还有更多测试。唯一对称的是.fail().operator!()(它们测试相同的事物),并且它们的对称相反的.operator bool()。其他.good().bad().eof()分别检查不同的事物!

答案 1 :(得分:0)

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

#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());
    char ch = '?';

    input >> ch;
    LOG(!!input);
    LOG(input.eof());
    LOG(ch);
}

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

    return 0;
}

及其输出:https://wandbox.org/permlink/r4OSFnkG3ZFETgd4

14: !!input = 1
15: input.eof() = 0
19: !!input = 0
20: input.eof() = 1
21: ch = ?

14: !!input = 1
15: input.eof() = 1
19: !!input = 0
20: input.eof() = 1
21: ch = ?
  1. 记住eof并不意味着您处于流的结尾,而是您试图读取超出其大小的流。
  2. 现在test getline的第二次运行成功(!!input),但是尝试读取超出流大小的数据,因此eof返回true。现在,与eof的循环可以拒绝对您来说很重要的事情,因为eof设置为true,但是阅读很成功。

答案 2 :(得分:0)

std::stringstream继承了定义操作符的类std::basic_ios

explicit operator bool() const;

那个

  

1返回:!fail()。

该操作符用于while语句的情况

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

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

来自C ++标准(C ++ 17、7标准转换)

  

4某些语言构造要求将表达式转换   为布尔值。在这种情况下出现的表达式e是   据说可以根据上下文转换为bool,并且如果且   仅当声明bool t(e)时;格式良好,对于某些发明   临时变量t(11.6)。