delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2001/03/27/01:34:25

From: Jack Klein <jackklein AT spamcop DOT net>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: is this a bug?
Message-ID: <amb0ct41pn1s6rndo0bg9k5e2uif2e89jv@4ax.com>
References: <99oo0k$gr7$1 AT neptunium DOT btinternet DOT com>
X-Newsreader: Forte Agent 1.8/32.548
MIME-Version: 1.0
Lines: 99
Date: Tue, 27 Mar 2001 06:18:41 GMT
NNTP-Posting-Host: 12.75.160.207
X-Complaints-To: abuse AT worldnet DOT att DOT net
X-Trace: bgtnsc04-news.ops.worldnet.att.net 985673921 12.75.160.207 (Tue, 27 Mar 2001 06:18:41 GMT)
NNTP-Posting-Date: Tue, 27 Mar 2001 06:18:41 GMT
Organization: AT&T Worldnet
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

On Tue, 27 Mar 2001 01:49:00 +0100, "Michael Ahumibe"
<M DOT Ahumibe AT btinternet DOT com> wrote in comp.os.msdos.djgpp:

> Hi
> 
> The following program should ask for a character to be input near the end
> 
> #include <stdio.h>
> 
> int main()
> {
>  char string[20];
>  unsigned int number;
>  char test;
> 
>  printf("Enter a string: ");

On many platforms the prompt will not appear until after the user
types some input and presses the enter or return key.  When you are
issuing a prompt to the user that does not end in '\n', you should
always add a fflush(stdout) before the input function to make sure
that the prompt shows up first.

>  scanf("%s", &string);

The line above is incorrect, the name of a character array like string
is always converted to a pointer to its first element when passed to a
function.  Just "string" is the address of string[0].  &string is a
pointer to an array of characters, not a pointer to char.  This just
happens to work on most compilers "by accident".

>  printf("Enter a number: ");
>  scanf("%u", &number);
> 
>  printf("Enter a character: ");
>  scanf("%c", &test);
> 
> 
>  printf("%s %u %c",string,number,test);
> 
>  return 0;
> }
> 
> I compile the code and run it. The line containing scanf("%c", &test); is
> skipt!! can someone tell me the exact reason for this?

It is a bug, but the bug is in your code caused by not understanding
the way scanf() works, it is not a bug in the compiler or its library
functions.  Before I go any further I must say this:

scanf() is a very difficult function to use correctly, and it is
impossible to use well for interactive user input.  Go look at the FAQ
for comp.lang.c (link in my signature) for better methods.

Your first call to scanf() asks it to input a string.  It will skip
leading white space (spaces, tabs, newlines) in the input until it
comes to the first non-white space character.  It will store that
character and all other characters it finds up to but not including
the first white space character.  Using "%s" in scanf() without a
length specifier is like playing Russian Roulette.  If the user
happens to type 50 non white space characters, scanf() will write past
the end of your 20 character array and cause undefined behavior and
probably crash your program.

But assuming your user enters less than 20 non white space characters
and presses the return or enter key, scanf() will store those
characters in your array, put a '\0' at the end, and leave the '\n'
from the enter key in the input stream.

Next you ask scanf() to input an unsigned int.  It will skip leading
white space in the input stream (starting with the '\n' left behind
from entering the string) until it finds the first non white space
character.  If that character can be part of a text string
representing an unsigned int, scanf() reads it and all the following
characters that can be part of the representation of an unsigned int.
It continues reading until it finds a character that can't be part of
an unsigned int, and leaves that character in the input stream.

So if you typed "123" and pressed the enter or return key, you put the
characters '1', '2', '3', '\n' into the stdin stream.  scanf() took
the '1', '2', and '3', converted them to a number, and left the '\n'
in the input stream.

In your third scanf() call you used "%c", asking for a single char.
This is the scanf() conversion specifier that does not skip leading
white space, but in turn takes the very first character it finds in
the stream no matter what it is.  In this case it finds the '\n' left
behind from entering the unsigned int, so it sets test to '\n' and it
is done.

Never, never mix single character input with formatted input!

-- 
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019