Why enter (new line) will not exit from scanf? - c

Here is the program:
#include "stdio.h"
int main()
{
int minx, x, y, z;
printf("Enter four ints: ");
scanf( "%i %i %i %i", &minx, &x, &y, &z);
printf("You wrote: %d %d %d %d", minx, x, y, z);
}
Say if I enter like the following: 1 2 3 4 (then press enter).
The scanf() runs and reads the input buffer = 1 (space) 2 (space) 3 (space) 4 (space)(\n)
it reads until (\n) and \n will remain in the buffer.
If I enter like the following: 1 (then press enter) 2 (then press enter) 3 (then press enter) 4 (then press enter).
The scanf() runs and reads the input buffer = 1(\n)2(\n)3(\n)4(\n)(\n).
In those 2 cases, the scanf() skips the newline, whitespace and tries to read an int.
But if I enter 1 (then press enter)(then press enter)... the scanf() then never runs if I keep hitting enter.
My question is: what triggers scanf()? Will it only run after it knows all the correct %d are placed in the buffer then run if the user press enter?

Because scanf() ignores white space, and white space includes newlines.
The scanf() processes the four numbers the same way each time: by skipping white space, then reading a candidate sequence that looks like a number (so signs and digits), and stops reading at the first character that can't be part of the candidate sequence; it then converts the candidate sequence (behaviour on overflow etc undefined). If you typed a space after the 4 (rather than just a newline), both the space and the newline will still be waiting to be read next. If there's no space, then the newline will be waiting to be read.
If you typed a non-numeric character (punctuation or letter), then scanf() would return with an error (or fewer than 4 numbers converted — unless the letter is after the fourth number).
When you type a single number followed by an arbitrary number of newlines, you're simply giving scanf() white space to skip over. It won't stop until it gets EOF (zero bytes read) or a read error (or a conversion error, such as a letter or punctuation character instead of a digit).

that is the expected behaviour of scanf
From the c99 standard:
A conversion specification is executed in the following steps:
- Input white-space characters (as specified by the isspace function) are skipped, unless the specification includes a '[', 'c', or 'n' specifier.
it tokenises on the seperator characters (space tab newline etc ..)
the last newline is part of the tokenisation .. otherwise how would it know when your integer finishes? :D
I think this solves your question? i am not sure . Hope this helps

Related

C printf wont print before scaning next number

I got this piece of code
#include<stdio.h>
#include <stdlib.h>
int main()
{
int i;
int number, S;
float MO;
S = 0;
for(i=0;i<10;i++)
{
printf("AAA %d\n", i );
scanf("%d\n", &number);
S = S + number;
}
MO = S/10;
printf("%d , %f \n",S , MO );
return 0;
}
when the execution starts, AAA 0 is printed.I then give my first number.After that, i am expecting to see AAA 1 , but this will be printed only after i give my second number.
Checked this here
C/C++ printf() before scanf() issue
but seems i can get none of these solutions work for me
The answers claiming that this has something to do with flushing input or output are wrong. The problem has nothing to do with this. The appearance of the \n character at the end of the scanf() template string instructs scanf() to match and discard whitespace characters. It will do so until a non-whitespace character is encountered, or end-of-file is reached. The relevant part of the C11 Standard is §7.21.6.2 5:
A directive composed of white-space character(s) is executed by
reading input up to the first non-white-space character (which remains
unread), or until no more characters can be read. The directive never
fails.
In OP's case, a second number must be placed in the input stream so that the first can be assigned. The second number then remains in the input stream until the next call to scanf(). In the case of the example given by Stephan Lechner, taking input from a file, there is a number in the input stream after each number to be assigned, until the last number (if there are exactly ten numbers), and then the EOF causes scanf() to return. Note that OP could also have signalled EOF from the keyboard after each input. Or, OP could enter all numbers on one line, with an extra number to signal end of input:
1 2 3 4 5 6 7 8 9 10 11
The solution is simply to remove the \n from the end of the scanf() template string. Whitespace characters at the end of such a template string are tricky, and almost never what is actually desired.
Just remove the \n from the scanf format string:
scanf("%d", &number);
"\n" waits for non-white-space. Instead use scanf("%d", &number) #Michael Walz and check its return value.
Let us break down scanf("%d\n", &number);
"%d" Scan for numeric text. This specifier will allow leading white-space. Once some non-numeric character is found, put that character back into stdin. If valid numeric text for an integer was found, convert to an int and save to number.
"\n" Scan and discard 0 or more white-spaces such as '\n', ' ', and others. Continue scanning until non-white-space is encountered, put that character back into stdin.
Now return the number of fields scanned (1).
Notice step 2. User had to type in data after the Return or '\n' to get scanf() to return.
The issue is with the buffering of stdout which doesn't force a flush unless a \n is in the output or fflush is called specifically

Break out of loop (do/while) by pressing a button [duplicate]

This question already has answers here:
What does space in scanf mean? [duplicate]
(6 answers)
Closed 7 years ago.
The following code gives the bizarre o/p as soon as I compile it.
main() {
char name[3];
float price[3];
int pages[3], i;
printf ( "\nEnter names, prices and no. of pages of 3 books\n" ) ;
for ( i = 0 ; i <= 2 ; i++ )
scanf ("%c %f %d", &name[i], &price[i], &pages[i] );
printf ( "\nAnd this is what you entered\n" ) ;
for ( i = 0 ; i <= 2 ; i++ )
printf ( "%c %f %d\n", name[i], price[i], pages[i] );
}
But if we give the space in the scanf statement before %c, it gives proper o/p.
Can anyone please explain me why is it so?
Update:-
If I am providing the input like this-
F
123.45
56
J
134
67
K
145
98
then my question is why not we are giving space before %f and space before %d? Why we need to give space before %c only?
Adding the space to the format string enables scanf to consume the newline character from the input that happens everytime you press return. Without the space, name[i] will receive the char '\n', and the real char is left to be misinterpreted by %f.
So, say your input is
a 1.0 2
b 3.0 4
c 5.0 6
The program sees it more like this:
a 1.0 2\nb 3.0 4\nc 5.0 6\n\377
That is, the line-breaks are actual characters in the file (and the \377 here indicates "end of file").
The first scanf will appear to work fine, consuming a char, a float, and an integer. But it leaves the input like this:
\nb 3.0 4\nc 5.0 6\n\377
So the second scanf will read the '\n' as its %c, unless you get rid of it first.
Adding the space to the format string instructs scanf to discard any whitespace characters (any of space ' ', tab '\t', or newline '\n').
A directive is one of the following:
A sequence of white-space characters (space, tab, newline, etc.; see isspace(3)). This directive matches any amount of white space, including none, in the input.
...
from http://linux.die.net/man/3/scanf
This sort of problem arises whenever you use scanf with %c in a loop. Because, assuming free-form input, newlines can happen anywhere. So, it's common to try to avoid the whole issue by using a two-tiered approach. You read lines of input into a buffer (using fgets); chop-off the silly newline characters; then use sscanf instead of scanf to read from the buffer (string) instead of straight from the file.
Incorrect input using %c
Consider the following snippet of code:
int main( ){
int x;
char y;
scanf("%d", &x);
scanf("%c", &y);
printf("%d %c", x, y);
}
Behavior: When you run the above program, the first scanf is called
which will wait for you to enter a decimal number. Say you enter
12(That’s ASCII ‘1’ and ASCII ‘2’). Then you hit the "enter" key to
signal the end of the input. Next the program will execute the second
scanf, except you will notice that the program doesn't wait for you to
input a character and instead goes right ahead to output 12 followed
by a ‘\n’.
Explanation:Why does that happen? Let’s look at the behavior of the
program step-bystep.
Initially there is nothing in the buffer. When the first scanf() is called, it has nothing
to read, and so it waits. It keeps waiting until you type 1,2, then "enter". Now what's in
the buffer are the character 1, the character 2, and the character ‘\n’. Remember that ‘\n’
signifies the end of input, once all fields have been entered, but it is also stored in the
buffer as an ASCII character. At this point scanf will read the largest decimal input from
the buffer and convert that to an integer. In this example, it finds the string "12" and
converts it to the decimal value twelve and puts it in x. Then scanf returns control back to
the main function and returns the value 1, for being able to convert one entry
successfully. In our example, we do not catch the return value of the scanf in a variable.
For robust code, it is important to check the return value of scanf( ) to make sure that the
user inputted the correct data.
What is now left in the buffer is ‘\n’. Next, the second scanf is
called and it's expecting a character. Since the buffer already has
the ‘\n’ character in it, scanf sees that, takes it from the buffer,
and puts it in y. That's why when you execute the printf afterwards,
12 and “enter” are printed to the screen.
Solution: Moral of the story is, enter is a character like any other,
and is inputted to the buffer, and consumed from the buffer by %c just
like any other ASCII character. To fix this, try using this code
instead:
int main( ){
int x;
char y;
scanf("%d", &x);
scanf("\n%c", &y); /* note the \n !! */
printf("%d %c", x, y);
}
**
How does this fix the problem?
** So you again type ‘1’,’2’,’\n’. The first scanf reads "1" and "2", converts that to the decimal twelve and leaves the ‘\n’ in the buffer.
The next scanf now expects a ‘\n’ at the beginning of the next input.
It finds the ‘\n’ in the buffer, reads it, and discards it. Now the
buffer is empty and scanf is waiting on the user to input a character.
Say the user inputs ‘c’, followed by the enter key. ‘c’ is now
assigned to y, NOT "enter". Therefore printf will output "12 c" to the
screen. NOTE: there is again a ‘\n’ sitting in the queue now. So if
you need to do another scanf for a single character, you will have to
"consume" that '\n' before taking another character in from the user.
This is not an issue for any other format specifier, as they all ignore white spaces before
the input.

How space is interpreted in the format of C scanf?

I would like to know how space is interpreted in the format of C scanf.
for example, when I write:
scanf("%d ",&c);
the value read from the keyboard is not directly assigned to the variable c.
And if I write:
while(c != 0){
scanf("%d ",&c);
printf("c = %d\n", c);
}
I have to enter 0 twice to exit the while loop.
Can someone explain this behaviour?
Thanks.
I assume c is declared as:
int c;
When you have a scanf line
scanf("%d ",&c);
the program will read into c the first non-whitespace characters that represent an int. It will skip all the whitespaces before the first non-whitespace character. That addresses the %d part of the format string. Then, it processes the whitespace part of the format string. It will wait to read all the whitespace characters from the stream that follow the last character that was processed to read into c. It will stop reading only when it encounters a subsequent non-whitespace character. The first non-whitespace character can be anything. It doesn't have to be a digit/number.
If you enter 10k as input, it will stop right away after reading 10. k will still be left in the input stream.
" " requires scanf("%d ",&c); to consume all white-space after an integer has been scanned.
Use input is line buffered. scanf() receives nothing until a '\n' or EOF is occurs.
Example
User types: Space 1 2 3 Enter which sends " 123\n" to stdin.
scanf("%d" consumes the " 123" scans the '\n' and seeing it is not a digit, "ungets" and puts it back into stdin.
scanf(" " consumes the white-spaces '\n' and waits for more input to examine.
User types: Space 4 5 7 Enter which sends " 456\n" to stdin.
scanf( continues step 3: scans the ' ', consumes it, scans the '4', and seeing it is not a white-space, "ungets" and puts it back into stdin.
The second space of the format scanf(" " scans the '4' ans seeing it is not a white-space, "ungets" and puts it back into stdin.
Finally first scanf() return as it is done. It retuns a 1 as it successfully scanned the first field. Notice 2 Enters have occurred.
The next scanf("%d" consumes the "456" and continues like step 2 above.
Do not recommend to have a format end in white-space with scanf().
N1256 7.19.6.2 The fscanf function
A directive composed of white-space character(s) is executed by reading input up to the
first non-white-space character (which remains unread), or until no more characters can
be read.
N1256 7.19.6.4 The scanf function
2 The scanf function is equivalent to fscanf with the argument stdin interposed
before the arguments to scanf.

why to put space between %d and %c while inputting there values using scanf

im a beginner to C,, and i was writing a code to print a square of a user entered character.
usually when we need to input two integers (say x and y) using scanf() we write this scanf("%d%d", &x, &y) but according to the needs of my code i am supposed to input one integer (say m) and a character (say ch).
I wrote it as scanf("%d%c", &x, &ch) but it has an error, when i execute the program it only asks the integral value to be entered and then it just stop executing.
I searched for this and i found that i need to put space between %d and %c as scanf("%d %c", &x, &ch);
Can anyone explain this why we need to put space between this?
Meaning of whitespace characters in the format string (from http://www.cplusplus.com/reference/cstdio/scanf/?kw=scanf):
Whitespace character: the function will read and ignore any whitespace characters encountered before the next non-whitespace character (whitespace characters include spaces, newline and tab characters -- see isspace). A single whitespace in the format string validates any quantity of whitespace characters extracted from the stream (including none).
When your code is:
scanf("%d%c", &x, &ch)
and you enter
10
in your console:
10 is read and stored in x.
the newline character is read and stored in ch.
If you use
scanf("%d %c", &x, &ch)
and you enter
10
10 is read and stored in x.
the newline character and other whitespace characters are consumed. The program waits for a non-whitespace character. Once a line of input is entered and at least one non-whitespace character is present in the line, the first non-white character of the line is read into ch. This is because stdin is typically line buffered.
Almost all format specifiers in scanf automatically skip all whitespace before trying to read anything. That's, for example, how %d works (as well as %s, %f and most other specifiers). However, %c is an exception from this behavior. %c does not skip whitespace. If your input data contains a whitespace character, %c will happily read that character into your ch variable.
This is most likely what happens in your case. If you enter
5 #
to create a 5x5 square of #s, the %d specifier will read 5 into x and stop reading at the space character. Then %c will read that space character into ch. And then your program will just proceed, leaving the # unread. It is quite possible that the rest of your program actually works as intended. It's just that since ch is a space character, it displays a 5x5 square of space characters, which are invisible :) To make your scanf in its original form work as intended you have to input your data as
5#
But a much better way to make sure that your scanf actually reads the # character into ch is to explicitly ask scanf to skip all whitespace before reading ch. In scanf this is done by inserting any whitespace character (space, newline, tab etc.) into the format string. This
scanf("%d %c", &x, &ch);
will force scanf to skip that space after 5 and read the # into ch. This will also work for inputs like this
5 #
and even like this
5
#
because scanf will automatically skip all whitespace until it hits the #. Note also that even with the updated format sting whitespace in the input is not required, meaning that this input
5#
will still work with the updated scanf.
You can also use these variants
scanf("%d\t%c", &x, &ch);
scanf("%d\n%c", &x, &ch);
scanf("%d %c", &x, &ch);
scanf("%d \n \t %c", &x, &ch);
to achieve the same thing. They are all equivalent. The first variant (with a space) just looks better.

Why we need to put space before %c? [duplicate]

This question already has answers here:
What does space in scanf mean? [duplicate]
(6 answers)
Closed 7 years ago.
The following code gives the bizarre o/p as soon as I compile it.
main() {
char name[3];
float price[3];
int pages[3], i;
printf ( "\nEnter names, prices and no. of pages of 3 books\n" ) ;
for ( i = 0 ; i <= 2 ; i++ )
scanf ("%c %f %d", &name[i], &price[i], &pages[i] );
printf ( "\nAnd this is what you entered\n" ) ;
for ( i = 0 ; i <= 2 ; i++ )
printf ( "%c %f %d\n", name[i], price[i], pages[i] );
}
But if we give the space in the scanf statement before %c, it gives proper o/p.
Can anyone please explain me why is it so?
Update:-
If I am providing the input like this-
F
123.45
56
J
134
67
K
145
98
then my question is why not we are giving space before %f and space before %d? Why we need to give space before %c only?
Adding the space to the format string enables scanf to consume the newline character from the input that happens everytime you press return. Without the space, name[i] will receive the char '\n', and the real char is left to be misinterpreted by %f.
So, say your input is
a 1.0 2
b 3.0 4
c 5.0 6
The program sees it more like this:
a 1.0 2\nb 3.0 4\nc 5.0 6\n\377
That is, the line-breaks are actual characters in the file (and the \377 here indicates "end of file").
The first scanf will appear to work fine, consuming a char, a float, and an integer. But it leaves the input like this:
\nb 3.0 4\nc 5.0 6\n\377
So the second scanf will read the '\n' as its %c, unless you get rid of it first.
Adding the space to the format string instructs scanf to discard any whitespace characters (any of space ' ', tab '\t', or newline '\n').
A directive is one of the following:
A sequence of white-space characters (space, tab, newline, etc.; see isspace(3)). This directive matches any amount of white space, including none, in the input.
...
from http://linux.die.net/man/3/scanf
This sort of problem arises whenever you use scanf with %c in a loop. Because, assuming free-form input, newlines can happen anywhere. So, it's common to try to avoid the whole issue by using a two-tiered approach. You read lines of input into a buffer (using fgets); chop-off the silly newline characters; then use sscanf instead of scanf to read from the buffer (string) instead of straight from the file.
Incorrect input using %c
Consider the following snippet of code:
int main( ){
int x;
char y;
scanf("%d", &x);
scanf("%c", &y);
printf("%d %c", x, y);
}
Behavior: When you run the above program, the first scanf is called
which will wait for you to enter a decimal number. Say you enter
12(That’s ASCII ‘1’ and ASCII ‘2’). Then you hit the "enter" key to
signal the end of the input. Next the program will execute the second
scanf, except you will notice that the program doesn't wait for you to
input a character and instead goes right ahead to output 12 followed
by a ‘\n’.
Explanation:Why does that happen? Let’s look at the behavior of the
program step-bystep.
Initially there is nothing in the buffer. When the first scanf() is called, it has nothing
to read, and so it waits. It keeps waiting until you type 1,2, then "enter". Now what's in
the buffer are the character 1, the character 2, and the character ‘\n’. Remember that ‘\n’
signifies the end of input, once all fields have been entered, but it is also stored in the
buffer as an ASCII character. At this point scanf will read the largest decimal input from
the buffer and convert that to an integer. In this example, it finds the string "12" and
converts it to the decimal value twelve and puts it in x. Then scanf returns control back to
the main function and returns the value 1, for being able to convert one entry
successfully. In our example, we do not catch the return value of the scanf in a variable.
For robust code, it is important to check the return value of scanf( ) to make sure that the
user inputted the correct data.
What is now left in the buffer is ‘\n’. Next, the second scanf is
called and it's expecting a character. Since the buffer already has
the ‘\n’ character in it, scanf sees that, takes it from the buffer,
and puts it in y. That's why when you execute the printf afterwards,
12 and “enter” are printed to the screen.
Solution: Moral of the story is, enter is a character like any other,
and is inputted to the buffer, and consumed from the buffer by %c just
like any other ASCII character. To fix this, try using this code
instead:
int main( ){
int x;
char y;
scanf("%d", &x);
scanf("\n%c", &y); /* note the \n !! */
printf("%d %c", x, y);
}
**
How does this fix the problem?
** So you again type ‘1’,’2’,’\n’. The first scanf reads "1" and "2", converts that to the decimal twelve and leaves the ‘\n’ in the buffer.
The next scanf now expects a ‘\n’ at the beginning of the next input.
It finds the ‘\n’ in the buffer, reads it, and discards it. Now the
buffer is empty and scanf is waiting on the user to input a character.
Say the user inputs ‘c’, followed by the enter key. ‘c’ is now
assigned to y, NOT "enter". Therefore printf will output "12 c" to the
screen. NOTE: there is again a ‘\n’ sitting in the queue now. So if
you need to do another scanf for a single character, you will have to
"consume" that '\n' before taking another character in from the user.
This is not an issue for any other format specifier, as they all ignore white spaces before
the input.

Resources