How to modify ((c=getchar())!=NULL) to use fscanf or scanf instead?

R

rivkaumiller

How to modify ((c=getchar())!=NULL) to use fscanf or scanf instead?

For example, compact while loops are written like this in k&r

while ((c=getchar())!=NULL){

// do certain actions

}

and I want to convert a stanza like

fscanf ( FpSource, "%d" , &input );
while (input != EOF){

// do certain actions

fscanf ( FpSource, "%d" , &input );
}

into the above form with getchar() so that there is a single instance of fscanf.

More than one alternative would be appreciated.

Thanks
 
R

rivkaumiller

How to modify ((c=getchar())!=NULL) to use fscanf or scanf instead?



For example, compact while loops are written like this in k&r



while ((c=getchar())!=NULL){



// do certain actions



}



and I want to convert a stanza like



fscanf ( FpSource, "%d" , &input );

while (input != EOF){



// do certain actions



fscanf ( FpSource, "%d" , &input );

}



into the above form with getchar() so that there is a single instance of fscanf.



More than one alternative would be appreciated.



Thanks

Will this work?

while (fscanf ( FpSource, "%d" , &input ) != EOF){

// do certain actions with "input"

}
 
S

Stefan Ram

For example, compact while loops are written like this in k&r
while ((c=getchar())!=NULL){

Shouldn't this be »!= EOF«?
and I want to convert a stanza like
fscanf ( FpSource, "%d" , &input );
while (input != EOF){
fscanf ( FpSource, "%d" , &input );

When, for example, EOF is -1, then you must exclude the
possibility that this is a valid value for input. In this
case you can use something like (untested):

int getd()
{ int input = 1;
int product = scanf( "%d", &input );
assert( input != EOF );
return product > 0 ? input : EOF; }

....

while( ( i = getd() )!= EOF )...

Also, you lose the distinction between scanf returning 0 on
an early failure to match and scanf returning EOF on certain
other conditions. But this sometimes can then detected by
other means.
 
R

rivkaumiller

is:



while(fscanf(FpSource, "%d", &input), input != EOF) {

// do certain actions

}



what you are looking for?

Actually, I am not very clear on the operation of scanf() or fscanf() as I used them years ago. I have now some code to understand and if possible improve. Its obvious that there is redundancy in the original "stanza" and there, output was actually compared with -1 to be honest. EOF is my substitution. The original code was written by a novice and so I am not sure if it isvery good. I have used while (c=getchar())!=EOF) as a standard idiom. I just wanted to remove the redundancy and make it more regular call and single call to fscanf().
 
R

rivkaumiller

(e-mail address removed) writes (some lines omitted):





Shouldn't this be »!= EOF«?









When, for example, EOF is -1, then you must exclude the

possibility that this is a valid value for input. In this

case you can use something like (untested):



int getd()

{ int input = 1;

int product = scanf( "%d", &input );

assert( input != EOF );

return product > 0 ? input : EOF; }



...



while( ( i = getd() )!= EOF )...



Also, you lose the distinction between scanf returning 0 on

an early failure to match and scanf returning EOF on certain

other conditions. But this sometimes can then detected by

other means.

NULL was a typo. It should be EOF.

but the rest of your approach is probably making the thing too complicated.I dont know why the original author of the "stanza" uses fscanf() twice, once before the while and once inside the while at the end.

Thats the main issue to make it single instance.
 
E

Eric Sosman

How to modify ((c=getchar())!=NULL) to use fscanf or scanf instead?

For example, compact while loops are written like this in k&r

while ((c=getchar())!=NULL){

// do certain actions

}

and I want to convert a stanza like

fscanf ( FpSource, "%d" , &input );
while (input != EOF){

// do certain actions

fscanf ( FpSource, "%d" , &input );
}

into the above form with getchar() so that there is a single instance of fscanf.

More than one alternative would be appreciated.

Alternative #1,pretty much what you asked for:

while ( fscanf(FpSource, "%d", &input) , input != EOF ) {

The funny-looking thing inside the while() is an expression using
the comma operator -- yes, the comma can be an operator in C --
which evaluates its left-hand side (the fscanf() call), throws
the result away, then evaluates the right-hand side (input != EOF)
and yields the right-hand side's value as the value of the whole
expression.

I'd recommend against using this, though: There are too many
things that can go wrong. For starters, C promises that EOF is a
negative int, but doesn't specify any particular value. It is
very often -1, but could be something else (a case could be made
for -129 on some systems), so you don't really *know* what number
you should enter to stop the loop. Even if you do know the system's
EOF value (-1, say), what happens if you actually want to enter -1
as a legitimate datum? You're out of luck.

A worse problem occurs if fscanf() encounters "12.0" in the
input stream, or anything else that isn't strictly an int value.
On the first attempt it will digest "12", see that "." isn't a
digit and leave it alone, and store 12 in `input'. On the next
attempt it will see the "." again, realize that it can't make
any progress, and leave things unchanged: `input' will still be
12 from the first time. And you'll keep on getting 12 as the
value of `input' on the third, fourth, fifth, ... time until you
finally get tired and pull the plug on your program. Similar
trouble occurs if the input is "$42" or "(17)" or a myriad of
other non-numeric stuff.

Which leads us to Alternative #2, not what you asked for but
perhaps closer to what you should have asked for:

while (fscanf(FpSource, "%d", &input) == 1) {

In this alternative you're not making the continue/stop decision
based on the value of the number from the input, but on whether
fscanf() was able to find a number at all. fscanf() returns the
number of items it successfully read and stored; you're asking
for one item, so fscanf() returns 1 if and only if it was actually
able to make integer sense of its input. In the "12.0" example
above, the first call would convert "12" to 12, store it in `input',
and return 1. The second call would stall on the ".", leave `input'
unchanged, and return 0 -- and your program would then know that
you'd either reached the end of the input stream or encountered
something undigestible in it.

You might be interested in telling those two cases apart,
which leads to Alternative #3:

int status;
...
while ((status = fscanf(FpSource, "%d", &input)) == 1) {
...
}
if (status == EOF) {
... read all the way to the end ...
} else {
... found garbage somewhere in mid-stream ...
}

I might use #3 in a quick one-off program or if I had good
reason to believe the input was well-structured (e.g., the input
was the unedited output of some other program known to be well-
behaved). For input from a less well-controlled source -- in
particular, for interactive input -- even #3 isn't robust enough
for real-world use. I'll refer you to Question 12.20 and its
various links and footnotes on the comp.lang.c Frequently Asked
Questions (FAQ) page at <http://www.c-faq.com/> for an exposition
of some of the issues and some hints about coping with them.
 
J

James Kuyper

How to modify ((c=getchar())!=NULL) to use fscanf or scanf instead?

For example, compact while loops are written like this in k&r

while ((c=getchar())!=NULL){

// do certain actions

}

and I want to convert a stanza like

fscanf ( FpSource, "%d" , &input );
while (input != EOF){

// do certain actions

fscanf ( FpSource, "%d" , &input );
}

into the above form with getchar() so that there is a single instance of fscanf.

More than one alternative would be appreciated.

The following code has the exact same behavior as your loop, except that
it contains only one call to fscanf():

while(fscanf ( FpSource, "%d" , &input ), input != EOF)
{
// do certain actions
}

However, that isn't a very good idea.
"The fscanf function returns the value of the macro EOF if an input
failure occurs before the first conversion (if any) has completed.
Otherwise, the function returns the number of input items assigned,
which can be fewer than provided for, or even zero, in the event of an
early matching failure." (7.21.6.2p16)

Your code pays no attention to the value returned by fscanf(), which
means it does nothing to deal with the possibility that anything might
go wrong when you call it. This could lead, among other possibilities,
to the value of 'input' being unequal to EOF, and never changing,
because fscanf() has reached the end of the file or has an input
failure, so you've written an infinite loop.

What your code does is check input != EOF, which will be false only
under two circumstances:
a) input has a value of EOF at the start of the loop, and the first call
to fscanf() fails, leaving that value unchanged.
b) fscanf() completes successfully, loading input with a value equal to
EOF that was read from FpSource.

In principle, this could be a legitimate way of marking the end of your
input data. However, it suggests to me the possibility that you're
confused about how fscanf() works, and thought that input == EOF would
be the way to determine whether or not the call to fscanf() succeeded.

int status;
while((status = fscanf(FpSource, "%d", &input)) != EOF)
{
if(status != 1)
{
// Handle early matching failure
}
else
{
// do certain actions
}
}
if(ferror(FpSource))
{
// Handle I/O error
}
else
{
// Handle end of file
}

How you handle each of those situations is up to you. End of File, in
particular, is a perfectly normal thing, except when it occurs at a time
when it shouldn't be occurring, such as after the tenth number in a file
that was supposed to contain 100 numbers.

If you choose to simplify the code by removing all of the handling
sections, you can drop the corresponding else blocks, and even the
second if(). However, do NOT remove the if(status != 1) test. If status
is not equal to 1, then the value of 'input' is indeterminate. That
means it can be either an unspecified integer, or a trap
representations. Any attempt to use a trap representation has undefined
behavior, but very few implementations support 'int' types with trap
representations. Much more important is the fact that the value of
'input' is unspecified. That doesn't mean that it's random - it could be
highly predictable if you know enough about that particular
implementation of the C standard library. However, it does mean that
there's no guarantees about which value it has. There's nothing useful
your program can portably do with that value, so it should not "do
certain actions" using that value.
 
J

James Kuyper

On 03/30/2014 10:58 PM, James Kuyper wrote:
....
int status;
while((status = fscanf(FpSource, "%d", &input)) != EOF)
{
if(status != 1)
{
// Handle early matching failure
}
else
{
// do certain actions
}
}
if(ferror(FpSource))
{
// Handle I/O error
}
else
{
// Handle end of file
} ....
If you choose to simplify the code by removing all of the handling
sections, you can drop the corresponding else blocks, and even the
second if(). However, do NOT remove the if(status != 1) test.

I said that incorrectly. If you want to ignore early matching failures,
(it's often the case that there's nothing you can do about them), then
you could drop the if-clause, not the else-clause; but the simplest way
to re-write it would be as:

if(status == 1)
{
// do certain actions.
}

or even more simply:

while(fscanf(FpSource, "%d", &input) == 1)
{
// do certain actions
}

With this re-write, if you want to determine whether the loop terminated
due to an early matching failure, you'd have to check both
ferror(FpSource) and feof(FpSource), because the status isn't stored
anywhere for checking. I've used this form pretty frequently.
 
B

BartC

but the rest of your approach is probably making the thing too
complicated. I dont know why the original author of the "stanza" uses
fscanf() twice, once before the while and once inside the while at the
end.

Thats the main issue to make it single instance.

End-of-file checking in C is a bit funny, because you only get an eof status
after attempting to read input.

That may be why it started off with a read attempt just before the main
loop.

There are probably ways to have just one main read, as I think some replies
have demonstrated.

My own approach would be different: I would create a special eof() function
that gives you the end-of-file status before trying to read anything, then
the loops become more straightforward:

while (!eof(FpSource()) {
.....
}

Of course you then have the different (but simpler) problem of implementing
such an eof() function. (I use something like the following at present. This
returns 1 when positioned at end-of-file, otherwise 0:

int eof(FILE* handle) {
int c;

c=getc(handle);
if (c==EOF) {
return 1;
}
ungetc(c,handle);
return 0;
}

But I don't think it works well when reading and writing the same file.)
 
K

Keith Thompson

How to modify ((c=getchar())!=NULL) to use fscanf or scanf instead?

For example, compact while loops are written like this in k&r

while ((c=getchar())!=NULL){

// do certain actions

}

NULL is a null pointer constant. getchar() returns EOF when it's unable
to read a character. And be sure that "c" is defined as an int, not as
a char.
and I want to convert a stanza like

fscanf ( FpSource, "%d" , &input );
while (input != EOF){

// do certain actions

fscanf ( FpSource, "%d" , &input );
}

into the above form with getchar() so that there is a single instance of fscanf.

To use any input function, you need to understand the value that it
returns.

getchar() returns the value of the character it just read from stdin,
treated as an unsigned char and converted to int (for typically systems,
it will be a value in the range 0..255). That's if it's able to read a
character. If it's not, either because there are no more characters to
be read or because there was an error, it returns EOF, which is a
negative int value (typically -1, but don't assume that).

fscanf(), if it's successful, returns the number of items it read.
For

fscanf(FpSource, "%d" , &input);

it returns 1 if it was able to read an int value into "input".

If an input failure occurs, it returns EOF. Otherwise, it returns the
number of items it was able to read, which in this case will be either 0
or 1. (It's 0 if the input doesn't match the syntax of an optionally
signed decimal integer.)

That, along with the other followups, should be enough information get
you going.

Note that comparing the value of input to EOF doesn't make much sense;
input==EOF doesn't say anything meaningful about the input.
 
R

rivkaumiller

The following code has the exact same behavior as your loop, except that

it contains only one call to fscanf():



while(fscanf ( FpSource, "%d" , &input ), input != EOF)

{

// do certain actions

}



However, that isn't a very good idea.

"The fscanf function returns the value of the macro EOF if an input

failure occurs before the first conversion (if any) has completed.

Otherwise, the function returns the number of input items assigned,

which can be fewer than provided for, or even zero, in the event of an

early matching failure." (7.21.6.2p16)



Your code pays no attention to the value returned by fscanf(), which

means it does nothing to deal with the possibility that anything might

go wrong when you call it. This could lead, among other possibilities,

to the value of 'input' being unequal to EOF, and never changing,

because fscanf() has reached the end of the file or has an input

failure, so you've written an infinite loop.



What your code does is check input != EOF, which will be false only

under two circumstances:

a) input has a value of EOF at the start of the loop, and the first call

to fscanf() fails, leaving that value unchanged.

b) fscanf() completes successfully, loading input with a value equal to

EOF that was read from FpSource.



In principle, this could be a legitimate way of marking the end of your

input data. However, it suggests to me the possibility that you're

confused about how fscanf() works, and thought that input == EOF would

be the way to determine whether or not the call to fscanf() succeeded.



int status;

while((status = fscanf(FpSource, "%d", &input)) != EOF)

{

if(status != 1)

{

// Handle early matching failure

}

else

{

// do certain actions

}

}

if(ferror(FpSource))

{

// Handle I/O error

}

else

{

// Handle end of file

}

Thanks to everyone who replied.

"status" is a good self-commenting alias for the return value of fscanf().

I finally found this worked well

while (fscanf ( FpSource, "%d" , &input ) != EOF){

// do certain actions with "input"

}

as all it cares about is reaching the end of the input file.

Concluded.
 
J

James Kuyper

....
"status" is a good self-commenting alias for the return value of fscanf().

I finally found this worked well

while (fscanf ( FpSource, "%d" , &input ) != EOF){
// do certain actions with "input"
}

as all it cares about is reaching the end of the input file.

And it therefore does not address this issue:

Are you certain that your input stream won't have any early matching
errors? Such certainty is often a matter of self-delusion.

Or do you simply not care about the possibility that your program might
end up processing meaningless values that have nothing to do with the
contents of your input file? If that's not a problem, you can simplify
your program a great deal by not even bothering to read that file.
 
G

glen herrmannsfeldt

End-of-file checking in C is a bit funny, because you only get an
eof status after attempting to read input.

Seems to me that Pascal is funny, in that it tests EOF before reading
the end of file.

Well, Fortran 66 had no method to detect EOF, so that was worse, but
many added the END= extension. All other languages that I know of
detect EOF when you actually try to read something and there isn't
anything to read.
That may be why it started off with a read attempt just before
the main loop.

I have seen some unusual C come from former Pascal programmers.

-- glen
 
K

Kaz Kylheku

Seems to me that Pascal is funny, in that it tests EOF before reading
the end of file.

In the Pascal wrong, this design is acknowledged as being wrong because it's
not repeated Wirth's successors to Pascal like Oberon and Modula 2.

Modula 2 calls streams "channels". A read operation produces a result
which is tested afterward. For instance, ReadChar tries to read a character
and store it to a CHAR location via a VAR parameter. Afer ReacChar,
you have to call ReadResult on the channel. Only if that result is allRight
was the character read successfully.

(It's very silly still: ReadChar is a procedure. Why can't it be a function
that returns the read result?)

Oberon calls streams "riders". The Oberon-2 report doesn't describe
I/O at all, but I found this quote in "Programming in Oberon"
[http://www.ethoberon.ethz.ch/WirthPubl/ProgInOberon.pdf]:

"The file can thereafter be read by the following pattern. First, the file
with pecified name is associated with variable f. Then a rider is placed at
the start o f the file, and then advanced by reading.

f := Files.Old("MyFile"); Files.Set(r, f, 0);
WHILE ~r.eof DO Files.Read(f, next); process(next) END

Note that the rider indicates that the end of the file had been reached
after the first unsuccessful attempt of reading."

LOL! Note how Wirth points out that EOF is established by a failed read,
but his example tests EOF at the top of the loop, and assumes that
the read succeeded.
 
B

BartC

Kaz Kylheku said:
In the Pascal wrong, this design is acknowledged as being wrong because
it's
not repeated Wirth's successors to Pascal like Oberon and Modula 2.

Modula 2 calls streams "channels". A read operation produces a result
which is tested afterward. For instance, ReadChar tries to read a
character
and store it to a CHAR location via a VAR parameter. Afer ReacChar,
you have to call ReadResult on the channel. Only if that result is
allRight
was the character read successfully.

Wrong or not, the Pascal design is far simpler to use. For example, I can
write an outline file-processing loop right now:

while (!eof(f)) {
.....
}

before I even have any idea of what's to go in the loop! Or I can change the
kind of reads I want to do, while the loop logic stays the same. It also
means the main read function can actually be in the body of the loop,
instead of always being part of the loop condition; not quite as readable.
 
K

Kaz Kylheku

Wrong or not, the Pascal design is far simpler to use. For example, I can

Simple redeems wrong?
write an outline file-processing loop right now:

while (!eof(f)) {

So we are not at EOF. Well, how *far* are we from EOF? Can we read, say, 512
bytes, without having to bother checking the result?

As soon as we have to check something about the read result, the !eof(f)
check was superfluous.
 
B

BartC

Kaz Kylheku said:
Simple redeems wrong?

How wrong can be it when it can work perfectly fine?
So we are not at EOF. Well, how *far* are we from EOF? Can we read, say,
512
bytes, without having to bother checking the result?

These sorts of loops, I generally read a character or a line at a time, ie,
per iteration. In both cases you will know you will get one character, or
one line (although the line can be empty as I throw away any newline
characters).

I suppose you can argue that with such restricted uses, it's not hard to
apply eof-checking to char-reading or line-reading routines, but it just
seems easier and more natural to me to use separate eof logic. (I mean, if
you were walking in fog near a cliff edge, you would check that it was safe
before the next step, not after you've fallen off the edge!)

(But also, I make extensive use of these low-level C file routines from
several other languages, and those like to use statements to read characters
and lines, not functions; an error return would be harder to check. So I
like to write C the same way.)
 
P

Phil Carmody

BartC said:
Wrong or not, the Pascal design is far simpler to use. For example, I
can write an outline file-processing loop right now:

while (!eof(f)) {
.....
}

before I even have any idea of what's to go in the loop!

If you don't know what's going on in the loop, perhaps you
shouldn't be writing it at all?
Or I can
change the kind of reads I want to do, while the loop logic stays the
same.

False. You need to change the return value checks to match
the kinds of reads that you're doing. And if you need to
to that, when why not just have the check in the while's
conditional clause?
It also means the main read function can actually be in the body
of the loop, instead of always being part of the loop condition; not
quite as readable.

Only if you're not familiar with, or simply intrinsically biased
against, that convention. For me, as long as the read functions
are sane (and in case they're not there's always the possibility
of creating sane wrappers) it's a perfectly readable convention.

Phil
 
E

Eric Sosman

[...]
Wrong or not, the Pascal design is far simpler to use. For example, I can

Simple redeems wrong?
write an outline file-processing loop right now:

while (!eof(f)) {

So we are not at EOF. Well, how *far* are we from EOF? Can we read, say, 512
bytes, without having to bother checking the result?

As soon as we have to check something about the read result, the !eof(f)
check was superfluous.

Aye. There's also the matter of the EOF-test-before-reading
on an interactive device like a keyboard. How would that work,
exactly? "Do you intend to press any more keys? If so, press Y.
If not, press -- oh, wait, if you're not going to press any more
keys you can't press N, can you? Okay: press Y if you're going
to press more keys, otherwise don't press any keys -- and that's
how I'll know whether we're at EOF."
 
G

glen herrmannsfeldt

BartC said:

(snip regarding EOF testing)
(snip)

Wrong or not, the Pascal design is far simpler to use. For
example, I can write an outline file-processing loop right now:
while (!eof(f)) {
.....
}
before I even have any idea of what's to go in the loop!
Or I can change the kind of reads I want to do, while the loop
logic stays the same. It also means the main read function can
actually be in the body of the loop, instead of always being
part of the loop condition; not quite as readable.

But you don't know that it is EOF until you know what you want
to read.

If you consider Java Scanner, which is commonly used for stream
input, you tell it what you want to read, and it tells you if you
can read that.

Scanner s=new Scanner(System.in);

while(s.hasNextDouble()) {
System.out.println(s.nextDouble());
}

The loop will exit at EOF, or earlier than EOF if the rest of the
stream doesn't look like a double. The file might have some blank
space left, and so not be at EOF, but no double.

s.hasNextChar() could still return true, though s.hasNextInt()
would return false.

The other way to do it in Java is to catch the exception at end of
file and/or I/O error.

-- glen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top