0

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

hss cscf "serving cscf" 32.5 ims 112.134

(注:当一个对象的变量需要多字串时,我用“....”,单字串不带引号)

如何使用 ifstream 读取它?(我搜索了谷歌但没有找到。)

我尝试使用 getline 阅读整行,但在确定是单个单词还是多单词输入时再次卡住了!

请为此提出一些建议。

4

2 回答 2

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 或继续将单词添加到临时字符串。

总而言之,这会在临时字符串中保留引号中的单词,并直接将单个单词添加到向量中。当引号结束时,它也会将临时字符串添加到向量中。

于 2013-08-09T12:50:01.843 回答
1

由于您正在尝试解析来自文件流的输入,并且您正在处理多个单词的可能性,如果您希望使用通用支持和完全可定制的支持 - 即您想要解析任何类型的输入,那么你需要正则表达式

您可以使用 C++11 的正则表达式,但gcc 目前不支持

因此,一种解决方案是使用适用于标准 c++98、c++03 和 c++0x 的 boost C++ 库:

#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

至于为什么可怕的长正则表达式,如果您希望使用正则表达式支持完整的十进制解析,那么上面的内容将适用于以下字符串:

"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

于 2013-08-09T12:53:04.453 回答