Why does order matter in scanf command in C programming? - c

#include <stdio.h>
void main() {
int i;
char x;
float y;
double z;
//line1
printf("enter an integer");
scanf("%d", &i);
//line3
printf("enter a character");
scanf("%c", &x);
printf("enter a floating point");
scanf("%f", &y);
printf("enter a double");
scanf("%lf", &z);
printf("Integer is %d \n character is %c \n floating point is %f \n double is %lf ",
i, x, y, z);
}
My question is, when I run this code it doesn't prompt the input of a character value and skips to the next command. But if I swap line 3 with 1 i.e. if I prompt for character first and then integer, then it works fine. Please help me understand this problem.

Most scanf format specifiers skip leading white-space (like newline), but %c does not (it should be able to read spaces).
That means the newline added to the input buffer from the Enter key you pressed for the previous input will be read by the %c format.
To skip leading space you need to add a space to the format string:
scanf(" %c",&x);
// ^
// Note leading space here

Use the following format string in the call of scanf for an object of the type char.
scanf(" %c",&x);
^^^
Otherwise this call (without the leading blank) will read white space characters that for example correspond to the entered key Enter.

Related

Unable to read the char input in C using %c

#include <stdio.h>
#include <stdlib.h>
int main()
{
int num1;
int num2;
char op;
printf("Enter the first number: ");
scanf("%d", &num1);
printf("Enter an operator: ");
scanf("%c", &op);
printf("Enter the second number: ");
scanf("%d", &num2);
switch(op){
case'+':
printf("%d", num1+num2);
break;
case'-':
printf("%d", num1-num2);
break;
case'/':
printf("%d", num1/num2);
break;
case'*':
printf("%d", num1*num2);
break;
default:
printf("Enter a valid Operator");
}
return 0;
}
I tried to build a basic calculator with user input. but I am getting an error in this line scanf("%c", &op); I searched in here(Stackoverflow) and I also found the answer that if I put a space in scanf(" %c", &op) then my program will work fine;
now the question I have is, Could someone explain me this in laymen's terms for a beginner? Please. Your answer will be much appreciated
scanf manual:
specifier c:
Matches a sequence of characters whose length is specified by the
maximum field width (default 1); the next pointer must be a pointer to
char, and there must be enough room for all the characters (no
terminating null byte is added). The usual skip of leading white space
is suppressed. To skip white space first, use an explicit space in the
format.
ie format scanf(" %c", &op).
After typing the first number for int num1 you type an enter '\n' the next scan for character captures the new line and prints it . So as per the manual, To skip white space first, use an explicit space in the format:
printf("Enter an operator: ");
scanf(" %c", &op);
or use like this below:
printf("Enter an operator: ");
scanf("%c", &op);
scanf("%c", &op);
Prepend the conversion specifier in the format string with a space like
scanf( " %c", &op );
^^^^^
In this case white space characters in the input stream as the new line character '\n' that corresponds to the pressed key Enter will be skipped
The problem is not with scanf but stdin. stdin and stdout refer to the same file in the memory for console application. So there is '\n' in the stdin which you have entered for first scanf which is taken by scanf and stored in op. Try putting scanf("%c", &op); above scanf("%d", &num1); or write fflush(stdin) above scanf("%c", &op);
Try using 'getc' and 'gets' instead.
'scanf' is considered to be unsafe altogether and it would be wise to search for safer alternatives. That way you will have greater control over user input.

scanf is being skipped in C [duplicate]

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 5 years ago.
I tried to run the following program:
int main(){
char a;
char b;
char c;
printf("\nenter a: ");
scanf("%c", &a);
printf("\nenter b: ");
scanf("%c", &b);
printf("\nenter c: ");
scanf("%c", &c);
return 0;
}
upon running the program it prompts you to enter a value for a. once you do, you are prompted to enter a value for b, however you are not allowed to input a value because the program skips the scan and then prompts you again to input a value for c which is not skipped. I can initialize a and c, but not b. and I have no idea why. I read somewhere that using %[^\n] in the scanf, but I tried using it and I don't think I used it correctly because it still wasn't working.
this is the output (with some input examples):
enter a: 1
enter b:
enter c: 1
process returned 0 (0x0)
Instead of "%c", use " %c".
Without the space, scanf does not skip white spaces when the format specifier is %c. That is initially confusing since it will skip white spaces for other format specifiers, such as %d, %f, %s, etc.
When you press enter, that adds a character to the input queue, which is then read into b.
You can either explicitly read a character to ignore it, or you can use (for one alternative) %1s to read a single-character string (which will skip white-space, including the new-line character entered when you press enter.
'\n' becomes the input for variable b after you press enter.
so to take care of this, use getchar() which will take care of '\n'.
int main(){
char a;
char b;
char c;
printf("\nenter a: ");
scanf("%c", &a);
getchar();
printf("\nenter b: ");
scanf("%c", &b);
getchar();
printf("\nenter c: ");
scanf("%c", &c);
return 0;
}

scanf() function with different format specifier

Below is a program which accepts two character and prints them
#include<stdio.h>
int main()
{
char c1, c2;
printf("\n Enter characters one : ");
scanf(" %c", &c1);
printf("\n Enter character two : ");
scanf("%c", &c2);
printf("\n The the characters are %c and %c ", c1, c2);
return 0;
}
Now one output instance is :-
Enter two characters : a
The the characters are a and
The problem is that I haven't given any space between two format specifier %c
Here I pressed 'a' and then '\n' which gets stored into c1 and c2 respectively. And thus I got output which was not accepted.
I know how to correct this problem.
Now I make the same program for the integers :-
#include<stdio.h>
int main()
{
int a, b;
printf("\n Enter two numbers : ");
scanf("%d%d", &a, &b);
printf("\n The two numbers are %d and %d ", a, b);
return 0;
}
Here we will not found any problem.
I think this time we didn't encounter problem because the second input we give is '\n' or space which is not any integer and thus we get a failure in the reading from the scanf() function so the input buffer is still active and if we press the next input as integer then it gets stored into variable 'b'.
Can you tell me the reason which I thought is correct or not?
Now if it is correct then what will happen if I press again a character. Then also it should not get stored into the variable 'b' but this time 0 gets stored into variable 'b'.
So my question is that what is the reason for proper behavior of the program when I'm trying to make the same program with %d
To answer your question, let's have a look at C11 standard, chapter ยง7.21.6.2
Input white-space characters (as specified by the isspace function) are skipped, unless
the specification includes a [, c, or n specifier.
So, when you have a newline ('\n', which is indeed a white-space character) left in the input buffer,
in case of scanf("%c", &charVar);, the newline is considered as the input, so the second scanf skips asking for the input from user.
in the case of scanf("%d", &intVar); the leftover newline is skipped and it wait for the integer input to appear, so it stops and asks the user for the input.
However, FWIW, in later case, if you input a non-whitespace character and press ENTER, the char input will be considered as an input, causing a matching failure.
Related
[...] If
the input item is not a matching sequence, the execution of the directive fails: this
condition is a matching failure.
It's reading the new line as the newline is a character. Simply changing scanf("%c", &c2); to scanf(" %c", &c2); will make it work.
So in your code:
#include
int main()
{
char c1, c2;
printf("\n Enter characters one : ");
scanf(" %c", &c1);
printf("\n Enter character two : ");
scanf(" %c", &c2);
printf("\n The the characters are %c and %c ", c1, c2);
return 0;
}

scanf works before its execution point

I tried a simple program..function returning integer and character pointer..after i run that code i found some weird acting by scanf..I tried to print message(enter a,b:) read two integer inputs and message(enter c,d:) read two char inputs.but at run time..i found that input for the char c is read rightafter i enter the inputs for a,b..
for eg:
enter a,b: 10
20
enter c,d: g
it gets only one input(for d) and input for c is newline after 20..
for eg 2:
enter a,b: 10
20a
enter c,d: g
it gets only one input(for d) and input for c is a after 20..
why is this happening..please clarify it
int* add(int *a,int *b)
{
return (*a>*b?a:b);
}
char* charret(char *c,char *d)
{
return (*c>*d?c:d);
}
int main()
{
int a,b;
char c,d;
printf("\n\t\tFUNCTION RETURNING INTEGER POINTER\n\t");
printf("Enter the Number A and B:");
scanf("%d %d",&a,&b);
printf("\tEnter the character c :");
scanf("%c %c",&c,&d);
printf("The Biggestt Value is : %d\n\t",*add(&a,&b));
printf("\n\tThe character c= %c hi d= %c",c,d);
// scanf("%c",&d);
printf("\n\tThe Biggestt Value is : %c", *charret(&c,&d));
getch();
return 0;
}
%c will read any character, including the newline character from your previous entry. If you want to read the first non-whitespace character, add a space before %c in your format string:
scanf(" %c %c",&c,&d);
/* ^ added space */
This will cause scanf() to eat any number of whitespaces before reading the character.
For most scanf() specifiers, any leading whitespace is skipped. %c is an exception to this, because it reads a single character value, including whitespace characters. Keep in mind when you press Enter, you've sent a '\n' to the input buffer.
scanf("%d %d",&a,&b);
Reads in two numbers. The \n at the end, from pressing Enter, is left in the buffer.
scanf("%c %c",&c,&d);
Reads in two characters, the first of which will be the \n left in the buffer. One way to get around this is:
while (getch() != '\n');
This will eat everything up to an including a newline. You can put that after the scanf() lines you know will leave a newline behind.

Problems with scanf

#include <stdio.h>
int main()
{
char C, B;
int x;
printf("What comes after G\n");
scanf("%c", &C);
printf("What comes after O\n");
scanf("%c", &B);
printf("What is your age?\n");
scanf("%d", &x);
printf("You said %c comes after G, %c after T and you're %d years old? Right?", C, B, x);
return 0;
}
The problem is whenever you run the code it skips the second question "What comes after O" and then asks "What is your age?"
The only way I could avoid the program skip the 2nd question was by adding a space to the code
printf("What comes after O\n");
scanf(" %c", &B);
You can see the space between " and %c
Can you please explain this to me?
You need to eat up the white space (i.e. new line) - as per the manual page http://linux.die.net/man/3/scanf
You can use scanf to eat the single character without assigning it to anything like this::
scanf( "%[^\n]%*c", &C ) ;
%[^\n] tells the scanf to read every character that is not '\n'. That leaves the '\n' character in the input buffer, then the * (assignment suppression) will consume the a single character ('\n') but would not assign it to anything.
The reason for this problem is newline character \n leftover by the previous scanf after pressing Enter. This \n is left for the next call of scanf.
To avoid this problem you need to place a space before %c specifier in your scanf.
scanf(" %c", &C);
...
scanf(" %c", &B);
...
scanf(" %c", &X);
A space before %c is able to eat up any number of newline characters.
The problem is you are using scanf to get the character ..and a new line will be added at the end of each input from user . So the second time only the new line will be stored in the 'B' Because of the first input given by you ..
Instead of scanf , change it to getchar - your problem should get solved

Resources