使用字符串流解析字符串时,它会提取新的行字符

时间:2015-02-08 23:59:35

标签: c++ string performance parsing stringstream

程序说明:程序必须读入可变数量的单词,直到指定了标记值("#"在这种情况下)。它将单词存储在矢量数组中。

问题:我使用getline读取字符串并使用stringstream解析字符串。我的问题是,字符串流不会吞掉每一行末尾的新行字符,而是提取它。

我想到的一些解决方案是通过创建子集或检查下一个提取的单词是否是新行字符来切断最后一个字符,但我觉得有一个更好的成本效益解决方案,例如更改我的条件环路。

我已经包含了可以重现问题的整体代码的最小化版本。

#include <iostream>
#include <sstream>
#include <string>
using namespace std;

int main()
{
   const int MAX_LIST_SIZE = 1000;
   string str;
   string list[MAX_LIST_SIZE];
   int numWords = 0;

   // program starts here
   getline(cin, str);          // read innput
   stringstream parse(str);    // use stringstream to parse input

   while(str != "#")           // read in until sentinel value
   {
       while(!parse.fail())    // until all words are extracted from the line    
       {
           parse >> list[numWords];    // store words
           numWords++;
       }
       getline(cin,str);      // get next line
       parse.clear();
       parse.str(str);
   }

   // print number of words
   cout << "Number of words : " << numWords << endl;
}

一组将产生问题的测试输入数据

输入:

apples oranges mangos
bananas 
pineapples strawberries

输出:

Number of words : 9

预期输出:

Number of words : 6

如果能以有效的方式处理这个问题,我将不胜感激。

2 个答案:

答案 0 :(得分:2)

解析流的逻辑不太正确。 fail()仅在 >>操作失败后才变为真,因此每次都会进行额外的增量。例如:

   while(!parse.fail())  
   {
       parse >> list[numWords];    // fails
       numWords++;                 // increment numWords anyway
   }                           // THEN check !fail(), but we incremented already!

所有这些操作都有返回,您应该检查以避免此问题:

while (getline(cin, str)) { // fails if no more lines in cin
    if (str != "#") {       // doesn't need to be a while
        stringstream parse(str);
        while (parse >> list[numWords]) { // fails if no more words
            ++numWords;                   // *only* increment if we got one!
        }
    }
}

更好的方法是根本不使用数组作为单词列表:

std::vector<std::string> words;

可以在内循环中使用:

std::string temp;
while (parse >> temp) {
    words.push_back(temp);
}

答案 1 :(得分:0)

numwords的增量比你想要在每一行结束时多一次。使用std :: vector&lt; std :: string&gt;为你的清单。然后你可以使用list.size()。