-=> Quoting Cameron Clark to Thomas Maeder
TM> Don't do this! An input stream isn't supposed to throw an exception on
TM> end of file. There is no good reason for it, since eof isn't an
TM> exceptional situation.
CC> I've got a dozen lines of redundant code that say otherwise. Try
CC> writting a reasonable tokenizer without it and you'll see why I
CC> need to do this.
I still would have to agree with Thomas.
CC> Let's pretend I have a simple language and everything is delimited
CC> by space.
CC> Given situation: get a character and build a token until white
CC> space is reached. White space can be an actual space, tab, or
CC> newline character.
void GetToken(
istream& is,
string& token,
bool& eof
)
{
token = ""; // clear the token
eof = false; // not likely
char c;
do
{
is.get(c);
if (is)
{
if (isspace(c))
{
// is.putback(c);
return; // space isn't part of token
}
token += c;
}
else
{
if (is.eof())
{
is.clear(); // can't recall offhand
eof = true;
return;
}
else
{
// what else could go wrong? Nothing, really...
assert(false);
return;
}
}
} while (token.length() < MAX_TOKEN_LEN);
}
No exceptions. No "fake" return codes. The programmer isn't likely to throw
away the eof value. Only one check for EOF (two if you count the conversion
of is to void* - but since eof really is the only error condition, we could
eliminate the test for eof explicitly). Use of string type makes the length
calculation a constant-time excersise. Use of isspace (which, IIRC, catches
\t and \n, as well as a number of others) standardizes your code, as well as
changes your space-check to a table-lookup (generally speaking). Also,
unlike your sample code, it doesn't put the space into the token (since it
isn't really part of a token in general - so I'm taking liberties with the
project here...). I also don't understand why you'd put back a whitespace
into the input - but you could just uncomment the putback line to do that...
CC> As you can see, this is a nasty piece of so called structured code.
Which is why it needs to be put into its own function. (I, however, don't
have a problem with multiple exits, especially where they are quite useful.)
CC> If MyIfstream would trow an exception, I could eliminate almost
CC> have of the redundant checks.
Or if you redesigned your code, you could eliminate redundant checks.
CC> Notice that there will be _only_ one end of file reached per file.
CC> If I check every character read from the file 3 times I have a
CC> slow, slow, slow piece for code.
Generally I/O is slower than CPU-bound activity anyway. Whereever you're
reading from (whether disk, floppy, modem, named pipe, whatever), three
checks will likely be faster than the average is.getc() call.
CC> I need one piece of code, to be run once, be one exception: not
CC> several lines of code to check every character, every time.
You're doing a check every character, every time, as it is - the if that
determines whether or not to throw. My code does no different, but without
the overhead of a throw.
CC> Note, I agree with you that the original ifstream should not be
CC> made to act in the prescribed way; however, I need such a
CC> specialized class in this case.
Perhaps you do - but, if so, it's gotta be for more than just this.
Good luck,
... "He's terminally inconvenienced, Jim."
--- FastEcho 1.46
---------------
* Origin: House of Fire BBS - Toronto - (416)601-0085 - v.34 (1:250/536)
|