まず、もちろん、よりも少し厳密に指定する必要があります。"[ 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 より大きくてもかまいません。後の行は前の行と同じ長さでなければなりません。)