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

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.

Related

is the function of fflush(stdin) similar to that of scanf("%*[^\n]%*c")? [duplicate]

I want to make a loop in C that, when the program asks for an integer and the user types a non-digit character, the program asks again for an integer.
I just found the below code. but I don't understand what this means scanf("%*[^\n]%*c"). What does ^\n mean? What does the * before ^\n and c mean?
/*
This program calculate the mean score of an user 4 individual scores,
and outputs the mean and a final grade
Input: score1, score2,score2, score3
Output: Mean, FinalGrade
*/
#include <stdio.h>
//#include <stdlib.h>
int main(void){
int userScore = 0; //Stores the scores that the user inputs
float meanValue = 0.0f; //Stores the user mean of all the notes
char testChar = 'f'; //Used to avoid that the code crashes
char grade = 'E'; //Stores the final
int i = 0; //Auxiliar used in the for statement
printf("\nWelcome to the program \n Tell me if Im clever enough! \n Designed for humans \n\n\n");
printf("Enter your 4 notes between 0 and 100 to calculate your course grade\n\n");
// Asks the 4 notes.
for ( ; i<=3 ; i++ ){
printf("Please, enter your score number %d: ", i+1);
//If the note is not valid, ask for it again
//This is tests if the user input is a valid integer.
if ( ( scanf("%d%c", &userScore, &testChar)!=2 || testChar!='\n')){
i-=1;
scanf("%*[^\n]%*c");
}else{ //Enter here if the user input is an integer
if ( userScore>=0 && userScore<=100 ){
//Add the value to the mean
meanValue += userScore;
}else{ //Enter here if the user input a non valid integer
i-=1;
//scanf("%*[^\n]%*c");
}
}
}
//Calculates the mean value of the 4 scores
meanValue = meanValue/4;
// Select your final grade according to the final mean
if (meanValue>= 90 && meanValue <=100){
grade = 'A';
} else if(meanValue>= 80 && meanValue <90){
grade = 'B';
} else if (meanValue>= 70 && meanValue <80){
grade = 'C';
} else if(meanValue>= 60 && meanValue <70){
grade = 'D';
}
printf("Your final score is: %2.2f --> %c \n\n" , meanValue, grade);
return 0;
}
Breakdown of scanf("%*[^\n]%*c"):
%*[^\n] scans everything until a \n, but doesn't scan in the \n. The asterisk(*) tells it to discard whatever was scanned.
%*c scans a single character, which will be the \n left over by %*[^\n] in this case. The asterisk instructs scanf to discard the scanned character.
Both %[ and %c are format specifiers. You can see what they do here. The asterisks in both the specifiers tell scanf, not to store the data read by these format specifiers.
As #chux commented below, it will clear a single line of the stdin (Standard Input Stream) up to and including the newline character. In your case, the line with invalid input gets cleared from the stdin.
It is better to use
scanf("%*[^\n]");
scanf("%*c");
to clear the stdin. This is because, in the former case (single scanf), %*[^\n] will fail when the first character to be scanned is the \n character and the rest of the format string of the scanf will be skipped which means that the %*c will not function and thus, the \n from the input will still be in the input stream. In this case, this will not happen as even when the first scanf fails, the second one will execute as they are separate scanf statements.
You can take a string as input in C using scanf(“%s”, s). But, it accepts string only until it finds the first space.
In order to take a line as input, you can use scanf("%[^\n]%*c", s); where s is defined as char s[MAX_LEN] where MAX_LEN is the maximum size of s. Here, [] is the scanset character. ^\n stands for taking input until a newline isn't encountered. Then, with this %*c, it reads the newline character and here, the used * indicates that this newline character is discarded.
Suppose char sen[max_length] where maximum length is maximum size of sen[].
this scanf(“%[^\n]%*c”,&sen[]); will help you to get a entire sentence until the next line isn’t encountered “\n” or enter is pressed which is done with the help of “%[^\n]” here [ ] is the scan set character . the ”%*c” will read the newline character , asterisk ” * ” is used to indicate that the next line character is discarded.
%[^\n]%*c
Which will read everything up to the newline into the string you pass in, then will consume a single character (the newline) without assigning it to anything (that '*' is 'assignment suppression').
Otherwise,the newline is left in the input stream waiting to immediately terminate the the subsequent %[^\n] format directives.
The problem with adding a space character to the format directive (%[^\n]) is that the space will match any white space. So, it will eat the newline from the end of the previous input, but it will also eat any other whitespace (including multiple newlines).
Essentially this is two reads using scanf. The first part "%[^\n]"
means 'read everything that is not a newline' and this is assigned to
the character buffer str.
The second part "%*c" means 'read the next character but don't save it
anywhere'; this gets rid of the newline that we didn't read in the
first part.
https://www.sololearn.com/Discuss/2249429/what-s-the-use-of-scanf-n-c-in-c-programming
In order to take a line as input, you can use scanf("%[^\n]%*c", s); where is defined as char s[MAX_LEN] where is the maximum size of . Here, [] is the scanset character. ^\n stands for taking input until a newline isn't encountered. Then, with this %*c, it reads the newline character and here, the used * indicates that this newline character is discarded.

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.

What does `scanf("%*[^\n]%*c")` mean?

I want to make a loop in C that, when the program asks for an integer and the user types a non-digit character, the program asks again for an integer.
I just found the below code. but I don't understand what this means scanf("%*[^\n]%*c"). What does ^\n mean? What does the * before ^\n and c mean?
/*
This program calculate the mean score of an user 4 individual scores,
and outputs the mean and a final grade
Input: score1, score2,score2, score3
Output: Mean, FinalGrade
*/
#include <stdio.h>
//#include <stdlib.h>
int main(void){
int userScore = 0; //Stores the scores that the user inputs
float meanValue = 0.0f; //Stores the user mean of all the notes
char testChar = 'f'; //Used to avoid that the code crashes
char grade = 'E'; //Stores the final
int i = 0; //Auxiliar used in the for statement
printf("\nWelcome to the program \n Tell me if Im clever enough! \n Designed for humans \n\n\n");
printf("Enter your 4 notes between 0 and 100 to calculate your course grade\n\n");
// Asks the 4 notes.
for ( ; i<=3 ; i++ ){
printf("Please, enter your score number %d: ", i+1);
//If the note is not valid, ask for it again
//This is tests if the user input is a valid integer.
if ( ( scanf("%d%c", &userScore, &testChar)!=2 || testChar!='\n')){
i-=1;
scanf("%*[^\n]%*c");
}else{ //Enter here if the user input is an integer
if ( userScore>=0 && userScore<=100 ){
//Add the value to the mean
meanValue += userScore;
}else{ //Enter here if the user input a non valid integer
i-=1;
//scanf("%*[^\n]%*c");
}
}
}
//Calculates the mean value of the 4 scores
meanValue = meanValue/4;
// Select your final grade according to the final mean
if (meanValue>= 90 && meanValue <=100){
grade = 'A';
} else if(meanValue>= 80 && meanValue <90){
grade = 'B';
} else if (meanValue>= 70 && meanValue <80){
grade = 'C';
} else if(meanValue>= 60 && meanValue <70){
grade = 'D';
}
printf("Your final score is: %2.2f --> %c \n\n" , meanValue, grade);
return 0;
}
Breakdown of scanf("%*[^\n]%*c"):
%*[^\n] scans everything until a \n, but doesn't scan in the \n. The asterisk(*) tells it to discard whatever was scanned.
%*c scans a single character, which will be the \n left over by %*[^\n] in this case. The asterisk instructs scanf to discard the scanned character.
Both %[ and %c are format specifiers. You can see what they do here. The asterisks in both the specifiers tell scanf, not to store the data read by these format specifiers.
As #chux commented below, it will clear a single line of the stdin (Standard Input Stream) up to and including the newline character. In your case, the line with invalid input gets cleared from the stdin.
It is better to use
scanf("%*[^\n]");
scanf("%*c");
to clear the stdin. This is because, in the former case (single scanf), %*[^\n] will fail when the first character to be scanned is the \n character and the rest of the format string of the scanf will be skipped which means that the %*c will not function and thus, the \n from the input will still be in the input stream. In this case, this will not happen as even when the first scanf fails, the second one will execute as they are separate scanf statements.
You can take a string as input in C using scanf(“%s”, s). But, it accepts string only until it finds the first space.
In order to take a line as input, you can use scanf("%[^\n]%*c", s); where s is defined as char s[MAX_LEN] where MAX_LEN is the maximum size of s. Here, [] is the scanset character. ^\n stands for taking input until a newline isn't encountered. Then, with this %*c, it reads the newline character and here, the used * indicates that this newline character is discarded.
Suppose char sen[max_length] where maximum length is maximum size of sen[].
this scanf(“%[^\n]%*c”,&sen[]); will help you to get a entire sentence until the next line isn’t encountered “\n” or enter is pressed which is done with the help of “%[^\n]” here [ ] is the scan set character . the ”%*c” will read the newline character , asterisk ” * ” is used to indicate that the next line character is discarded.
%[^\n]%*c
Which will read everything up to the newline into the string you pass in, then will consume a single character (the newline) without assigning it to anything (that '*' is 'assignment suppression').
Otherwise,the newline is left in the input stream waiting to immediately terminate the the subsequent %[^\n] format directives.
The problem with adding a space character to the format directive (%[^\n]) is that the space will match any white space. So, it will eat the newline from the end of the previous input, but it will also eat any other whitespace (including multiple newlines).
Essentially this is two reads using scanf. The first part "%[^\n]"
means 'read everything that is not a newline' and this is assigned to
the character buffer str.
The second part "%*c" means 'read the next character but don't save it
anywhere'; this gets rid of the newline that we didn't read in the
first part.
https://www.sololearn.com/Discuss/2249429/what-s-the-use-of-scanf-n-c-in-c-programming
In order to take a line as input, you can use scanf("%[^\n]%*c", s); where is defined as char s[MAX_LEN] where is the maximum size of . Here, [] is the scanset character. ^\n stands for taking input until a newline isn't encountered. Then, with this %*c, it reads the newline character and here, the used * indicates that this newline character is discarded.

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

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

Resources