Behavior of scanf() - c

why the program is not stopping at the line 4 for taking the input?
int main(int argc, char *argv[])
{
int a, b;
char c1, c2;
printf("Enter something: ");
scanf("%d",&a); // line 1
printf("Enter other something: ");
scanf("%d", &b); // line 2
printf("Enter a char: ");
scanf("%d",&c1); // line 3
printf("Enter other char: ");
scanf("%d", &c2); // line 4
printf("Done"); // line 5
system("PAUSE");
return 0;
}
i read this question from a book and in above line 4 the scanf() is not executing but why?

%d expects to read a bunch of digits from input, so that it can form an integer and store the result into the pointer you pass (which is invalid in this example, since you provided a pointer to char, but anyway, this is irrelevant here).
The problem is that if you input a character, scanf() will notice that there isn't a valid digit on input. It will read this character, push it back into the input, and return prematurely. This happens on line 3. Since the character was pushed back, line 4 will again retrieve the same character from input and see that there is no valid integer on input, so the same character is pushed back again.
The key point to keep in mind here is that scanf returns prematurely with invalid input, leaving the input stream untouched.
For example, if stdin holds the character a, scanf() on line 3 will retrieve an a from input. It sees that this cannot be a valid digit, so a "goes back" to stdin and scanf() returns. On line 4, the scanf call will do the same thing: it picks the next item from input, which is the same a, and returns prematurely. Scanning for integers won't work until you consume this character. For example, if you call getchar() after line 3, you consumed the problematic character, and scanf() on line 4 will wait for input.

scanf has issues with the newline. A quick and dirty way to solve this, is by adding a space or a \n before %c in order to bypass that...
printf("Enter a char: ");
scanf(" %c",&c1); // line 3
printf("Enter other char: ");
scanf(" %c", &c2); // line 4

printf("Enter a char: ");
scanf("%c",&c1); // line 3
printf("Enter other char: ");
scanf("%c", &c2); // line 4
change %d with %c (from decimal to character)

Related

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;
}

how field specifier works in C

I need to take two int values from user. First value is using field specifier and second is normal integer value.
#include<stdio.h>
int main()
{
int num, num1;
printf("Enter first number: \n");
scanf("%2d", &num);
printf("First number is %2d\n", num);
printf("Enter second number: \n");
scanf("%d", &num1);
printf("Second number is %d\n", num1);
return 0;
}
and the output is
Enter first number:
12345
First number is 12
Enter second number:
Second number is 345
It won't give control to enter second number. I don't know why?
You see this behaviour because you have limited the size of input that the first scanf statement can consume. scanf("%2d", &num) says that scanf should read a field of width at most 2 and convert that into into num.
Change the scanf to scanf("%d", &num) and the entirety of 12345 will be processed.
you don't get to enter second num because your program gets it from first num.
First time, your scanf lets your num get first two digits of the number you entered, and rest remains in the buffer/stream.
next time scanf is executed, it reads the remaining digits from the stream till an enter stroke, hence you don't get to enter the second no.
if you want to read the second no.
try flushing the stream before using second scanf(), you will get what you want.
Why would you expect it to "give control"? The fist scanf() explicitly consumed at most two digits, leaving "345" unconsumed. The next scan begins with the unconsumed input. What else would you expect?
If you want to discard any unconsumed input before the next scan, use fpurge(stdin).
There is always a tradeoff with scanf. If you want to enter a whole number and then consume the trailing newline (left in the input buffer (stdin) as the result of pressing [enter]), you canappend a %*c to read and discard the trailing newline. This itself causes problems if an empty-string is entered.
However, limiting your scanf format string and specifier to %2d and then entering 123456, you intentially leave 3456\n in the input buffer which is taken as your input to the second scanf call. The only way to insure each of your scanf calls will only accept your expected input is to manually empty the input buffer after each read by scanf to insure there are no characters remaining prior to the next call. A simple way to do this is with either a do .. while or simply a while ; using getchar() to read each character in stdin until a '\n' is encountered or EOF:
#include<stdio.h>
int main()
{
int c, num, num1;
printf("Enter first number: \n");
scanf("%2d", &num);
while ((c = getchar()) && c != '\n' && c != EOF) ;
printf("First number is %2d\n", num);
printf("Enter second number: \n");
scanf("%d", &num1);
printf("Second number is %d\n", num1);
return 0;
}
output:
$ ./bin/scanf_tradeoff
Enter first number:
123456
First number is 12
Enter second number:
12345
Second number is 12345
The reason for second value is not getting from you, in first scanf you are mentioning that
get the two values from the input. You are giving more than two that time the remaining value is stored in the buffer. So second scanf will get the value from the buffer.
If you want to avoid this you can use this statement before the second scanf.
while ((c=getchar())!='\n' && c!=EOF);// clearing the buffer.
So now the second input will get from the user.

Ambigious nature of scanf taking input before it is asked to enter from user?

#include<stdio.h>
void main(){
int num1,num2;
printf("\n Enter number 1 \t "); // Ask for input one. >>>>>>>> line 1.
scanf("%d ",&num1);
printf("\n Entered number is %d \n",num1);
printf("\n Enter number 2 \t "); // Ask for input Two. >>>>>>>>> line 2.
scanf("%d ",&num2);
printf("\n Entered number is %d \n",num2);
return;
}
I wish to know REASON.Please do provide it.
The code above accepts two inputs,first input is asked(By executing line 1) then user enter one number then terminal should ask to enter second input but instead it is taking other number(before executing line2 ) and then asking to enter second input(i.e after executing line 2).
In the End is is displaying the two input that are taken before executing line two but after executing line 1.
I am confused.I am interested to know reason.
I am using GCC 4.8.2 on ubuntu 14.04 64 bit machine.
Remove spaces between the scanf of access specifier.
scanf("%d ",&num1);
to
scanf("%d",&num1);
Because the scanf get the another value due to that spaces.
And kept in the buffer. After the memory has got it get assigned.
It is for all scanf function.
if I input like
Enter Number1 1
2
Entered number is 1
Enter number2 3
Entered number is 2.
It is better to use int main() and in the end write return 0;
use fflush(stdout); to flush your buffer.
After editing here is the final code
#include<stdio.h>
int main(){
int num1,num2;
printf("\n Enter number 1 \t "); // Ask for input one. >>>>>>>> line 1.
scanf("%d ",&num1);
printf("\n Entered number is %d \n",num1);
printf("\n Enter number 2 \t "); // Ask for input Two. >>>>>>>>> line 2.
fflush(stdout);
scanf("%d ",&num2);
printf("\n Entered number is %d \n",num2);
return 0;
}
Here is the Demo.
You need to put
fflush(stdout);
before the scanf
This will flush your buffer
(also a good idea to check the return value of scanf)
You have given a space in scanf for %d. If you remove that space after %d the program will run
Let's take this apart slowly
#include <stdio.h>
// void main(){
int main(void) {
int num1, num2;
printf("\n Enter number 1 \t ");
scanf("%d ",&num1);
printf("\n Entered number is %d \n",num1);
...
Use a proper function signature for main() - but that is not the main issue.
Code prints "\n Enter number 1 \t "
"%d" directs scanf() to scan for text convertible to an int in 3 steps:
A: Scan for optional leading white-space like '\n', '\t', ' '. Throw them away.
B: Scan for text representing an integer like "+1234567890". If any digits found, save the converted result to the address &num1.
C: Scanning continues in step B until a char that does not belong to the int is found. That char is "un-read" and returned to stdin.
(This is where you get in trouble as suggested by #Chandru) " " directs scanf() to scan for any number (0 or more) white spaces including '\n', '\t', ' ' and others. Then they are thrown away - not saved.
B: Scanning continues!! until a non-white-space is found. That char is "un-read" and returned to stdin.
Lastly scanf() return the value of 1 as that is how many field specifiers were converted. Code sadly did not check this value.
Recall stdin is usually line buffered, which means input is not available to user IO until Enter is hit.
User enters 1 2 3 Enter and scanf() scans the "123" and saves 123 to &num1. Then it scans "\n" as that is a white-space in step 4. and it continues waiting for more white-space.
User enters 4 5 6 Enter and the first scanf() which is not yet done, scans '4', sees it is not a white space and puts '4' back in stdin. scanf() finally returns after 2 lines are entered. At this point "456\n" are waiting in stdio for subsequent scanf().
The second scanf() then perpetuates the issue.
Recommend use fgets() only for all user input, at least until your are very skilled in C.
printf("\n Enter number 1 \t ");
char buf[100];
fgets(buf, sizeof buf, stdin);
if (sscanf(buf, "%d", &num1) != 1) Handle_BadInput();
else printf("\n Entered number is %d \n",num1);

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.

Resources