0

オペレーターに問題があります>>

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

送信されたマトリックスに依存しないようにforループを変更したいので、istreamオペレーターのサイズを変更したいのです。つまり、サイズ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]"あり、; 新しい行を意味します。行と列がいくつあるか知りたいです。

4

4 に答える 4

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
}
于 2011-12-22T09:01:21.100 に答える
1

まず、もちろん、よりも少し厳密に指定する必要があります。"[ 11 12 13; 21 22; 31 32 33 ]"たとえば0.0、欠落している値に対して a を挿入したり、 を設定したり する場合はどうすればよいでしょ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()の の読み取りがset'['で失敗した 場合にのみそれを設定できますeofbit。しかし、これには、クライアント コードのエラーをチェックするための非常に非標準的な方法が必要になります。その結果、メンテナンスの問題が際限なく発生します。)

最後に、2 つのメタコメントです。さまざまなエラー条件をチェックする必要があるため、ほとんどの場合、入力は複雑です。次に、関数を使用して、個々の操作 (一種) をシンプルに保つことに注意してください。初心者がこのように物事を分解しないことはよくある間違いです。たとえば、関数にネストされたループがあるのは、ほとんどの場合、プログラミングが貧弱です。 Matrix. この場合、解析は数学的アルゴリズムではなく、各行の処理を全体的な処理から分離する必要があります。この場合、エラーのケースが異なるため、最初の行の処理を他の行から分離することも役立ちます。(最初の行の長さは 0 より大きくてもかまいません。後の行は前の行と同じ長さでなければなりません。)

于 2011-12-22T09:48:06.640 に答える
0

問題は、ストリーム抽出演算子が、変更可能な既に構築されたオブジェクトを必要とすることです。動的にサイズ変更できるように、マトリックスクラスを調整する必要があります。

于 2011-12-22T08:52:42.373 に答える
0

「istream 演算子のサイズ」を決定することはできません。これは、まあ、ストリームであり、最初の行列要素を読み取るときに、最後の要素が既に存在することを誰も保証できないためです。最初に文字列全体を読み取り、それを解析して入力行列のサイズに関する情報を抽出する必要があります。その後、この文字列を 経由で提供することにより、コードを使用できますstringstream。もちろん、マトリックスのサイズを動的に変更できる必要があります。

于 2011-12-22T08:59:07.923 に答える