[Courses] C Programming For Absolute Beginners, Lesson 2: Fun With Printf, Scanf, Puts, and Variables
Sachin Divekar
ssd532 at gmail.com
Wed Feb 29 06:01:45 UTC 2012
On Wed, Feb 29, 2012 at 9:49 AM, Jacinta Richardson <
jarich at perltraining.com.au> wrote:
> On 29/02/12 13:06, Damián wrote:
>
>>
>> Hi Jacinta, thanks for your answer. I understood all of that (I think),
>> but I still don't get why in the original code:
>>
>> ====
>> scanf( "%d", &a );
>> puts( "Please enter another number up to three digits: " );
>> scanf( "%d", &b );
>> c = a + b;
>> printf("%d + %d = %d\n", a, b, c);
>> ====
>>
>> If you enter an invalid value in the first scanf, all the other lines are
>> run, except for the second 'scanf'. It doesn't wait for user input. I don't
>> see the relation between the first scanf returning 0 and the second not
>> running because of that condition.
>>
>>
> Oh! I'm sorry, yes, that is much more clear.
>
> scanf() reads a value in from the STDIN input buffer. Essentially this
> contains all of the stuff you type in, and that gets passed to the program
> each time you hit enter. When scanf() runs, it starts at the start of the
> buffer and tries to find something there that matches what it is looking
> for. It'll skip whitespace, but not other characters. So if we type in:
>
> " 123<newline>"
>
> (without the quotes, and where we hit the enter key to create a newline
> (also represented as "\n")) the first scanf() will skip all of that
> whitespace, see a number (123) and read that in. At the end of this call
> to scanf(), the position in the buffer that we are up to is just before
> that newline/enter. When the second scanf() runs, it sees that there is no
> data for it (there's only the newline) so it waits for further input.
>
> On the other hand, if we typed in:
>
> "123 456\n"
>
> (without the quotes, and where \n is our newline (hitting the enter key))
> then the first scanf() will skip any leading whitespace (of which there
> isn't any) then then see a number (123) and read that in. At the end of
> this call to scanf(), the position in the buffer that we are up to is the
> space before after the 3. When we run the second scanf() it sees that
> there is still data in the buffer and it reads the next number 456 without
> waiting for further input.
>
> Something similar happens when we type in garbage data. If we type in:
>
> "no thanks"
>
> then the first scanf() sees that there isn't a number there for it, so it
> doesn't read anything in (and returns 0 for how many things it read in).
> So the position of in the input buffer is still at that letter "n" in
> "no". When the next scanf() happens it sees that there is still data in
> the buffer, so it reads from that and also fails to match a number,
> therefore also returning 0.
>
> This is actually really helpful. It means that you can do the following:
>
> if( scanf( "%d", &number) ) {
> printf("You gave me a number!\n");
> }
> else if( scanf( "%s", &string) ) {
> printf("You gave me a string!\n");
> }
>
> I hope this helps.
>
>
> J
>
>
Yes we can avoid such kind of problems by just discarding the user input by
nr = scanf( "%d",&a );
if(nr< 1) {
printf( "Invalid input.\n" );
return 1;
}
as stated by Jacinta.
But out of curiosity I searched for flushing the input stream buffer. One
solution is to
use fflush(stdin), but it is said that it does not fit into standards and
risky
to use.
http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1052863818&id=1043284351
Then I found a less risky solution to flush input stream buffer.
// using flush_i() to clear input stream buffer
#include<stdio.h>
int main()
{
void flush_i(void){
int c;
while (c != '\n' && c != EOF){
c = getchar();
}
}
int a, b, c;
printf("Please enter any number up to three digits:" );
scanf("%d", &a);
flush_i();
printf("You entered %d. Now enter another number up to three
digits:\n", a );
scanf("%d", &b);
c = a + b;
printf("%d + %d = %d\n", a, b, c);
return 0;
}
Here flush_i() discards everything upto the next new line in the input
stream buffer.
Even if we can discard the wrong input here, flush_i() might be useful
somewhere else.
--
Regards,
Sachin Divekar
More information about the Courses
mailing list