在字符串流中使用 .clear() (C++)

Using .clear() in string streams (C++)

这是我教科书中关于使用/实现字符串流的示例:

int main() {
   istringstream inSS;       // Input string stream
   string lineString;        // Holds line of text
   string firstName;         // First name
   string lastName;          // Last name
   int    userAge = 0;       // Age
   bool   inputDone = false; // Flag to indicate next iteration

   // Prompt user for input
   cout << "Enter \"firstname lastname age\" on each line" << endl;
   cout << "(\"Exit\" as firstname exits)." << endl << endl;

   // Grab data as long as "Exit" is not entered
   while (!inputDone) {

      // Entire line into lineString
      getline(cin, lineString);

      // Copies to inSS's string buffer
      inSS.clear();                        // <-- HELLO RIGHT HERE
      inSS.str(lineString);

      // Now process the line
      inSS >> firstName;

      // Output parsed values
      if (firstName == "Exit") {
         cout << "   Exiting." << endl;

         inputDone = true;
      }
      else {
         inSS >> lastName;
         inSS >> userAge;

         cout << "   First name: " << firstName << endl;
         cout << "   Last  name: " << lastName << endl;
         cout << "   Age:        " << userAge   << endl;
         cout << endl;
      }
   }

   return 0;
}

我不明白为什么 inSS.clear(); 是必要的。书中指出:

"The statement inSS.clear(); is necessary to reset the state of the stream so that subsequent extractions start from the beginning; the clear resets the stream's state."

当它所做的只是“set a new value for the stream's internal error state flags.”时,.clear() 如何导致下一次提取从头开始?

如果我从上面的示例中删除 inSS.clear() 语句,它将不起作用。例如: 输入:

joe shmo 23
alex caruso 21

输出:

   First name: joe
   Last  name: shmo
   Age:        23

   First name: joe
   Last  name: shmo
   Age:        23

这是我预期删除语句 inSS.clear() 后会发生的情况。我的理解显然有问题,请指正:

输入:

joe shmo 23
alex caruso 21

getline(cin, lineString);cin 流中提取 joe shmo 23lineString 并在最后丢弃 /n

inSS.str(lineString); 将字符串流缓冲区初始化为字符串 lineString

inSS >> firstName; 将提取 joe

inSS >> lastName; 将提取 shmo

inSS >> userAge; 将提取 23

inSS 留空并准备好处理下一个输入。

根据how to reuse stringstream

If you don't call clear(), the flags of the stream (like eof) wont be reset, resulting in surprising behaviour

这是什么行为? 那么,实际发生了什么以及为什么需要 .clear()?

在您第一次执行 inSS >> userAge; 之后,这涉及尝试读取字符串的末尾,因为它必须查看在年龄的最后一位数字之后是否还有另一位数字。

这意味着在流上设置了 eofbit,这意味着由于流处于文件结束状态,未来的提取将失败。 clear() 调用清除此状态。

您应该会发现,如果您第一次提供的输入字符串可以提取 userAge 而不会结束(例如 joe shmo 23 foo),那么 clear() 调用就没有必要了(但这仍然是个好习惯)。

顺便说一句,最好在 inSS >> userAge 之后测试 if (!inSS) 以检查错误,否则你会继续以变量已经具有的任何值的形式输出 "garbage" 值,因为读取尝试失败。