1

我不太确定我认为我的根本问题是如何工作的。我已经阅读了之前关于 while(cin>>x) 的几篇文章,但似乎没有什么能真正回答我的问题。我正在使用这个循环来读取一些文本数据:

while (cin >> x){
    searchText.push_back(x);
}

但后来在代码中,我试图用一个单词阅读:

cout << "Please enter your target word: ";
string targetWord;
cin >> targetWord;

但是上面的while循环/ eof似乎破坏了第二个代码片段(如果我将第二个代码片段移到上面它一切正常,但显然这不是我想要做的)

编辑 为了清楚起见,这是完整的代码:

int main()
{
// ask for the target word
//   cout << "Please enter your target word: ";
//   string targetWord;
//   cin >> targetWord;

   // ask for and read the search text
   cout <<  "Enter the complete search text, "
            "followed by end-of-file: ";
   vector<string> searchText;
   string x;
   while (cin >> x){
      searchText.push_back(x);
   }

   // check that some text was entered
   typedef vector<string>::size_type vec_sz;
   vec_sz size = searchText.size();
   if (size == 0){
      cout << endl <<   "You must enter some text. "
                        "Please try again." << endl;
      return 1;
   }

// ask for the target word
   cin.clear();
   cout << "";
   cout << "Please enter your target word: ";
   string targetWord;
   cin >> targetWord;


   int count = 0;
   for (int i=0; i<size; ++i){
      if (targetWord == searchText[i]){
      count++;
      }
   }

   cout  << "The target word [" << targetWord << "] was "
            "in the search text " << count << " times." << endl;

   return 0;
}

我只是想从用户那里获取一些文本......然后是一个搜索词,看看这个词在输入的文本中出现了多少次(很简单!)

我知道我可以做不同的事情,但这里的问题更多是关于如何在之前有 EOF 之后再次使用 cout/cin 流

4

5 回答 5

4

cin(或任何其他std::stream)到达文件末尾时,它会设置一个状态以指示这已经发生。

要重置此状态,您需要调用cin.clear();,这将清除所有“坏”状态,并确保流“正常”以再次使用。如果您正在读取文件并希望从头开始重新启动,这也适用。

编辑:我刚刚获取了上面发布的代码,并在我的机器上运行它,在顶部添加

#include <iostream>
#include <vector>

using namespace std;

以下是编译和运行:

$ g++ -Wall words.cpp 
words.cpp: In function ‘int main()’:
words.cpp:40:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
$ ./a.out
Enter the complete search text, followed by end-of-file: aa bb cc [CTRL-D]
Please enter your target word: aa
The target word [aa] was in the search text 1 times.

这是我期望看到的......

Edit2:为了完整性:使用的“成功率”cin.clear()将取决于实现。更可靠的解决方案是在程序的第一阶段使用不同的方式来标记单词流的结束。可以使用单个"."或“!” 或者其他一些不应该出现在“单词”中的东西 - 或者更长的东西,例如"&&@&&",但这使得输入和记住一个输入的内容是 15 页时变得很困难。

于 2013-07-01T12:24:12.820 回答
2

当执行离开循环

while (cin >> x){
    searchText.push_back(x);
}

这样做是因为“测试” 的“测试”cin已返回 false,换句话说,failbit和/或badbit已在流上设置。在这种情况下,任何进一步的从流中读取的尝试都将失败,即targetWord留空。

要使流再次可用,您必须通过调用重置错误标志cin.clear();

于 2013-07-01T12:27:30.500 回答
2

如果我们知道x第一个循环中的类型会有所帮助,但基本上:您阅读了所有可用的输入,然后尝试阅读更多内容,您会惊讶于它失败了。相反会让我感到惊讶。

真正的问题是:你想做什么?基本上, 的类型是什么x,并且——我假设你假设这cin是一个交互式设备,因为提示——你如何确定第一个输入已经完成?如果第一个循环由于“文件结尾”而结束(用户在 Unix 下输入 control-D,或在 Windows 下输入 control-Z),那么您就无法可靠地期望阅读更多内容。重置错误状态cin.clear() 可能会起作用;这将导致istream尝试从streambuf. 但它可能不会;在其下方有任意数量的层istream ,无论出于何种原因,它们可能已经记住了文件的结尾。所以你必须找到一些不同的方式来识别结局。

只是从变量的名称中猜测:如果您要读取单词列表,我会使用std::getline,列表末尾有一个空行。所以第一个循环会变成:

while ( std::getline( std::cin, x ) && x != "" ) {
    searchText.push_back( x );
}
if ( ! std::cin ) {
    //  Something really bad has happened...
}

或者,您可能希望在空白处拆分行,以允许每行多个单词(并忽略行中任何额外的空白:

std::string line;
while ( std::getline( std::cin, x ) && x != "" ) {
    std::istringstream l( line );
    while ( l >> x ) {
        searchText.push_back( x );
    }
}
if ( ! std::cin ) //  ...

即使x有其他类型,您也可能需要考虑这些方面的内容。

于 2013-07-01T13:50:39.297 回答
0

我使用了 cin.clear() 并且在我的 mac 设置上它似乎没有清除 EOF 但在 ubuntu 设置上它确实清除了流

苹果:

(Canopy 32bit) joes-imac:chap3 joe$ g++ --version
i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)

Ubuntu:

joe@joe-HPlaptop:~$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.

我很高兴接受这只是编译器差异并完成/关闭问题(真的是一个愚蠢的小家伙!)

不过感谢所有帮助(实际上是我的第一个 stackoverflow 问题!)

于 2013-07-01T17:08:48.560 回答
0

cin 在遇到结束行字符或换行符时将停止。因此,每次您输入内容并按 Enter 时,您都会提供一个“\n”。while(cin>>x){} 应该用于连续读取输入而没有 endline/'\n'。

于 2020-11-23T07:55:02.773 回答