【问题标题】:Overload stream operator for nested template C++ STL嵌套模板 C++ STL 的重载流运算符
【发布时间】:2011-11-15 10:30:51
【问题描述】:

我有一个数据文件,它是单行,由一系列嵌套的双精度组成,例如。

[[0.127279,0.763675,0.636396],[0.254558,0.890955,0.636396],
[0.127279,0.636396,0.763675],[0.254558,0.763675,0.763675],
[0.381838,0.890955,0.763675],[0.127279,0.509117,0.890955],
[0.254558,0.636396,0.890955],[0.509117,0.890955,0.890955]]

我希望能够使用跨 A 的内部类型模板化的流运算符将其读入 STL vector<vector<double> >

vector<vector<double> > A;
FIN >> A;

当向量没有嵌套时,我已经找到了一种方法,即。一个简单的vector&lt;T&gt; 这样:

template <class T>
istream& operator>>(istream& s, vector<T> &A){
  T x;
  string token; char blank;

  s >> blank; // Gobble the first '['
  while( getline(s, token, ',') ) {
   istringstream input(token);
   input >> x;
   A.push_back(x);
  }
  s >> blank; // Gobble the last ']'
  return s;
}

但我对istream&amp; operator&gt;&gt;(istream&amp; s, vector&lt;vector&lt;T&gt; &gt;&amp;A) 部分有疑问,因为我似乎无法正确捕捉到内部]。我确信 Boost 有办法做到这一点,但我希望看到 STL 的解决方案用于教学目的。

注意:我知道为vector&lt;T&gt; 重载流运算符可能会产生深远的不良后果,并且实现应该包含在它自己的类中 - 我使用上面的这个例子是为了澄清问题。

编辑: 我希望该方法足够健壮,可以处理一个输入数组,其大小(和内部数组)的大小事先知道,而是从读取流中推断出来的。

【问题讨论】:

    标签: c++ templates stream operator-overloading


    【解决方案1】:

    实际上,当T 时,您希望对两者使用相同功能的代码的问题是:

    • vector&lt;double&gt;
    • double

    但是需要将数据读入vectordouble的逻辑略有不同。所以你不能这样做,至少不能用那个简单的逻辑:

    我更喜欢编写两个函数,分别处理这两种情况。毕竟,即使在您的情况下,编译器也会为T 的每个值生成两个不同的函数。

    template <class T>
    istream& operator>>(istream& s, vector<T> &A)
    {
      T x;
      string token; char blank;
    
      s >> blank; // Gobble the first '['
      while( getline(s, token, ',') ) 
      {
       istringstream input(token);
       input >> x;
       A.push_back(x);
      }
    // s >> blank; // Gobble the last ']'
      return s;
    }
    
    template <class T>
    istream& operator>>(istream& s, vector<vector<T>> &A)
    {
      vector<T> x;
      string token; 
      char blank;
    
      s >> blank; // Gobble the first '['
      while( getline(s, token, ']') ) 
      {
       istringstream input(token);
       input >> x;
       s >> blank; //read , after [...]
       A.push_back(x);
       x.clear();
      }
      s >> blank; // Gobble the last ']'
      return s;
    }
    

    测试代码:

    int main() {
            vector<vector<double>> A;       
            cin >> A;
            for(size_t i = 0 ;i < A.size(); ++i)
            {
                for(size_t j = 0 ; j < A[i].size(); ++j)
                     cout << A[i][j] <<"   ";
                cout << endl;
            }
            return 0;
    }
    

    输入:

    [[1,2,3],[4,5,6],
    [7,8,9],[10,11,12],
    [13,14,15],[16,17,18],
    [19,20,21],[22,23,24]]
    

    输出:

    1   2   3   
    4   5   6   
    7   8   9   
    10   11   12   
    13   14   15   
    16   17   18   
    19   20   21   
    22   23   24 
    

    在线演示:http://ideone.com/iBbmw

    【讨论】:

    • 这是有道理的,感谢您在示例中使用我自己的代码,它明确地回答了问题而没有引入任何临时细节。看着它,它似乎应该能够处理任意级别的嵌套向量!
    • @Hooked: it should be able to handle any an arbitrary level of nested vectors!... 是的,我想是的。顺便说一句,你想看看提升解决方案吗?
    • 为了我自己的启迪,绝对!由于 Boost 并不总是作为标准配置安装,因此明确询问了 STL 的问题。
    【解决方案2】:

    在您的特定示例中非常简单。

    • 将整行读入字符串。
    • 将所有 [ , ] 和 , 替换为空白字符。
    • 用空格替换字符串创建一个简单的字符串流。

    现在你可以有一个简单的循环

    double x;
    while( stringstreamp >> x )
    {
    }
    

    以及在读取三个双精度后将它们插入新数组的一些特殊逻辑。

    【讨论】:

    • 这适用于上面的示例,但它似乎相当脆弱。如果内部容器的大小发生变化,该方法将失败。此外,如果每个内部容器的大小不同(这当然可能是向量的向量),那么这种方法将无法提前知道何时开始新数组。
    【解决方案3】:

    几年后,我在这里为同样的问题苦苦挣扎。

    根据您的贡献,我开发了原始模板的修改版本。这个能够解析多维数组,即使它们分布在多行中。

    template <class T>
    istream& operator>>(istream& s, vector<T> &A){
      while(true){
        T x;
        char c = s.peek();
    
        if( c == '[' || c == ','){ 
            s.ignore();
            if(s >> x) A.push_back(x);
            else throw invalid_argument("Bad, bad JS array!");
            continue;
        }
    
        if( c == ']') {
            s.ignore();
            return s;
        }
    
        /* Ignore line-break */
        s.ignore();     
      }
      return s;
    }
    

    希望这对某人有用。

    【讨论】:

      猜你喜欢
      • 2013-09-20
      • 2018-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多