简体   繁体   English

简单的C ++不能读取EOF

[英]Simple C++ not reading EOF

I'm having a hard time understanding why while (cin.get(Ch)) doesn't see the EOF . 我很难理解为什么while (cin.get(Ch))没有看到EOF I read in a text file with 3 words, and when I debug my WordCount is at 3 (just what I hoped for). 我在一个包含3个单词的文本文件中读取,当我调试我的WordCount时为3(正如我所希望的那样)。 Then it goes back to the while loop and gets stuck. 然后它回到while循环并卡住。 Ch then has no value. 然后Ch没有价值。 I thought that after the newline it would read the EOF and break out. 我认为在换行后它会读取EOF并突破。 I am not allowed to use <fstream> , I have to use redirection in DOS. 我不允许使用<fstream> ,我必须在DOS中使用重定向。 Thank you so much. 非常感谢。

#include <iostream>
using namespace std;

int main()
{
    char Ch = ' ';
    int WordCount = 0;
    int LetterCount = 0;

    cout << "(Reading file...)" << endl;

    while (cin.get(Ch))
    {
        if ((Ch == '\n') || (Ch == ' '))
        {
            ++WordCount;
            LetterCount = 0;
        }
        else
            ++LetterCount;
    }

    cout << "Number of words => " << WordCount << endl;

    return 0;
}
while (cin >> Ch)
{   // we get in here if, and only if, the >> was successful
    if ((Ch == '\n') || (Ch == ' '))
    {
        ++WordCount;
        LetterCount = 0;
    }
    else
        ++LetterCount;
}

That's the safe, and common, way to rewrite your code safely and with minimal changes. 这是一种安全且通用的方法,可以安全地重写代码并且只需进行最少的更改。

(Your code is unusual, trying to scan all characters and count whitespace and newlines. I'll give a more general answer to a slightly different question - how to read in all the words.) (你的代码很不寻常,试图扫描所有字符并计算空格和换行符。我将对一个稍微不同的问题给出更一般的答案 - 如何阅读所有单词。)

The safest way to check if a stream is finished if if(stream) . 如果是if(stream) ,检查流是否已完成的最安全方法。 Beware of if(stream.good()) - it doesn't always work as expected and will sometimes quit too early. 请注意if(stream.good()) - 它并不总是按预期工作,有时会过早退出。 The last >> into a char will not take us to EOF, but the last >> into an int or string will take us to EOF. 最后一个>>进入一个char不会把我们带到EOF,但最后一个>>进入一个intstring 将把我们带到EOF。 This inconsistency can be confusing. 这种不一致可能令人困惑。 Therefore, it is not correct to use good() , or any other test that tests EOF. 因此,使用good()或测试EOF的任何其他测试是不正确的。

string word;
while(cin >> word) {
   ++word_count;
}

There is an important difference between if(cin) and if(cin.good()) . if(cin)if(cin.good())之间有一个重要的区别。 The former is the operator bool conversion . 前者是operator bool转换 Usually, in this context, you want to test: 通常,在此上下文中,您要测试:

"did the last extraction operation succeed or fail?" “最后一次提取操作成功还是失败?”

This is not the same as: 这是一样的:

"are we now at EOF?" “我们现在在EOF吗?”

After the last word has been read by cin >> word , the string is at EOF. 在通过cin >> word读取最后一个单词后,该字符串处于EOF。 But the word is still valid and contains the last word. 但这个word仍然有效,并包含最后一个字。

TLDR: The eof bit is not important. TLDR: eof位并不重要。 The bad bit is. bad是。 This tells us that the last extraction was a failure. 这告诉我们最后一次提取失败了。

The Counting 计数

The program counts newline and space characters as words. 该程序将换行符和空格字符计为单词。 In your file contents "this if fun!" 在你的文件内容“这有趣!” I see two spaces and no newline. 我看到两个空格,没有换行符。 This is consistent with the observed output indicating two words. 这与观察到的输出结果一致,表示两个单词。

Have you tried looking at your file with a hex editor or something similar to be sure of the exact contents? 您是否尝试使用十六进制编辑器或类似内容查看文件以确定具体内容?

You could also change your program to count one more word if the last character read in the loop was a letter. 如果循环中读取的最后一个字符是一个字母,您也可以更改您的程序以再计一个字。 This way you don't have to have newline terminated input files. 这样您就不必使用换行符终止输入文件。

Loop Termination 循环终止

I have no explanation for your loop termination issues. 我没有解释你的循环终止问题。 The while-condition looks fine to me. 那段时间对我来说很好看。 istream::get(char&) returns a stream reference. istream::get(char&)返回流引用。 In a while-condition, depending on the C++ level your compiler implements, operator bool or operator void* will be applied to the reference to indicate if further reading is possible. 在while-condition中,根据编译器实现的C ++级别, operator booloperator void*将应用于引用,以指示是否可以进一步读取。

Idiom 成语

The standard idiom for reading from a stream is 从流中读取的标准习语是

char c = 0;
while( cin >> c )
   process(c);

I do not deviate from it without serious reason. 没有严肃的理由,我不会偏离它。

In your case, the correct way to bail out of the loop is: 在你的情况下,摆脱循环的正确方法是:

while (cin.good()) {
  char Ch = cin.get();
  if (cin.good()) {
    // do something with Ch
  }
}

That said, there are probably better ways to do what you're trying to do. 也就是说,可能有更好的方法来做你想做的事情。

you input file is 你输入的文件是

this is fun!{EOF} 这很有趣!{EOF}

two spaces make WordCount increase to 2 and then EOF, exit loop! 两个空格使WordCount增加到2然后EOF,退出循环! if you add a new line, you input file is 如果添加新行,则输入文件为

this is fun!\n{EOF}

I took your program loaded it in to visual studio 2013, changed cin to an fstream object that opened a file called stuff.txt which contains the exact characters "This is fun!/n/r" and the program worked. 我把你的程序加载到visual studio 2013中,将cin更改为一个fstream对象,打开一个名为stuff.txt的文件,其中包含确切的字符“这很有趣!/ n / r”,程序运行正常。 As previous answers have indicated, be careful because if there's not a /n at the end of the text the program will miss the last word. 如前面的答案所示,要小心,因为如果文本末尾没有a / n,程序将错过最后一个单词。 However, I wasn't able to replicate the application hanging in an infinite loop. 但是,我无法复制悬挂在无限循环中的应用程序。 The code as written looks correct to me. 写的代码对我来说是正确的。

cin.get(char) returns a reference to an istream object which then has it's operator bool() called which returns false when any of the error bits are set. cin.get(char)返回对istream对象的引用,然后调用它的运算符bool(),当设置任何错误位时返回false。 There are some better ways to write this code to deal with other error conditions... but this code works for me. 有一些更好的方法来编写此代码来处理其他错误条件......但此代码适用于我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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