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

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.

Related

What is the difference between scanf("%s", &str) and scanf("%s\n", &str)?

Input
There will be several lines in the input terminated with a line containing a single *. This last line
should not be processed. Each of the lines will contain either Hajj or Umrah.
Output
For each line of the input, output either Hajj-e-Akbar or Hajj-e-Asghar in separate lines without
quotations. For the exact format refer to the sample.
Here's my code for this problem.
#include <stdio.h>
int main()
{
char str[100];
int i = 1;
while (scanf("%s", &str))
{
if (str[0] == '*')
break;
else if (str[0] == 'H')
printf("Case %d: Hajj-e-Akbar\n", i);
else
printf("Case %d: Hajj-e-Asghar\n", i);
i++;
}
}
For the input
Hajj
Umrah
*
When I gave this input at a time, the program provides the expected output by printing
Hajj
Case 1: Hajj-e-Akbar
Umrah
Case 2: Hajj-e-Asghar
*
But after getting * as input, the program is waiting for an Enter. After hitting Enter, the program terminates. But I want my program to terminate, whenever it gets * as input, not by pressing Enter. Please help me here. But this is not my question. My question is for the same input-
Hajj
Umrah
*
When I take input by scanf("%s\n", &str). The program does not print the output Case 1: Hajj-e-Akbar after the first input Hajj but it prints the output for first input after taking the second input Umrah. Then the program is waiting for an Enter for the input *.
The output is like this
Hajj
Umrah
Case 1: Hajj-e-Akbar
*
Then I press Enter, it prints the output Case 2: Hajj-e-Asghar for the second input Umrah
and then waits for another input. This the output looks like after pressing Enter.
Hajj
Umrah
Case 1: Hajj-e-Akbar
*
Case 2: Hajj-e-Asghar
I don't understand how \n is making a difference in scanf.
Thank you.
I'm sorry if I can't explain my question correctly. I am new to programming.
scanf reads formated input, so when you use %s\n”, &str the string will consumed and stored in str as will the newline character , which will be present in the buffer when you press enter, the string will be stored and the newline character will be discarded.
Note that the correct usage is “%s\n”, str, str is already a pointer you shouldn't use &.
When you use “%s”, &str the newline character will be left in the buffer and will be consumed in the next loop, so str will be stored in the first iteration, and "\n" will be stored in str in the next iteration, only then you will be asked for input again, in the third iteration.
For completion, as stated in the comments bellow, as per the definition of scanf:
...any single whitespace character in the format string consumes all available consecutive whitespace characters from the input (determined as if by calling isspace in a loop). Note that there is no difference between "\n", " ", "\t\t", or other whitespace in the format string.
I would also advise you to limit the size of the string expected by scanf to avoid container overflow, something like %99s for a 100 charaters container like you have, and also check scanf return, in this case, it must be = 1 for each cycle.
To do what you want, which I gather is to get a character from stdin without pressing return you will need a SO specific method, here is a small example for Windows using <conio.h> library, and getch():
#include <stdio.h>
#include <conio.h>
int main()
{
int i = 1, c;
while (1)
{
if ((c = getch()) == '*')
return 0;
else if (c == 'H')
printf("Case %d: Hajj-e-Akbar\n", i);
else
printf("Case %d: Hajj-e-Asghar\n", i);
i++;
}
}
For Linux one option is to use also getch() from <ncurses.h> library, which you might need to install.
PS: Don't worry, your question is well built, specially being only the second in the site.
The trailing \n in the scanf is a bad idea: any whitespace character in the format string causes any sequence of whitespace characters to be discarded from the input stream. If reading from a file, you will not necessary have a problem but if you read from the terminal, scanf() will not return until you have typed the next item, and this will create major confusion as you experience, because the program's output will correspond to the previous item, not the one that was just typed... Never add trailing spaces or newlines in a scanf() format string.
You should test if scanf() returns 1 to avoid an infinite loop when it returns EOF at the end of file.
Note also that it is incorrect to pass &str: str is an array, passing it as str will effectively pass a pointer to its first element, which is correct.
Furthermore, you should tell scanf() the maximum number of characters that can be stored into the destination array to avoid undefined behavior on overlong input. Since the array is defined with a size of 100, the format string should be "%99s" to leave space for the null terminator.
Finally, you need to hit Enter after the final * for 3 combined reasons, each of which would force this behavior:
the terminal device driver is line buffered by default, so the input is not made available to the program until you type Enter.
the standard input stream (stdin) is line buffered by default, so it will read data from the system handle until it gets a newline, and only then does scanf() get a chance to see the first character of the entered line.
scanf("%s", str) will keep its input stream until it gets the end of the word, a whitespace character or the end of file, so it does not return when you type just *.
Here is a modified version:
#include <stdio.h>
int main() {
char str[100];
int i = 1;
while (scanf("%99s", str) == 1 && str[0] != '*') {
if (str[0] == 'H') {
printf("Case %d: Hajj-e-Akbar\n", i);
} else {
printf("Case %d: Hajj-e-Asghar\n", i);
}
i++;
}
return 0;
}

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

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.

Input taking spaces by default in c

In the below program when am reading input from keyboard its taking only 2 characters instead of 4 and remaining 2 characters its taking spaces by default.
why is it???
program to take char input through pointers/
int c,inc,arrysize;
char *revstring;
printf("enter the size of char arry:");
scanf("%d",&arrysize);
revstring = (char *)malloc(arrysize * sizeof(*revstring));
printf("%d",sizeof(revstring));
printf("enter the array elements:");
for(inc=0;inc<arrysize;inc++)
{
scanf("%c",&revstring[inc]);
}
for(inc =0;inc<arrysize;inc++)
printf("%c",revstring[inc]);
getch();
return 0;
}
scanf reads formatted inputs. When you tape a number, you tape the digits, and then, you press <Enter>. So there is a remaining \n in stdin, which is read in the next scanf. The same applies if you press <Enter> between the characters.
A solution is to consume the characters in the standard input stream after each input, as follow:
#include <stdio.h>
void
clean_stdin (void)
{
int c;
while ((c = getchar ()) != '\n' && c != EOF)
;
}
Another idea is to use fgets to get human inputs. scanf is not suitable for such readings.
Most of the time scanf reads formatted input. For most % formats, scanf will first read and discard any whitespace and then parse the item specified. So with scanf("%d", ... it will accept inputs with initial spaces (or even extra newlines!) with no problems.
One of the exceptions, however, is %c. With %c, scanf reads the very next character, whatever it may be. If that next character is a space or newline, that is what you get.
Depending on what exactly you want, you may be able to just use a blank space in your format string:
scanf(" %c",&revstring[inc]);
The space causes scanf to skip any whitespace in the input, giving you the next non-whitespace character read. However, this will make it impossible to enter a string with spaces in it (the spaces will be ignored). Alternately, you could do scanf(" "); before the loop to skip whitespace once, or scanf("%*[^\n]"); scanf("%*c"); to skip everything up to the next newline, and then skip the newline.

Resources