Why this C scanf is automatically skipped? [duplicate] - c

This question already has answers here:
How to read / parse input in C? The FAQ
(1 answer)
scanf() leaves the newline character in the buffer
(7 answers)
Closed 6 years ago.
I am facing problem regarding scanf in C. When I run this:
char c;
int a, b;
scanf("%d", &a);
scanf("%c", &c);
scanf("%d", &b);
Then first two scanf were working properly but 3rd one is skipped completely. I searched different posts in this forum about this problem and found a lot of information, but want to know something else.
I already found that the easiest solution would be:
scanf("%d %c %d", &a, &c, &b);
And another solution could be using:
getchar();
And I also found that the reason behind my problem is it writes an extra new line character \n to the buffer, that's why the 3rd one was skipped. But for further researching I found that when I use another scanf of char type after 2nd scanf then it works. That means, in my case the problem occurs if I take input of any integer type after char type. Again I have seen many others were problem having opposite case, they couldn't take input of char after integer. Now I want to be clarified about the exact schemes those are supported in C for scanf that is when I will face similar problems and why char can be scanned after char but integer can't. Thanks to all.

The "%d" format specifier includes skipping leading white-space. The "%c" format doesn't have that, it reads the next character in the input buffer no matter what kind of character it is.
If you want to skip leading white-space using the "%c" format, you need to tell scanf explicitly to do so with a space in the format string, like e.g. " %c".

This is the same problem as "not able to take char after an int", with a small twist.
Recall that when you read an int from an input using scanf with %d format specifier, the characters representing the number are consumed, but the separator following it is not. Consider a buffer that looks like this (I use underscores to show spaces):
char 9 8 _ x _ 7 6
- - - - - - -
position 0 1 2 3 4 5 6
Before the first scanf call your buffer is positioned at zero.
After the first call your buffer is positioned at 2.
After the second call your buffer is positioned at 3, because space is read for your char
Now the problem becomes clear: the third scanf tries to read an int, but the buffer is at x, so the read is not possible.

Related

Wanting scanf to proceed without all parameters filled [duplicate]

This question already has answers here:
How to make that scanf is optionally ignoring one of its conversion specifiers?
(4 answers)
Closed 2 years ago.
I want to have a scanf function that allows the user to input up to four integers separated by spaces but still run if only 2 integers are put in.
scanf("%d %d %d %d", &command, &num_one, &num_two, &num_three);
scanf does exactly that. It returns the number of successful conversions it performed. If it cannot perform a conversion (or cannot match a literal character), it stops reading precisely at that point.
You should always check its return value, even if the examples you are copying don't do that.
What scanf doesn't guarantee is that the values converted are separated by spaces. They might be separated by newlines. If you want a newline character to stop the scan, you need to read the line using something like fgets (or, better if possible, the Posix getline function), and then call sscanf on the line which was read.
You could also force scanf to stop at the end of the line by using %*[ \t] instead of to separate the %ds, which will only match space and tab characters. (The * causes scanf to not try to save the matched string, and also to not count the conversion in its return count.) But that will run you into the other problem with scanf: if there is garbage in the line, you normally want to continue reading with the next line. The getline/sscanf solution will do that for you. If you use scanf, you'll need to manually flush the rest of the input line, which requires calling fgets or getline anyway.
And while I'm at it, note that there is no difference between scanf("%d %d %d %d", ...) and scanf("%d%d%d%d", ...), because %d, like all scanf conversions other than %c, %[ and %%, skips leading whitespace.

Program is skipping 2nd switch [duplicate]

This question already has answers here:
How to read / parse input in C? The FAQ
(1 answer)
scanf() leaves the newline character in the buffer
(7 answers)
Closed 6 years ago.
I am facing problem regarding scanf in C. When I run this:
char c;
int a, b;
scanf("%d", &a);
scanf("%c", &c);
scanf("%d", &b);
Then first two scanf were working properly but 3rd one is skipped completely. I searched different posts in this forum about this problem and found a lot of information, but want to know something else.
I already found that the easiest solution would be:
scanf("%d %c %d", &a, &c, &b);
And another solution could be using:
getchar();
And I also found that the reason behind my problem is it writes an extra new line character \n to the buffer, that's why the 3rd one was skipped. But for further researching I found that when I use another scanf of char type after 2nd scanf then it works. That means, in my case the problem occurs if I take input of any integer type after char type. Again I have seen many others were problem having opposite case, they couldn't take input of char after integer. Now I want to be clarified about the exact schemes those are supported in C for scanf that is when I will face similar problems and why char can be scanned after char but integer can't. Thanks to all.
The "%d" format specifier includes skipping leading white-space. The "%c" format doesn't have that, it reads the next character in the input buffer no matter what kind of character it is.
If you want to skip leading white-space using the "%c" format, you need to tell scanf explicitly to do so with a space in the format string, like e.g. " %c".
This is the same problem as "not able to take char after an int", with a small twist.
Recall that when you read an int from an input using scanf with %d format specifier, the characters representing the number are consumed, but the separator following it is not. Consider a buffer that looks like this (I use underscores to show spaces):
char 9 8 _ x _ 7 6
- - - - - - -
position 0 1 2 3 4 5 6
Before the first scanf call your buffer is positioned at zero.
After the first call your buffer is positioned at 2.
After the second call your buffer is positioned at 3, because space is read for your char
Now the problem becomes clear: the third scanf tries to read an int, but the buffer is at x, so the read is not possible.

Difference between different scanf formats [duplicate]

This question already has answers here:
whitespace in the format string (scanf)
(4 answers)
Closed 6 years ago.
I'm currently prepping myself for programming school by going through the textbook. There's this particular question which I don't understand and the textbook doesn't give the answer.
PS: I've learned some C++/C# online, but never go through proper-taught programming classes, so I'm struggling with some of the concepts.
Q: For each of the following pairs of scanf format strings, indicate
whether or not the two strings are equivalent. If they are not, show
how they can be distinguished.
A) "%d" versus " %d"
B) "%d-%d-%d" versus "%d -%d -%d"
C) "%f" versus "%f "
D) "%f,%f" versus "%f, %f"
First off, I don't even understand what the question is asking. What does the textbook mean by whether or not the 2 strings are 'equivalent'?
If they are, could someone explain the differences and possibly show me how they can be distinguished?
Let us try A first: "%d" versus " %d", they are equivalent format strings for scanf().
" " will do the following. It never fails.
1) Scan and discard (skip) optional white-space.
2) After reading a non-white-space or end-of-file, if not (EOF), the last character read is put back into stdin.
"%d" itself will attempt 3 things (It can fail)
1) Scan and discard (skip) optional white-space.
2) Scan and convert numeric text representing a decimal integer.
3) After reading a non-numeric text or end-of-file, if not (EOF), the last character read is put back into stdin.
" %d" does both the above. It is the same result of just doing the 2nd with "%d".
With *scanf() specifiers note:
Input white-space characters (as specified by the isspace function) are skipped, unless the specification includes a [, c, or n specifier. C11 ยง7.21.6.2 8
B, C, D differences?
Mouse over for hint 1:
A " " before a scanf() specifier, except the 3 noted above, is an equivalent scanf() format as without it.
Mouse over for hint 2:
Only 1 of 3 equivalent.
Mouse over for hint 3:
Consider inputs:
"123 -456-789"
"123.456 x" What is the next character to be read?
B) "%d-%d-%d" versus "%d -%d -%d"
C) "%f" versus "%f "
D) "%f,%f" versus "%f, %f"
Answer:
Awww, Do you really want to be given the answer?
From Wikipedia
whitespace: Any whitespace characters trigger a scan for zero or more whitespace characters. The number and type of whitespace characters do not need to match in either direction.
scanf is about keep consuming the input and get the thing you care about. The normal char in format string means it consumes the exactly same char, and do nothing else. %d, %f could skip the leading whitespace. So, sum it up, we got:
A, it is the same, because %d skip the leading space
B, %d-%d-%d is pretty strict, it reads an integer after exactly - and then another integer and so on, so it reads 1-2-3 well, 1- 2- 3 well, too, but it fails on 1 - 2 - 3. While on the other hand, %d -%d -%d first skip spaces, read an integer, skip spaces, expect char-, then skip spaces again, and so on...
C, trailing spaces does not make a difference
D, it is the same, because %f skip leading spaces, too
So the answer would be B.

Spaces in scanf leading to abnormal results

Through my search for a solution I found this question.
Which made me think and make some experiments:
Case 1
#include<stdio.h>
main()
{ char a;
//some code
scanf("%c",&a);
/*This code might not be evaluated(missed)
sometimes*/
//This is how it is solved
scanf(" %c",&a);
//the rest of code
}
case 2
#include<stdio.h>
main()
{ int a;
//some code
scanf(" %d ",&a);
//this one will take 2 numbers instead of one
//the rest of code
}
I don't know much about c language so it would be appreciated if someone explains these results to me.(I'm using turbo c++ if it matters.)
A couple of general notes:
If you want to ask questions about C it would be beneficial for you to read about how the functions work. There is a lot of documentation available online for scanf() for example.
It's always better when you can give full compile-able examples rather than //some code
So in your first case the example would be:
char a, b;
scanf("%c", &a);
scanf("%c", &b); // this one will be "missed"
The reason is that when you enter a character in to stdin you're getting two characters really, what was typed plus an invisible newline character ('\n'). So really the second scanf isn't "missed" it's just picking up a character that doesn't have an ASCII representation.
If you printed these with:
printf("%c %d\n%c%d\n", a, a, b, b);
you would see:
>> ./my_prog
>> a
>> a 97
10
Because you entered "a\n" and the two scanf's read first the "a" then the "\n" respectively.
Using a scanf with a space before it:
scanf(" %c", &b); // this one will work instead
Will tell the scanf that any white space characters (including the newline '\n') left on stdin should be ignored.
In your second case, it's not looking for 2 numbers, it's looking for a number and a white space character. scanf(" %d ", &a) says "ignore any white space, then look for a decimal number, then look for white space". However once the variable (a) is filled it stops reading, because this is how scanf works:
A directive composed of one or more white-space characters shall be executed by reading input until no more valid input can be read, or up to the first byte which is not a white-space character, which remains unread.
So it's not really looking for another number, you can type anything at this point and it will be happy because it's just looking for another white space character to be input. So this:
scanf(" %d ", &a);
could be satisfied by this input:
>> 5
f
First the "%d" matches the 5, then the newline following the f matches the " "

Difference between scanf("%c", &c) and scanf(" %c", &c) [duplicate]

This question already has answers here:
Why does a space in my scanf statement make a difference? [duplicate]
(3 answers)
Closed 9 years ago.
Consider the following C code snippet:
#include <stdio.h>
int main()
{
int a;
char c;
scanf("%d",&a);
scanf("%c",&c);
printf("int=%d\n",a);
printf("char=%c\n",c);
}
I'm able to input only the integer and not the character.The output is simply the integer value and no value is output for the second printf statement.
However if I use a space before the format specifier:
scanf(" %c",&c);
It works as expected. Why is this the case?
Someone told me it has something to do with clearing the input buffer. Could someone shed some light on the same?
The difference between scanf("%c", &c1) and scanf(" %c", &c2) is that the format without the blank reads the next character, even if it is white space, whereas the one with the blank skips white space (including newlines) and reads the next character that is not white space.
In a scanf() format, a blank, tab or newline means 'skip white space if there is any to skip'. It does not directly 'clear the input buffer', but it does eat any white space which looks similar to clearing the input buffer (but is quite distinct from that). If you're on Windows, using fflush(stdin) clears the input buffer (of white space and non-white space characters); on Unix and according to the C standard, fflush(stdin) is undefined behaviour.
Incidentally, if you typed the integer followed immediately by a carriage return, the output of your program ends with two newlines: the first was in c and the second in the format string. Thus, you might have seen:
$ ./your_program
123
int=123
char=
$
That is, the scanf() reads the newline as its input. Consider an alternative input:
$ ./your_program
123xyz
int=123
char=x
$
The integer input stopped when it read the 'x'; the character input therefore reads the 'x'.
Because after you input the number and press ENTER, the new line stays in the buffer and will be processed by the second scanf.
In short, you saved new line in the variable c.
However ,if you use
scanf(" %c",&c);
// ^
the space will consume the new line, which makes c the value you expected.
You have to pass a pointer to the data object specified by the format string, so
scanf("%c", c);
will actually pass the value of c, which in turn could cause a program fault,
scanf("%c", &c);
will pass the address of c, allowing scanf to change the value of your copy.
The space after the %c will force it to look for a character, AND THEN a space. If there is not a space, it will not read the character

Resources