Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > scanf(), ungetc() behaviour.

Reply
Thread Tools

scanf(), ungetc() behaviour.

 
 
Argento
Guest
Posts: n/a
 
      03-03-2006
I was curious at the start about how ungetc() returns the character to the
stream, so i did the following coding. Things work as expected except if I
change the scanf("%c",&j) to scanf("%d",&j). I don't understand how could
scanf() affect the content of i[0] and i[1]. Can someone tell me why?

#include <stdio.h>
#include <ctype.h>

void main()
{
char i[2], j;
printf("Please input a two digit number:");
i[0]= getchar();
i[1]= getchar();
ungetc(i[1],stdin);
ungetc(i[0],stdin);
scanf("%c", &j); //scanf("%d",&j);
fflush(stdin);
printf("\nYou entered %d in decimal and %c in character mode for
i[0]",i[0],i[0]);
printf("\nYou entered %d in decimal and %c in character mode for
i[1]",i[1],i[1]);
printf("\nYou entered %d in decimal and %c in character mode for j",j,j);

getchar();

}


 
Reply With Quote
 
 
 
 
Jack Klein
Guest
Posts: n/a
 
      03-03-2006
On Fri, 3 Mar 2006 10:19:19 +0800, "Argento" <>
wrote in comp.lang.c:

> I was curious at the start about how ungetc() returns the character to the
> stream, so i did the following coding. Things work as expected except if I
> change the scanf("%c",&j) to scanf("%d",&j). I don't understand how could
> scanf() affect the content of i[0] and i[1]. Can someone tell me why?


Your program has so many instances of undefined behavior that there is
nothing at all that the C standard has to say about what it should do.

> #include <stdio.h>
> #include <ctype.h>
>
> void main()


The C standard requires that main() be defined with a return type of
int in a hosted environment, unless you have a C99 conforming compiler
that specifically documents that it accepts "void main()", and I will
most certainly bet that you do not. This means your program is
undefined.

> {
> char i[2], j;
> printf("Please input a two digit number:");
> i[0]= getchar();
> i[1]= getchar();
> ungetc(i[1],stdin);
> ungetc(i[0],stdin);


You haven't checked the return value of the ungetc() function,
particularly the second one. Only one character of push back is
guaranteed by the standard. The second one could have failed.

> scanf("%c", &j); //scanf("%d",&j);


'j' is a character and has a size of one byte (with 8 or more bits).
If you pass scanf() a "%d" conversion specifier and the address of
'j', you are telling scanf() to write an int into that one byte. On
your platform int has more than one byte, and so won't fit into 'j'
which only has room for a single character. You are lying to scanf()
when you use "%d" and this causes undefined behavior.

> fflush(stdin);


The fflush() function is not defined for input streams, more undefined
behavior.

> printf("\nYou entered %d in decimal and %c in character mode for
> i[0]",i[0],i[0]);
> printf("\nYou entered %d in decimal and %c in character mode for
> i[1]",i[1],i[1]);
> printf("\nYou entered %d in decimal and %c in character mode for j",j,j);
>
> getchar();
>
> }


Fix the undefined behavior in your program and then ask questions if
you are puzzled about what it does.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
 
Reply With Quote
 
 
 
 
Argento
Guest
Posts: n/a
 
      03-03-2006
> The C standard requires that main() be defined with a return type of
> int in a hosted environment, unless you have a C99 conforming compiler
> that specifically documents that it accepts "void main()", and I will
> most certainly bet that you do not. This means your program is
> undefined.


Well, sorry. I don't know much about the standard but i am using DEV C++ and
the compiler compiles it happily.
I am just lazy with the 'return' when i don't check for it.


>> {
>> char i[2], j;
>> printf("Please input a two digit number:");
>> i[0]= getchar();
>> i[1]= getchar();
>> ungetc(i[1],stdin);
>> ungetc(i[0],stdin);

>
> You haven't checked the return value of the ungetc() function,
> particularly the second one. Only one character of push back is
> guaranteed by the standard. The second one could have failed.


Ok, i checked on this after your post by replacing the two ungetc statement
with the following.
if( (ungetc(i[1],stdin))== i[1] ) printf("First ungetc() success.\n");
if( (ungetc(i[0],stdin))== i[0] ) printf("Second ungetc() success.\n");

It seems like that, i have no problem with pushing back both characters.



>> scanf("%c", &j); //scanf("%d",&j);

>
> 'j' is a character and has a size of one byte (with 8 or more bits).
> If you pass scanf() a "%d" conversion specifier and the address of
> 'j', you are telling scanf() to write an int into that one byte. On
> your platform int has more than one byte, and so won't fit into 'j'
> which only has room for a single character. You are lying to scanf()
> when you use "%d" and this causes undefined behavior.
>


You are right, I was careless. If I change j to 'int' things are solve,
however, it's still weird to change the content of i[0] and i[1].
Maybe scanf('%d", &j) when j is 'char' overwrite the memory of i[0]?

>> fflush(stdin);

>
> The fflush() function is not defined for input streams, more undefined
> behavior.


Well, i just keep on seeing examples that uses fflush( stdin ) and i was
told to do so after a scanf() and before a getchar()
because the '\n' is not taken by scanf("%d") or scanf("%c"). That was my
practice of clearing the stdin's buffer.
Any suggestion/alternative of doing so would be appreciated.



 
Reply With Quote
 
Martin Ambuhl
Guest
Posts: n/a
 
      03-03-2006
Argento wrote:
> I was curious at the start about how ungetc() returns the character to the
> stream, so i did the following coding. Things work as expected except if I
> change the scanf("%c",&j) to scanf("%d",&j). I don't understand how could
> scanf() affect the content of i[0] and i[1]. Can someone tell me why?
>
> #include <stdio.h>
> #include <ctype.h>
>
> void main()

^^^^
Don't bother with trying to learn how ungetc() works until you stop this
absurd BullSchildtism.
 
Reply With Quote
 
Richard Heathfield
Guest
Posts: n/a
 
      03-03-2006
Argento said:

>> The C standard requires that main() be defined with a return type of
>> int in a hosted environment, unless you have a C99 conforming compiler
>> that specifically documents that it accepts "void main()", and I will
>> most certainly bet that you do not. This means your program is
>> undefined.

>
> Well, sorry. I don't know much about the standard but i am using DEV C++
> and the compiler compiles it happily.


Nevertheless, it is incorrect. And now you *know* it's incorrect.

I know for certain that at least one regular contributor to this group, and
possibly more than one, has got into the habit of completely ignoring any
"plea-for-help" article in which the questioner has used void main, on the
grounds that they can't be all that serious about C if they can't even get
the entry point right.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
 
Reply With Quote
 
Argento
Guest
Posts: n/a
 
      03-03-2006

"Martin Ambuhl" <> wrote in message
news:buRNf.5792$ ink.net...
> Argento wrote:
>> I was curious at the start about how ungetc() returns the character to
>> the stream, so i did the following coding. Things work as expected
>> except if I change the scanf("%c",&j) to scanf("%d",&j). I don't
>> understand how could scanf() affect the content of i[0] and i[1]. Can
>> someone tell me why?
>>
>> #include <stdio.h>
>> #include <ctype.h>
>>
>> void main()

> ^^^^
> Don't bother with trying to learn how ungetc() works until you stop this
> absurd BullSchildtism.


Ok, so i listened and search, then read about this
http://www.eskimo.com/~scs/readings/...in.960823.html
But i don't quite understand whether i should end my program with exit(0) or
return 0;
Can you explain to me pls?


 
Reply With Quote
 
Argento
Guest
Posts: n/a
 
      03-03-2006

> Nevertheless, it is incorrect. And now you *know* it's incorrect.
>
> I know for certain that at least one regular contributor to this group,
> and
> possibly more than one, has got into the habit of completely ignoring any
> "plea-for-help" article in which the questioner has used void main, on the
> grounds that they can't be all that serious about C if they can't even get
> the entry point right.
>

I see. I didn't know it was that serious until i looked into the faq.
I was taught that way, "when you don't check for the return of main, why
declare int main?"
Now i know after reading
http://www.eskimo.com/~scs/readings/...in.960823.html
and i will change that habit


 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      03-03-2006
"Argento" <> writes:
[...]
> Ok, so i listened and search, then read about this
> http://www.eskimo.com/~scs/readings/...in.960823.html
> But i don't quite understand whether i should end my program with exit(0) or
> return 0;
> Can you explain to me pls?


"exit(0);" and "return 0;" (within main) are almost exactly
equivalent. If you use exit, you must have a "#include <stdlib.h>" at
the top of your source file. The exit function can be used to
terminate the program from functions other than main; a return
statement from a function other than main just returns from that
function.

Use whichever one you like. (I usually use return, but it's no a big
deal.)

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
Nick Keighley
Guest
Posts: n/a
 
      03-03-2006
Argento wrote:

<snip>

> >> {
> >> char i[2], j;
> >> printf("Please input a two digit number:");


if you want your output to be guaranteed to appear put a
\n at the end or call fflush(stdout)


> >> i[0]= getchar();
> >> i[1]= getchar();
> >> ungetc(i[1],stdin);
> >> ungetc(i[0],stdin);


is there some sort of international shortage of whitespace
no one told me about? This is the third post in three days
which uses an atrocious layout. An indent of one!

> > You haven't checked the return value of the ungetc() function,
> > particularly the second one. Only one character of push back is
> > guaranteed by the standard. The second one could have failed.

>
> Ok, i checked on this after your post by replacing the two ungetc statement
> with the following.
> if( (ungetc(i[1],stdin))== i[1] ) printf("First ungetc() success.\n");
> if( (ungetc(i[0],stdin))== i[0] ) printf("Second ungetc() success.\n");
>
> It seems like that, i have no problem with pushing back both characters.


it's not portable though

<snip>


> >> fflush(stdin);

> >
> > The fflush() function is not defined for input streams, more undefined
> > behavior.

>
> Well, i just keep on seeing examples that uses fflush( stdin )


they are wrong. If your book uses void main() and fflush(stdout) then
destroy it. DO NOT give it to a charity shop as some other poor sucker
will mistake it for a C book. If you want a good book try
http://cm.bell-labs.com/cm/cs/cbook/

> and i was
> told to do so after a scanf() and before a getchar()
> because the '\n' is not taken by scanf("%d") or scanf("%c"). That was my
> practice of clearing the stdin's buffer.
> Any suggestion/alternative of doing so would be appreciated.


don't use scanf() use fgets() followed by sscanf()


--
Nick Keighley

"Half-assed programming was a time-filler that, like knitting,
must date to the beginning of human experience."
"A Fire Upon The Deep" by Verne Vinge

 
Reply With Quote
 
Argento
Guest
Posts: n/a
 
      03-03-2006

> "exit(0);" and "return 0;" (within main) are almost exactly
> equivalent. If you use exit, you must have a "#include <stdlib.h>" at
> the top of your source file. The exit function can be used to
> terminate the program from functions other than main; a return
> statement from a function other than main just returns from that
> function.
>
> Use whichever one you like. (I usually use return, but it's no a big
> deal.)


Thx, that's what i got too from K&R2 Sec. 7.6 pp.164. Except that it says
exit has the advantage call from other function and that exit calls flcose
for each
open output file to flush out any buffered output.

Yet, a friend of mine told me not to rely on it and do the flcose() myself.


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments