How does scanf work in this simple program? - c

I have some trouble working with scanf in a while loop.
I wanted to make a program that would ask the user to write three integers and save them in an array of three positions. If the user writes something which is not an integer, the program should continue asking for an integer until (s)he enters it. But it didn't work properly.
So I tried to simplify the problem with this code:
#include <stdio.h>
int main()
{
int num1=1;
int num2=2;
int num3=3;
printf ("write a number\n");
scanf("%i", &(num1));
printf("%i\n",num1);
printf ("write a number2\n");
scanf("%i", &(num2));
printf("%i\n",num2);
printf ("write a number3\n");
scanf("%i", &(num3));
printf("%i\n",num3);
}
If the inputs are 3 integers, there's no problem. But if you write a character, for example a, for the first integer, the other 2 values are not scanned and it simply writes:
a
2
3
The last two values are the initialization values.
Can anyone tell me what I have to do?

The scanf function does not have to read after it encounters the first invalid character in the input.
The %i specifier allows a as a hexadecimal, but it MUST be preceded by 0x.
If a was the first character in the input, and it was supposed to match to %i, then scanf wouldn't have to read anything afterwards - it can stop at the first invalid character..
References:
http://www.gidnetwork.com/b-64.html

For each conversion specifier scanf tries to locate the appropriate data item. scanf reads the item, stopping when it encounters a character that can't possibly belongs to the item. If any item is not read successfully then scanf returns immediately without looking at the rest of the format string.
When you enter a 5 10, scanf finds a for the specifier %i. It immediately returns and stops reading other inputs 5 and 10.

Related

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.

C - printf and scanf buffer

I'm sorry about the generic title, but i didn't find anything better.
And I'm sorry if the question is stupid but I'm a novice and I could not find anything of use to me.
I have written this code to solve a simple problem: you have a sequence of positive integers terminated by a negative: for every integer you have to print a corresponding amount of * characters and go to a new line.
The code DOES WORK but I can't really understand WHY.
int main()
{
int d=0,i;
while (d>=0){
scanf("%d",&d);
for (i=0;i<d;i++)
{
printf("*");
}
printf("\n");
}
return 0;
}
I did a bit of research and I understand that terminal gives the integer sequence to scanf only when I press return.
I thought it would work this way:
scanf gets the integer sequence it registers the first one while the others are discarded
prints the amount of *s corresponding to the first integer
Instead it seems that scanf reads the first integer, then printf sends it to a buffer then the cycle restarts and scanf gets the second integer and so on.
When the last positive integer is reached printf flushes the buffer.
Am I wrong? And if not, why does it work this way?
scanf() does reads the first integer, then printf sends it to a buffer then the cycle continues and scanf gets the second integer and so on. After a negative integer is reached the rest of stdin is ignored. stdout is flushed with each \n and program ending.
This should clear your ideas about scanf
http://home.datacomm.ch/t_wolf/tw/c/getting_input.html

confused about getchar and scanf

I'm really confused about the usage of getchar() and scanf(). What's the difference between these two?
I know that scanf() [and family] get a character by character from the user [or file] and save it into a variable, but does it do that immediately or after pressing something (Enter)?
and I don't really understand this code, I saw many pieces of code using getchar() and they all let you type whatever you want on the screen and no response happen, but when you press enter it quits.
int j, ch;
printf("please enter a number : \n");
while (scanf("%i", &j) != 1) {
while((ch = getchar()) != '\n') ;
printf("enter an integer: ");
}
Here in this code can't I use scanf() to get a character by character and test it? Also, what does this line mean?
scanf("%i", &j) != 1
because when I pressed 1 it doesn't differ when I pressed 2? what does this piece do?
and when this line is gonna happen?
printf("enter an integer: ");
because it never happens.
Well, scanf is a versatile utility function which can read many types of data, based on the format string, while getchar() only reads one character.
Basically,
char someCharacter = getchar();
is equivalent to
char someCharacter;
scanf("%c", &someCharacter);
I am not 100% sure, but if you only need to read one character, getchar() might be 'cheaper' than scanf(), as the overhead of processing the format string does not exist (this could count to something if you read many characters, like in a huge for loop).
For the second question.
This code:
scanf("%i", &j) != 1
means you want scanf to read an integer in the variable 'j'. If read successfully, that is, the next input in the stream actually is an integer, scanf will return 1, as it correctly read and assigned 1 integer.
See the oldest answer to this SO question for more details on scanf return values.
As far as I understand,
the getchar function will read your input one character at a time.
scanf will read all types of data, and will be more useful to define a data group.
However, as far as strings go, my teacher recommends using gets instead of scanf. This is because scanf will stop 'getting' the data at the first white space you put in, like in a sentence...
while (scanf("%i", &j) != 1) {
while((ch = getchar()) != '\n') ;
printf("enter an integer: ");
}
Here's how this code breaks down.
scanf() consumes individual characters from the input stream until it sees a character that does not match the %i conversion specifier1, and that non-matching character is left in the input stream;
scanf() attempts to convert the input text into a value of the appropriate type; i.e., if you enter the string "1234\n", it will be converted to the integer value 1234, the converted value will be assigned to the variable j, and the '\n' will be left in the input stream;
if there are no characters in the input string that match the conversion specifier (such as "abcd"), then no conversion is performed and nothing is assigned to j;
scanf() returns the number of successful conversions and assignments.
if the result of the scanf() call is not 1, then the user did not enter a valid integer string;
since non-matching characters are left in the input stream, we need to remove them before we can try another scanf() call, so we use getchar() to consume characters until we see a newline, at which point we prompt the user to try again and perform the scanf() call again.
1. The %i conversion specifier skips over any leading whitespace and accepts optionally signed integer constants in octal, decimal, or hexadecimal formats. So it will accept strings of the form [+|-]{0x[0-9a-fA-F]+ | 0[0-7]+ | [1-9][0-9]*}
The scanf can scan arbitrarily formatted data and parse it as multiple types (integers, floating point, strings, etc). The getchar function just gets a single character and returns it.
The expression
scanf("%i", &j) != 1
reads a (possibly signed) integer from the standard input, and stores it in the variable j. It then compares the return value of the scanf function (which returns the number of successfully scanned conversions) and compares it to 1. That means the expression will be "true" if scanf didn't read or converted an integer value. So the loop will continue to loop as long as scanf fails.
You might want to check this scanf reference.
That the printf doesn't happen might be either because it never happens (use a debugger to find out), or it just seemingly doesn't happen but it really does because the output needs to be flushed. Flushing output is done either by printing a newline, or with the fflush function:
fflush(stdout);
As far as I know, scanf will read user input until the first whitespace, considering the input format specified. getchar, however, reads only a single character.
scanf will return the number of arguments of the format list that were successfully read, as explained here. You obtain the same result when pressing 1 or 2 because both of them are successfully read by the %i format specifier.
getchar reads one char at a time from input. where as scanf can read more depending upon the data type u specify.
its not good practice to use scanf() try using fgets(), its much more efficient and safe than scanf.

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.

Why does scanf not terminate when I expect it to

If I write a C program then it will not automatically get out of if else like ....
#include<stdio.h>
int main ()
{
int a, b, c, d;
printf ("enter the value ");
scanf("%d %d %d ",&a,&b,&c);
d=a+b+c;
if(d==180)
printf("triangle is valid ");
else
printf("triangle is invalid ");
return 0;
}
then it will not terminate itself.....
Can anyone help to figure out what the problem in this .....
It's the space at the end of the scanf format string. Remove that space and your program will terminate.
I guess there is inconsistency between the scanf() format string and the format you enter your data in. But seriously, you should accept some old answers before asking new questions.
Omit the spaces in the scanf string
scanf("%d%d%d",&a,&b,&c);
scanf function normally skip the space between the inputs.
In your code you ask the input in the following format
scanf("%d %d %d ",&a,&b,&c);
It is represent the 1input as 1 space,1input and 1 space, 1input and 1 space.
So if you give the three input after the enter, it will skip the new line also.
Because scanf function will take the input as non white space character.
To avoid this you need to give the 4 input. So that time, the first three inputs are stored in the variable a b c, Then next space and values are stored in the buffer.
After run the program you need to give the input like the folllowing
12 12 12 12
Here the first three inputs are stored in the a b c variables.
Otherwise your scanf format should be the following format
scanf("%d%d%d",&a,&b,&c);

Resources