嵌套模板C ++ STL的重载流运算符

时间:2011-09-12 15:02:43

标签: c++ templates stream operator-overloading

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

[[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]]

我希望能够使用流操作符将其读入STL vector<vector<double> >,该操作符模仿内部类型A:

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

当矢量未嵌套时,我已经想出了一种方法,即。一个简单的vector<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;
}

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

注意:我知道重载vector<T>的流操作符可能会产生深远的不良后果,并且实现应该包含在它自己的类中 - 我正在使用上面的这个例子澄清这个问题。

修改 我希望这个方法足够健壮,能够处理一个输入数组,该数组的大小(和内部数组)大小事先已知 ,但是从读取流中推断出来。

3 个答案:

答案 0 :(得分:2)

实际上,当Tvector<double>时,您希望对两者使用相同功能的代码存在问题:

  • double
  • T

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

我更愿意编写两个函数,分别处理两个案例。毕竟,即使在您的情况下,编译器也会为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 

输出:

{{1}}

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

答案 1 :(得分:1)

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

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

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

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

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

答案 2 :(得分:1)

几年后,我在这里遇到同样的问题。

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

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;
}

希望这对某人有用。