解析格式化输入时分割单词的问题

时间:2013-09-04 14:32:14

标签: c++ string parsing io formatting

#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
int main(int argc, char *argv[])
{
    std::vector<std::string> vec;
    std::string line;
    std::ifstream in(argv[1]);
    while(!in.eof()) {
        std::getline(in,line);
        vec.push_back(line);
    }
    std::istringstream is;
    line = "";
    for(auto a:vec) {
        for(auto i = a.begin(); i != a.end(); i++) {
            if(!(isspace(*i) | ispunct(*i)))
                line += *i;
            else {
                is.str(line);
                std::cout << is.str() << std::endl;
                line = "";
            }
        }
    }
    std::cout << is.str() << std::endl;
    return 0;
}

我编写了一个程序,它接受一个文件并将每一行放在一个字符串向量中。然后从元素中一次读取一个单词。

当我从矢量中读取时,我在指定新行时遇到问题。我的输出连接一行的结尾和下一行的开头。如何指定有新行?

我正在阅读的文件内容:

Math 3 2
Math 4 3
Math 5 4
Phys 3 1
Math 3 1
Comp 3 2

我得到的输出:

Math
3
2Math
4
3Math
5
4Phys
3
1Math
3
1Comp
3
3

EDIT ::

为了澄清,矢量元素是正确构造的。如果我从for(auto a:vec)打印输入,它会像文件一样逐行给我。当我尝试从向量中的每个字符构建单词时。我问我该怎么做才能指明有一个新行,以便

line += a[i] 

在点击一行结尾时不会继续添加到行。

3 个答案:

答案 0 :(得分:2)

不要做

while (!in.eof()) { ... }

它不会像你期望的那样工作。

取而代之的是

while (std::getline(...)) { ... }

原因是因为eof标志未设置,直到您在文件结束时实际尝试读取为止。这意味着您将循环一次到多次,尝试读取不存在的行,然后将其添加到向量中。


还有另一种分离单词&#34;在空间边界上,使用std::istringstream和普通输入操作符>>

std::istringstream is{a};

std::string word;
while (is >> word)
{
    // Do something with `word`
}

答案 1 :(得分:1)

这里的实际问题是代码逻辑错误。这是打印输出时你正在做的伪代码:

for every line:
    for every character in the line:
        if it is alphanumerical character
            then add it to the word
        else
            print the so-far built word

现在查看行Math 4 3〜&gt;打印单词“4”后,此代码会在行中添加字符'3',但不会将其作为单词打印,因此3是下一行单词的开头。

另请注意,您的代码比必要的复杂得多。它可能看起来像这样:

std::string word;
for (size_t i = 0; i < vec.size(); ++i) {
    std::istringstream lineStream(vec[i]);
    while (lineStream >> word)
        std::cout << word << std::endl;
}

但是如果您想保留原始代码,可以采取以下措施来解决此问题:

line = "";
for(auto a:vec) {
    for(auto i = a.begin(); i != a.end(); i++) {
        if (isalnum(*i))
            line += *i;
        else {
            std::cout << line << std::endl;
            line = "";
        }
    }

    // before we start processing the next element...
    // in case there's another line to be printed:
    if (!line.empty()) {
        // print the line and reset the variable:
        std::cout << line << std::endl;
        line = "";
    }
}

答案 2 :(得分:0)

你也可以使用这样的矢量逐行阅读;

矢量定义;

    struct VectorName {
       std::string str;
       float num1;
       float num2;
};

std::vector <VectorName> smthVector_;

使用功能

   VectorName vector;
   std::string str;
   char buf_1[50];
   while(std::getline(in, str))
   {
       if(sscanf(str.c_str(), "%s %f %f", buf_1, &vector.num1, &vector.num2) == 3)
       {
           vector.str = buf_1;
           smthVector_push_back(vector);
       }
        else
            std::cout << "No param in string  " << str << std::endl;
   }