C++ istream 运算符 >>

c++ istream operator >>

本文关键字:gt 运算符 istream C++      更新时间:2023-10-16

我的操作符有问题>>

istream& operator>> (istream& is, Matrix& M) {
    char first;
    is>>first;

    for(int i = 0;i<M.rows();i++) {
        for(int j = 0;j<M.cols();j++) {
            is>>M[i][j];
            cout<<M[i][j];
        }
        is>>first;
    }
    return is;
}

我想要istream操作符的大小,因为我想改变for循环,这样它们就不依赖于发送进来的矩阵,也就是说,如果你发送一个大小为1的矩阵和流[1 2 3 4; 4 5 6 7; 1 2 3 4],那么应该构造一个大小为(3*4)的新矩阵。这样我就可以使用赋值运算符将其赋值给矩阵m。

也就是说,流的形式是"[ 1 2 3; 2 3 4; 4 5 6]"和;表示新行。我想知道有多少行和颜色

你可以像这样得到所有的行:

vector<string> rows;
string line;
is.ignore(INT_MAX, '['); // ignores all characters until it passes a [
while (std::getline(is, line, ';'))
    rows.push_back(line); // put each row in rows
rows.back().erase(rows.back().find(']')); // erase the ending ]

现在你有rows中的每一行字符串,然后

for (size_t i = 0; i < rows.size(); ++i) {
    vector<int> items;
    istringstream strstm(rows[i]);
    std::copy(istream_iterator<int>(strstm), istream_iterator<int>(), back_inserter(items));
    // now items is full of the entries, resize the matrix to hold items.size()
    // many items and insert each one into it, or whatever
}

首先,当然,您需要指定比您更严格的东西有。您应该如何处理"[ 11 12 13; 21 22; 31 32 33 ]"之类的东西,例如:为缺失的值或集合插入0.0failbit ?

除此之外,使用std::vector收集输入将使事情变成a更容易一些。例如:

template< typename T >
char getRow( std::istream& source, std::vector<T>& dest )
{
    dest.clear();
    char separator;
    source >> separator;
    while ( source && separator != ';' && separator != ']' ) {
        source.unget();
        T tmp;
        source >> tmp;
        if ( source ) {
            dest.push_back( tmp );
            source >> separator;
        }
    }
    if ( source && dest.empty() ) {
        dest.setstate( std::ios_base::failbit );
    }
    return source ? separator : '';
}
template< typename T >
char getFirstRow( std::istream& source,
                  std::vector<std::vector<T> >& dest )
{
    dest.clear();
    std::vector<T> row;
    char separator = getRow( source, row );
    if ( source ) {
        if ( row.empty() ) {
            dest.setstate( std::ios_base::failbit );
        } else {
            dest.push_back( row );
        }
    }
    return source ? separator : '';
}
template< typename T >
char getFollowingRow( std::istream& source,
                 std::vector<std::vector<T> >& dest )
{
    std::vector<T> row;
    char separator = getRow( source, row );
    if ( source ) {
        if ( row.size() != dest.front().size() ) {
            dest.setstate( std::ios_base::failbit ) ;
        } else {
            dest.push_back( row );
        }
    }
    return source ? separator : '';
}
template< typename T >
std::istream&
operator>>( std::istream& source, Matrix<T>& dest )
{
    char separator;
    source >> separator;
    if ( separator != '[' ) {
        source.setstate( std::ios_base::failbit );
    } else {
        std::vector<std::vector<T> > results;
        separator = getFirstRow( source, results );
        while ( separator == ';' ) {
            separator = getFollowingRow( source, results );
        }
        if ( separator != ']' ) {
            source.setstate( std::ios_base::failbit );
        }
        if ( source ) {
            dest.assign( results );
        }
    }
    return source;
}

当然,这意味着Matrix<T>::assign函数必须能够设置尺寸。为了可用,Matrix<T>需要一个默认值构造函数,它可能将实际构造"推迟"到Matrix<T>::assign .

也:我们在上面的可能性有限用于在iostreams中报告错误。特别是,我们真的很想区分像"[11 12 13; 21"这样的输入和什么都没有(真正的结束)文件条件)。但是我们试图读取"21"之后的分隔符会设置eofbit,我们对此无能为力。(实际上,we 可以创建一个新的状态词,使用std::ios_base::xalloc(),当且仅当在开始时读取'['失败时设置它eofbit集。但这需要一种非常不标准的检查方式对于客户端代码中的错误,这将反过来创建一个无尽的流)

最后,两个元注释:如果这看起来很复杂…它是。输入几乎总是很复杂,因为有各种各样的错误你必须检查的条件。第二,注意函数的使用保持每个单独的操作(某种程度上)简单。这是经常发生的初学者不像这样把事情分解是错误的几乎总是糟糕的编程,例如,在函数,除了将数学算法应用于Matrix。在这种情况下,解析不是数学算法,并且您希望将每行的处理与总体处理分开;在这种情况下,分离第一行的处理也很有用与其他的不同,因为错误情况是不同的。(第一行可以有任何大于0的长度,后面的行必须有相同的长度)

问题是流提取操作符需要一个已经构造的对象,它可以修改这个对象。你必须调整你的矩阵类,以便它可以动态调整大小。

不可能确定" istream操作符的大小",因为它是流,当您读取第一个矩阵元素时,没有人可以保证最后一个元素已经存在。您应该首先读取整个字符串,然后解析它并提取有关输入矩阵大小的信息。之后,您可以通过stringstream向它提供这个字符串来使用您的代码。当然,你必须能够动态地改变矩阵的大小。