c ++ istream operator>>

时间:2011-12-22 08:50:26

标签: c++ matrix istream ostream

我的运营商有一些问题>>

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循环,以便它们不依赖于发送的Matrix,即你是否发送大小为1的矩阵和流{{ 1}}然后应该构造一个大小为(3 * 4)的新矩阵。这样我就可以使用赋值运算符将其赋值给矩阵M.

换句话说,流的格式为[1 2 3 4; 4 5 6 7; 1 2 3 4]和;意味着新的一行。 我想知道有多少行和列。

4 个答案:

答案 0 :(得分:2)

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

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
}

答案 1 :(得分:1)

首先,当然,您需要指定比您更严格的事情 有。您应该对"[ 11 12 13; 21 22; 31 32 33 ]"之类的事情做些什么,例如:为缺失值插入0.0或设置 failbit

除此之外,使用std::vector收集输入将使事情成为现实 有点容易。如下所示:

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 : '\0';
}

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 : '\0';
}

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 : '\0';
}

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>需要默认值 构造函数,可能&#34;推迟&#34;实际建设,直到 Matrix<T>::assign

另外:由于有限的可能性,我们在上述方面有所限制 用于iostreams中的错误报告。特别是,我们真的很喜欢 区分像"[11 12 13; 21"这样的输入和没有(真正的结束) 文件条件)。但我们尝试在"21"之后读取分隔符 将设置eofbit,我们无能为力。 (其实, 我们可以使用std::ios_base::xalloc()创建新的状态字, 当且仅当在开始时读取'['失败时才设置它 {{1套。但这需要一种非常不标准的检查方式 对于客户端代码中的错误,这反过来会产生无穷无尽的流 维修问题。)

最后,两个元评论:如果这看起来很复杂......那就是。输入 几乎总是很复杂,因为所有的各种错误 你必须检查的条件。第二,注意函数的使用 保持每个单独的操作(某种程度)简单。这是一个常见的 初学者的错误就是不要像这样把事情搞得一团糟 几乎总是糟糕的编程,例如,在a中有一个嵌套循环 函数,除了将数学算法应用于类似的东西 eofbit。在这种情况下,解析不是数学算法,而且 你想把每一行的处理与整体处理分开; 在这种情况下,它对分离第一行的处理也很有用 来自其他人,因为错误案例不同。 (第一排 可以具有大于0的任何长度,以后的行必须具有相同的长度 如前一行。)

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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