从文件中读取多个单词

时间:2013-08-09 11:22:00

标签: c++ file ifstream

我有一个输入文件。它包含许多输入值。 如果一个对象的输入如下:

hss cscf "serving cscf" 32.5 ims 112.134

(注意:当一个对象的变量需要多字符串时,我使用“....”,对于单个字符串,它没有引号)

如何使用ifstream阅读? (我搜索谷歌但没找到。)

我尝试使用getline读取整行,但在找出它是单个字还是多字输入时再次卡住了!

请为此提出一些建议。

2 个答案:

答案 0 :(得分:1)

希望这个程序可以帮助你

int main()
{
    fstream fstr;
    fstr.open("abc.txt",ios::in);
    string str;
    vector<string> Vec;
    while(getline(fstr,str))
    {
        char* pch;
        bool flag = false;
        string strTmp;
        int counter=0;
        pch = strtok (const_cast<char*>(str.c_str())," ");
        while (pch != NULL)
        {
            //this "is a" sample
            if(pch[0]=='\"')
            {
                flag = true;
                strTmp = strTmp + " " + string(pch).substr(1,strlen(pch)-1);
            }
            else
            {
                if(flag==true)
                {
                    if(pch[strlen(pch)-1]=='\"')
                    {
                        flag=false;
                        strTmp = strTmp + " " + string(pch).substr(0,strlen(pch)-1);
                        Vec.push_back(strTmp);
                    }
                    else
                    {
                        strTmp = strTmp + " " + pch;
                    }
                }
                else
                {
                    Vec.push_back(pch);
                }
            }
            pch = strtok(NULL," ");
        }

    }
    for(auto itr = Vec.begin();itr!=Vec.end();itr++)
        {
            cout<<*itr<<endl;
        }
        getchar();
}

只提供摘要

  1. 使用空格作为分隔符,使用strtok取出每一行并获取单词。(这里,即使引号中的单词也会被提取为单个单词而不将它们视为多个单词。

  2. 对于每个提取的单词,检查它是否以引号开头。如果不是,则将其添加到向量中,否则将其添加到临时字符串并启用标记。

  3. 现在,检查每个单词是否以引号结尾,以及是否设置了标志。如果两者都满足,则将整个临时字符串添加到vecor或继续将字添加到临时字符串。

  4. 总结一下,这会在temp字符串中引用单词并直接将单个单词添加到vector中。当引号结束时,它也会将临时字符串添加到向量中。

答案 1 :(得分:1)

由于您正在尝试解析文件流中的输入,并且您正在处理多个单词的可能性,如果您希望使用通用支持并且可以完全自定义 - 即您要解析任何类型输入,然后你需要Regular Expressions

您可以使用C ++ 11的正则表达式,但目前在gcc中使用isn't supported

所以,一个解决方案是使用boost C ++库,它应该适用于标准c ++ 98,c ++ 03和c ++ 0x:

#include <string>
#include <iostream>
#include <cstdlib>
#include <boost/regex.hpp>
using namespace std;

int main() {
  string text = "hss cscf \"serving\" 32.5 ims 112.134";

  boost::regex e("(\\w+)\\s(\\w+)\\s\"(\\w+\\s?)+\"\\s([0-9]+(\\.[0-9][0-9]?)?)\\s(\\w+)\\s([0-9]+(\\.[0-9][0-9]?)?)");

  boost::sregex_token_iterator iter(text.begin(), text.end(), e, 0);
  boost::sregex_token_iterator end;

  for(; iter != end; ++iter) {
    std::cout << *iter << std::endl;
  }

  return 0;
}

您可以使用gcc(我使用gcc-4.7.2)通过以下方式编译它:

g++ {filename} -std={language version} -I{your boost install location} -L{your boost library location} -o {output filename} {your boost library location}/libboost_regex.a

至于为什么这个可怕的长正则表达式,如果你想支持完整的decimal parsing using a regex,那么上面的代码将适用于以下字符串:

"hss cscf \"serving\" 32.5 ims 112.134"
"hss cscf \"serving more than one\" 32.5 ims 112.134"
"hss cscf \"serving\" 32 ims 112"

参考文献:

提升正则表达式:http://www.solarix.ru/for_developers/api/regex-en.html