I don't understand the purpose of the outer loop at all. First, file
will never be equal to eof()
, or... What is eof()
, any way?
Second, if you've actually written while ( !file.eof() )
, this could
explain the fact that some of the elements get overwritten. There will
likely be some trailing characters (a new line, at least) after the last
digit, so you'll reenter the loop again.
And you're incrementing the indexes even when the character you read is
not a digit. If the data is 9 lines of 9 digits, you'll end up with 9
cells in grid
which haven't been initialized, and 9 characters that
haven't been read from the file once you've finished the inner two
iterations. So you'll enter the outer loop again, reading these
characters. Some of which will be digits, so you'll end up overwriting
cells in grid
that you've already written—this is probably the
effect you're observing. Also that once you reach the end of the file,
file.get()
will start returning EOF
—typically -1. That's
doubtlessly why your tests for '\n'
and '\r'
didn't work.
And these are just the problems with a correctly formatted file. For a
correctly formatted file, just using file >> n
, with char n;
would
almost work; operator>>
skips whitespace. But you'd still enter the
outermost loop a second time, since file.eof()
won't be reliable until
an input has failed. You say "I have to use this", but your code can't
be made to work unless you change it.
Personally, I favor robust solutions, with lots of error checking. I'd
use std::getline()
, and I'd verify that each line contained exactly 9
digits. Something like:
std::string line;
int i = 0;
while ( i < 9 && std::getline( file, line ) ) {
if ( line.size() != 9 ) {
throw FormatError( "wrong line length" );
}
for ( int j = 0; j != 9; ++ j ) {
if ( ! isdigit( static_cast<unsigned char>( line[j] ) ) ) {
throw FormatError( "illegal character" );
}
grid[i][j] = line[i] - '0';
}
}
if ( i != 9 || std::getline( file, line ) ) {
throw FormatError( "wrong line count" );
}
It wouldn't be too hard to use file.get()
, and read one character at
at time, but you'd still want to check for EOF
after each read:
for ( int i = 0; i != 9; ++ i ) {
for ( int j = 0; j != 9; ++ j ) {
int ch = file.get();
if ( ch == EOF ) {
throw FormatError( j == 0
? "line too short"
: "too few lines" );
}
if ( !isdigit( ch ) ) {
throw FormatError( "illegal character" );
}
grid[i][j] = ch - '0';
}
int ch = file.get();
if ( ch != '\n' ) {
throw FormatError( ch == EOF ? "too few lines" : "line too long" );
}
}
if ( file.get() != EOF ) {
throw FormatError( "too many lines" );
}