оператор c ++ istream >> - PullRequest
       79

оператор c ++ istream >>

0 голосов
/ 22 декабря 2011

У меня возникла проблема с оператором >>

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).так что я могу использовать оператор присваивания для присвоения его матрице М.

Другими словами, поток находится в форме "[ 1 2 3; 2 3 4; 4 5 6]" и;означает новый ряд.Я хочу знать, сколько строк и столбцов.

Ответы [ 4 ]

2 голосов
/ 22 декабря 2011

Вы можете получить все строки следующим образом:

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 голос
/ 22 декабря 2011

Во-первых, конечно, вам нужно будет указать более строгие правила, чем вы. иметь. Что вы должны сделать с чем-то вроде "[ 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> требуется значение по умолчанию конструктор, который, вероятно, "откладывает" фактическую конструкцию до Matrix<T>::assign.

Кроме того: мы несколько ограничены в вышеупомянутых ограниченных возможностях для сообщения об ошибках в iostreams. В частности, нам бы очень хотелось различать ввод как "[11 12 13; 21" и ничего (истинный конец состояния файла). Но наши попытки прочитать разделитель после "21" установит eofbit, и мы ничего не можем с этим поделать. (На самом деле, мы могли бы создать новое слово состояния, используя std::ios_base::xalloc(), установить его тогда и только тогда, когда чтение '[' в начале завершится неудачно с eofbit установлено. Но это потребует очень нестандартного способа проверки за ошибки в клиентском коде, которые, в свою очередь, создали бы бесконечный поток проблем с обслуживанием.)

Наконец, два мета-комментария: если это кажется сложным ... это так. вход почти всегда сложно, из-за всех различных ошибок условия вы должны проверить. И во-вторых, обратите внимание на использование функций для Сделайте каждую отдельную операцию (своего рода) простой. Это частый ошибка новичков не сломать вещи как это - это почти всегда плохое программирование, например, чтобы иметь вложенный цикл в функция, за исключением случаев применения математических алгоритмов к таким вещам, как Matrix. В этом случае разбор не математический алгоритм, а вы хотите отделить обработку каждой строки от общей обработки; в этом случае также полезно разделить обработку первого ряда от других, так как случаи ошибок разные. (Первый ряд может иметь любую длину больше 0, более поздние строки должны иметь одинаковую длину как предыдущие строки.)

0 голосов
/ 22 декабря 2011

Невозможно определить «размер оператора istream», поскольку это, ну, в общем, поток, и когда вы читаете первый элемент матрицы, никто не может гарантировать, что последний элемент уже существует. Сначала вы должны прочитать всю строку, а затем проанализировать ее и извлечь информацию о размере входной матрицы. После этого вы можете использовать свой код, передав ему эту строку через stringstream. Конечно, вы должны иметь возможность динамически изменять размер матрицы.

0 голосов
/ 22 декабря 2011

Проблема в том, что оператору извлечения потока требуется уже созданный объект, который он может изменить.Вы должны адаптировать свой матричный класс так, чтобы он мог динамически изменяться.

...