Scanf Function

i recently wrote a program in C that allows a user to enter a letter which is later identified with the help of the coding of the program and displays an output mentioning if the entered letter is A , B or something else.

Though this is a simple program i found an error that surprised me after compilation.

the coding does not stop at the scanf and ask the user to enter a value.

the coding is as follows,



// THIS PROGRAM SCANS A LETTER AND AND DETERMINES IF THE ENTERED LETTER IS
//EQUAL TO A , B or SOMETHING ELSE
// AND PRINTS A MESSAGE
// QQQ : WHY DOES THE DEFAULT STATEMENT EXECUTE TWO TIMES???
//i.e. WHY DOES IT READ THE NULL CHARACTOR TOO?if we enter letter 'A' and
//press enter,it reads the enter too! i.e. it reads the '\n' provided by the
//enter


#include <stdio.h>
#include <math.h>

int main () {

char a;

do {

printf ( "Enter a letter for char 'a' : " );
scanf ("%c" ,&a );

switch (a) {

case 'a' :
printf ( " AAA ");
printf ("\n\n\n");
break;

case 'b' :
printf ( " BBB ");
printf ("\n\n\n");
break;

default :
printf ( " the default statement excecuted");
printf ("\n\n\n");
break;


}

} while ( 1);

return 0;

}


After a cople of days of hard work, i found the reason( upto my best knowledge) for this error. the reason is that the function SCANF buffers the A and the "enter button" i.e. \n i press in the console screen as a another charactor.

thus it does not let the program to go to the TOP (start of the while loop) till its buffered variables finish.
thus it will execte printf ( " the default statement excecuted"); TWO times!

but according to the study meterial you provided
ref to http://www.cplusplus.com/reference/clibrary/cstdio/scanf/

it says
" ..the function will read and ignore any whitespace characters (this includes blank spaces and the newline and tab characters) which are encountered before the next non-whitespace character. This includes any quantity of whitespace characters, or none.."

now this conflicts with results but cant think of another solution.

Help at this level from you will be greatly appreciated.

thank you
I don't maintain the cplusplus site, but there's an answer to your questions.

Firstly, you are absolutely right, that the scanf() routine catches the '\n' character. That's why the default statement is executed after you hit enter.

Secondly, concerning
but according to the study meterial you provided
ref to http://www.cplusplus.com/reference/clibrary/cstdio/scanf/
it says
" ..the function will read and ignore any whitespace characters (this includes blank spaces and the newline and tab characters) which are encountered before the next non-whitespace character. This includes any quantity of whitespace characters, or none.."
this refers to the first argument of the scanf() function, not the line you enter at runtime. The first argument of scanf() in your code is "%c".

Thirdly, the solution to your problem does not seem trivial to me. Standard C does not know a keyboard. Single keystrokes cannot be retrieved. But a non-standard header-file (which should work on most systems including Windows, Linux and Unix) can solve the problem. Include
#include <conio.h>
at the beginning of your source file. Then replace your scanf() line by
a = getch();
The function getch() retrieves a single key stroke. I hope this works for you.
Last edited on
The conio library, as far as I know, isn't frequently implemented on most *nixes, including Linux and Mac OS X. Just a heads-up. :/

An alternative that I know is cross-platform is pdcurses. http://pdcurses.sourceforge.net/

-Albatross
Last edited on
Firstly, you are absolutely right, that the scanf() routine catches the '\n' character. That's why the default statement is executed after you hit enter.


That has nothing to do with scanf - that's just how most terminals/shells work.
Yes, scanf buffers the end of line character. So, you should clean the buffer.

1
2
scanf("%c",&a);
fflush(stdin);


Or you can get the whole line and use sscanf to get the character.

1
2
3
char str[10];
gets(str);
sscanf(str,"%c",&a);


You can use second method for almost every time you need scanf.
Last edited on
Just use after scanf()

 
fflush(stdin);
gets function gets the line. It gets end of line character too but it erases it. So, you can use gets and sscanf method instead of scanf and fflush method.
thanks everyone for replying to my question
i have another doubt

#include <stdio.h>

int
main(void)
{
char n;
while (scanf("%c", & n))
printf("%c\n", n);
return 0;
}


when we use this scanf, it prints the o/p line by line. the function while its working inputs char by char to the printf line thus we see :

input : abc cde f
o/p :
a
b
c
d
e
f

i.e. each letter is printed in a new line!


BUT the same program for integers behave differently :

#include <stdio.h>

int
main(void)
{
int n;
while (scanf("%d", & n))
printf("%d\n", n);
return 0;
}


input : 456 123 789 456 12
456 1
2378

optput :

456
123
789
456
12
456
1
2378

it takes one set! at a time monitoring the white space

why all this difference for %d and %c? i dont understand.
Amalinda Gamage
Last edited on
And People as the answer to my previous question i think no more solution but it is the change of scanf thats reqd


scanf ("%2c" ,&a );


this works perfectly.


i have changed the format specifier.
so it reads BOTH characters at once at the console.
scanf grabs BOTH entered characters at ONCE like before but now it tries to apply both "entered letter" and "\n" to the variable A (char A) . but since A was entered first. A goes in first.

the scanf is reading TWO BY TWO blocks of characters entered
if i input : ADBW

i will observe two printf lines saying

printf ( " AAA ");
printf ( " BBB ");
because the first letter of both blocks is respectively A and B . The second letter of each BLOCK is not Considered.


nothing is buffered. Am i right?

Amalinda Gamage
(SLIIT)
Last edited on
Topic archived. No new replies allowed.