Очень легко различить EOF и другие ошибки, если вы не сконфигурируете поток для использования исключений.
Просто отметьте stream.eof()
в конце.
Перед этим проверяйте только неисправность / неисправность, например, stream.fail()
или !stream
. Обратите внимание, что good
не является противоположностью fail
. Так что вообще никогда даже не смотрите на good
, только на fail
.
Edit:
Некоторый пример кода, а именно ваш пример, изменен, чтобы различать плохую спецификацию bool в данных:
#include <iostream>
#include <sstream>
#include <string>
#include <stdexcept>
using namespace std;
bool throwX( string const& s ) { throw runtime_error( s ); }
bool hopefully( bool v ) { return v; }
bool boolFrom( string const& s )
{
istringstream stream( s );
(stream >> boolalpha)
|| throwX( "boolFrom: failed to set boolalpha mode." );
bool result;
(stream >> result)
|| throwX( "boolFrom: failed to extract 'bool' value." );
char c; stream >> c;
hopefully( stream.eof() )
|| throwX( "boolFrom: found extra characters at end." );
return result;
}
void readbools( istream& is )
{
string word;
while( is >> word )
{
try
{
bool const b = boolFrom( word );
cout << (b ? "T" : "F") << endl;
}
catch( exception const& x )
{
cerr << "!" << x.what() << endl;
}
}
cout << "- " << is.good() << is.eof() << is.fail() << is.bad() << "\n";
}
void testread( string const& s )
{
istringstream is( s );
readbools( is );
}
int main()
{
cout << string( 60, '-' ) << endl;
testread( "true false" );
cout << string( 60, '-' ) << endl;
testread( "true false tr" );
cout << string( 60, '-' ) << endl;
testread( "true false truex" );
}
Пример результата:
------------------------------------------------------------
T
F
- 0110
------------------------------------------------------------
T
F
!boolFrom: failed to extract 'bool' value.
- 0110
------------------------------------------------------------
T
F
!boolFrom: found extra characters at end.
- 0110
Редактировать 2 : в опубликованном коде и результатах добавлен пример использования eof()
проверки, которую я забыл.
Редактировать 3 :
В следующем соответствующем примере используется предложенное OP решение skip-whitespace-before-read:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
void readbools( istream& is )
{
bool b;
while( is >> ws && !is.eof() && is >> b ) // <- Proposed scheme.
{
cout << (b ? "T" : "F") << endl;
}
if( is.fail() )
{
cerr << "!readbools: failed to extract 'bool' value." << endl;
}
cout << "- " << is.good() << is.eof() << is.fail() << is.bad() << "\n";
}
void testread( string const& s )
{
istringstream is( s );
is >> boolalpha;
readbools( is );
}
int main()
{
cout << string( 60, '-' ) << endl;
testread( "true false" );
cout << string( 60, '-' ) << endl;
testread( "true false tr" );
cout << string( 60, '-' ) << endl;
testread( "true false truex" );
}
Пример результата:
------------------------------------------------------------
T
F
- 0100
------------------------------------------------------------
T
F
!readbools: failed to extract 'bool' value.
- 0110
------------------------------------------------------------
T
F
T
!readbools: failed to extract 'bool' value.
- 0010
Основное отличие состоит в том, что в третьем случае этот подход дает 3 успешно прочитанных значения, даже если третье значение указано неправильно (как "truex"
).
т.е. он не может распознать неверную спецификацию как таковую.
Конечно, моя способность писать код, который не работает и торгует; нет никаких доказательств того, что это не может работать. Но я довольно хорошо разбираюсь в вещах и не вижу способа обнаружить "truex"
как неправильный с этим подходом (хотя это было легко сделать с помощью подхода, основанного на исключениях из чтения слов). Так что, по крайней мере, для меня подход, основанный на исключениях из чтения слов, проще в том смысле, что легко заставить его вести себя правильно.
Приветствия и hth.,