【问题标题】:How to use istringstream with more than one delimiter如何使用带有多个分隔符的 istringstream
【发布时间】:2012-09-20 03:12:52
【问题描述】:

您好,我想问一下如何从字符串中解析多个浮点数,用“/”和空格分隔。

文件中的文本格式为“f 1/1/1 2/2/2 3/3/3 4/4/4” 我需要将这行文本中的每个整数解析成几个 int 变量,然后用这些变量构造一个“face”对象(见下文)。

int a(0),b(0),c(0),d(0),e(0);
int t[4]={0,0,0,0};
//parsing code goes here
faces.push_back(new face(b,a,c,d,e,t[0],t[1],t[2],t[3],currentMaterial));

我可以使用 sscanf() 来做到这一点,但我的 uni 讲师已经警告我不要这样做,所以我正在寻找替代方案。我也不允许使用其他 3rd 方库,包括 boost。

已经提到了正则表达式和使用 stringstream() 进行解析,但我对两者都不太了解,希望得到一些建议。

【问题讨论】:

  • 您想将 12 个整数(四组三个,每组三个)解析为九个变量,五个独立变量和四个数组?这对any有什么意义?
  • 虽然这个问题最初看起来不像是重复的,但您似乎想要做的已经包含在之前的答案中:stackoverflow.com/a/2909187/179910

标签: c++ parsing


【解决方案1】:

如果您使用 std::ifstream 读取文件,则首先不需要 std::istringstream(尽管使用两者非常相似,因为它们继承自同一个基类)。以下是使用 std::ifstream 的方法:

ifstream ifs("Your file.txt");
vector<int> numbers;

while (ifs)
{
    while (ifs.peek() == ' ' || ifs.peek() == '/')
        ifs.get();

    int number;
    if (ifs >> number)
        numbers.push_back(number);
}

【讨论】:

    【解决方案2】:

    考虑到您的示例f 1/1/1 2/2/2 3/3/3 4/4/4,您需要阅读的是:char int char int char int int char int char int int char int char int

    为此:

    istringstream is(str);

    char f, c;
    int d[12];
    
    bool success = (is >> f) && (f == 'f') 
                && (is >> d[0])  && (is >> c) && (c == '/') 
                && (is >> d[1])  && (is >> c) && (c == '/') && 
                .....  && (is >> d[11]);
    

    【讨论】:

      【解决方案3】:

      我会这样做的方法是 change the interpretation of space 包含其他分隔符。如果我想得到幻想,我会使用不同的 std::ostream 对象,每个对象都设置一个 std::ctype&lt;char&gt; 方面来处理一个分隔符,并使用一个共享的 std::streambuf

      如果您想明确使用分隔符,您可以改为使用合适的操纵器来跳过分隔符,或者如果没有分隔符,则表明失败:

      template <char Sep>
      std::istream& sep(std::istream& in) {
          if ((in >> std::ws).peek() != std::to_int_type(Sep)) {
              in.setstate(std::ios_base::failbit);
          }
          else {
              in.ignore();
          }
          return in;
      }
      
      std::istream& (* const slash)(std::istream&) = Sep<'/'>;
      

      代码未经测试并在移动设备上输入,即可能包含小错误。你会像这样读取数据:

      if (in >> v1 >> v2 >> slash >> v3 /*...*/) {
        deal_with_input(v1, v2, v3);
      }
      

      注意:以上使用假设输入为

      1.0 2.0/3.0
      

      即第一个值后有一个空格,第二个值后有一个斜线。

      【讨论】:

        【解决方案4】:

        你可以使用 boost::split。

        示例是:

        string line("test\ttest2\ttest3");
        vector<string> strs;
        boost::split(strs,line,boost::is_any_of("\t"));
        
        cout << "* size of the vector: " << strs.size() << endl;    
        for (size_t i = 0; i < strs.size(); i++)
            cout << strs[i] << endl;
        

        更多信息在这里:

        http://www.boost.org/doc/libs/1_51_0/doc/html/string_algo.html

        还有相关的:

        Splitting the string using boost::algorithm::split

        【讨论】:

        • 我很抱歉。我被告知要避免使用任何非标准库(因为我的讲师不会拥有它们),这让我恍然大悟。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-25
        • 1970-01-01
        • 2019-11-03
        • 1970-01-01
        • 2014-10-16
        相关资源
        最近更新 更多