Scanf reads wrong value - c

I’m new to C programming language, I have wrote a simple code that reads two “char” values and prints them on the screen but the second one got empty value for a strange reason. What’s going wrong with my code?
Char c;
Scanf(“%c”,&c);
Printf(“Value:%c”,c);
Scanf(“%c”,&c);
Printf(“Value:%c”,c);
Output:
Value:g
Value:

(This is a comment, but comments are hard to format)
There's nothing wrong with your code (other than the failure to check the value returned by scanf and deal with errors or incorrect input). Consider:
#include <stdio.h>
int
main(void)
{
char c;
scanf("%c",&c);
printf("Value:%c",c);
scanf("%c",&c);
printf("Value:%c",c);
return 0;
}
$ gcc a.c
$ printf 'abc' | ./a.out
Value:aValue:b
Perhaps what's "wrong" is that you have newlines in your input. (eg, you are entering data interactively and forgetting that when you hit "return" a newline is inserted into the input stream.)

If your goal was to read two "interesting" characters, and if you don't think that whitespace characters like space and newline are "interesting", you've been tripped up by number six out of the seventeen things about scanf that are designed to trip up the unwary: %c does read whitespace characters.
If you want scanf to skip over whitespace characters, so that %c will read the next, non-whitespace or "interesting" character, simply include a space character in the format string before the %c:
char c;
scanf(" %c", &c);
printf("Value: %c\n",c);
scanf(" %c", &c);
printf("Value: %c\n",c);
In a scanf format string, the presence of a whitespace character indicates that you want scanf to skip over all whitespace at that point in the input.
Normally you don't have to worry about skipping whitespace with scanf, because most of the other format specifiers -- %d, %f, %s, etc. -- automatically skip over any whitespace, if necessary, before they start parsing their input. But %c is special: someone thought you might want to use it to read whitespace characters, so it doesn't skip them, so if you don't want to read them, you have to skip them yourself, with that space character in the format string first.

Related

Why does the 2nd iteration not execute the expected printf in the loop and even takes one extra input to show the final output? [duplicate]

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *method1(void)
{
static char a[4];
scanf("%s\n", a);
return a;
}
int main(void)
{
char *h = method1();
printf("%s\n", h);
return 0;
}
When I run the code above, the prompt is asking me twice for input (I only use scanf once in the code). Why is that?
(I entered 'jo'; it asked for more input, so I entered 'jo' again. Then it only printed out 'jo' once.)
From my scanf manual page
White space (such as blanks, tabs, or newlines) in the format string match any amount of white space, including none, in the input. Everything else matches only itself.
Thus with scanf ("%s\n", a) it will scan for a string followed by optional white space. Since after the first newline more whitespace may follow, scanf is not done after the first newline and looks what's next. You will notice that you can enter any number of newlines (or tabs or spaces) and scanf will still wait for more.
However, when you enter the second string, the sequence of whitespace is delimited and scanning stops.
Use scanf ("%s", a) to not scan trailing whitespace.
you have to remove the \n from the string format of the scanf. It should be
scanf("%s",a);
EDIT: Explanation
the %s means that the scanf reads the input character till it gets a delimiter which should be a white space like space or tab or new line(\n) so the first enter is get as a delimiter for the "%s" and adding the "\n" to the string format "%s\n" means that the scanf will wait 2 newlines the first newline is related to the delimiter of the "%s" and the second newline is related to the\n of the string format.
Remove \n from the scanf format and give an input and it displays the output based on the given output once.
you can use either of these to avoid the mentioned problem :
scanf("%s",a);
or
scanf("\n%s",a);
Try this: Don't use \n on scanf, it won't ask you twice and sometimes it might show an error
Your code: scanf("%s\n", a);
Try this on scanf: scanf("%s", a);
use gets() or fgets() instead...alternatively use scanf("%[^\n]s",a);
Don't use the escape sequence in scanf stdio function
scanf ("%s", a);

Why is this creating two inputs instead of one

https://i.imgur.com/FLxF9sP.png
As shown in the link above I have to input '<' twice instead of once, why is that? Also it seems that the first input is ignored but the second '<' is the one the program recognizes.
The same thing occurs even without a loop too.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(){
int randomGen, upper, lower, end, newRandomGen;
char answer;
upper = 100;
lower = 1;
end = 1;
do {
srand(time(0));
randomGen = rand()%(upper + lower);
printf("%d\n", randomGen);
scanf("%s\n", &answer);
}while(answer != '=');
}
Whitespace in scanf format strings, like the \n in "%c\n", tries to match any amount of whitespace, and scanf doesn’t know that there’s no whitespace left to skip until it encounters something that isn’t whitespace (like the second character you type) or the end of input. You provide it with =\n, which fills in the %c and waits until the whitespace is over. Then you provide it with another = and scanf returns. The second time around, the character could be anything and it’d still work.
Skip leading whitespace instead (and use the correct specifier for one character, %c, as has been mentioned):
scanf(" %c", &answer);
Also, it’s good practice to make sure you actually succeeded in reading something, especially when failing to read something means leaving it uninitialized and trying to read it later (another example of undefined behaviour). So check scanf’s return value, which should match the number of conversion specifiers you provided:
if (scanf(" %c", &answer) != 1) {
return EXIT_FAILURE;
}
As has been commented, you should not use the scanf format %s if you want to read a single character. Indeed, you should never use the scanf format %s for any purpose, because it will read an arbitrary number of characters into the buffer you supply, so you have no way to ensure that your buffer is large enough. So you should always supply a maximum character count. For example, %1s will read only one character. But note: that will still not work with a char variable, since it reads a string and in C, strings are arrays of char terminated with a NUL. (NUL is the character whose value is 0, also sometimes spelled \0. You could just write it as 0, but don't confuse that with the character '0' (whose value is 48, in most modern systems).
So a string containing a single character actually occupies two bytes: the character itself, and a NUL.
If you just want to read a single character, you could use the format %c. %c has a few differences from %s, and you need to be aware of all of them:
The default maximum length read by %s is "unlimited". The default for %c is 1, so %c is identical to %1c.
%s will put a NUL at the end of the characters read (which you need to leave space for), so the result is a C string. %c does not add the NUL, so you only need to leave enough space for the characters themselves.
%s skips whitespace before storing any characters. %c does not ignore whitespace. Note: a newline character (at the end of each line) is considered whitespace.
So, based on the first two rules, you could use either of the following:
char theShortString[2];
scanf("%1s", theShortString);
char theChar = theShortString[0];
or
char theChar;
scanf("%c", &theChar);
Now, when you used
scanf("%s", &theChar);
you will cause scanf to write a NUL (that is, a zero) in the byte following theChar, which quite possibly is part of a different variable. That's really bad. Don't do that. Ever. Even if you get away with it today, it will get you into serious trouble some time soon.
But that's not the problem here. The problem here is with what comes after the %s format code.
Let's take a minute (ok, maybe half an hour) to read the documentation of scanf, by typing man scanf. What we'll see, quite near the beginning, is: (emphasis added)
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.
So when you use "%s\n", scanf will do the following:
skip over any white-space characters in the input buffer.
read the following word up to but not including the next white-space character, and store it in the corresponding argument, followed by a NUL.
skip over any white-space following the word which it just read.
It does the last step because \n — a newline — is itself white-space, as noted in the quote from the manpage.
Now, what you actually typed was < followed by a newline, so the word read at step 2 will be just he character <. The newline you typed afterwards is white-space, so it will be ignored by step 3. But that doesn't satisfy step 3, because scanf (as documented) will ignore "any amount of white space". It doesn't know that there isn't more white space coming. You might, for example, be intending to type a blank line (that is, just a newline), in which case scanf must skip over that newline as well. So scanf keeps on reading.
Since the input buffer is now empty, the I/O library must now read the next line, which it does. And now you type another < followed by a newline. Clearly, the < is not white-space, so scanf leaves it in the input buffer and returns, knowing that it has done its duty.
Your program then checks the word read by scanf and realises that it is not an =. So it loops again, and the scanf executes again. Now there is already data in the input buffer (the second < which you typed), so scanf can immediately store that word. But it will again try to skip "any amount of white space" afterwards, which by the same logic as above will cause it to read a third line of input, which it leaves in the input buffer.
The end result is that you always need to type the next line before the previous line is passed back to your program. Obviously that's not what you want.
So what's the solution? Simple. Don't put a \n at the end of your format string.
Of course, you do want to skip that newline character. But you don't need to skip it until the next call to scanf. If you used a %1s format code, scanf would automatically skip white-space before returning input, but as we've seen above, %c is far simpler if you only want to read a single character. Since %c does not skip white-space before returning input, you need to insert an explicit directive to do so: a white-space character. It's usual to use an actual space rather than a newline for this purpose, so we would normally write this loop as:
char answer;
srand(time(0)); /* Only call srand once, at the beginning of the program */
do {
randomGen = rand()%(upper + lower); /* This is not right */
printf("%d\n", randomGen);
scanf(" %c", &answer);
} while (answer != '=');
scanf("%s\n", &answer);
Here you used the %s flag in the format string, which tells scanf to read as many characters as possible into a pre-allocated array of chars, then a null terminator to make it a C-string.
However, answer is a single char. Just writing the terminator is enough to go out of bounds, causing undefined behaviour and strange mishaps.
Instead, you should have used %c. This reads a single character into a char.

what is the significance of newline character in the format string of scanf function?

#include<stdio.h>
int main()
{
int a,b;
printf("enter two numbers ");
scanf("%d \n%d",&a,&b);
printf("%d %d",a,b);
return 0;
}
when I give inputs like 3 and 5 , then the issue is that even if I give inputs without any newline character in between them then also the scanf function scans the input value , but in the formal string I have stated that the next input should be scanned after a newline character so how can the next input be scanned just after some few whitespaces .
White-space in the scanf format string tells scanf (and family) to read and ignore white-space in the input. It doesn't matter what kind of white-space character you use in the format: Space, newlines and tabs are all the same.
However, you don't actually need it for all formats. most scanf formats automatically reads and ignore leading white-space, including the "%d" format.
The " \n" in the "%d \n%d" format string will "eat" all whitespace characters as defined by isspace, including newlines.
To force reading the integers off separate lines, use this instead:
if(scanf("%d%*[^\n]\n%d",&a,&b) != 2) return EXIT_ERROR;

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 does scanf ask twice for input when there's a newline at the end of the format string?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *method1(void)
{
static char a[4];
scanf("%s\n", a);
return a;
}
int main(void)
{
char *h = method1();
printf("%s\n", h);
return 0;
}
When I run the code above, the prompt is asking me twice for input (I only use scanf once in the code). Why is that?
(I entered 'jo'; it asked for more input, so I entered 'jo' again. Then it only printed out 'jo' once.)
From my scanf manual page
White space (such as blanks, tabs, or newlines) in the format string match any amount of white space, including none, in the input. Everything else matches only itself.
Thus with scanf ("%s\n", a) it will scan for a string followed by optional white space. Since after the first newline more whitespace may follow, scanf is not done after the first newline and looks what's next. You will notice that you can enter any number of newlines (or tabs or spaces) and scanf will still wait for more.
However, when you enter the second string, the sequence of whitespace is delimited and scanning stops.
Use scanf ("%s", a) to not scan trailing whitespace.
you have to remove the \n from the string format of the scanf. It should be
scanf("%s",a);
EDIT: Explanation
the %s means that the scanf reads the input character till it gets a delimiter which should be a white space like space or tab or new line(\n) so the first enter is get as a delimiter for the "%s" and adding the "\n" to the string format "%s\n" means that the scanf will wait 2 newlines the first newline is related to the delimiter of the "%s" and the second newline is related to the\n of the string format.
Remove \n from the scanf format and give an input and it displays the output based on the given output once.
you can use either of these to avoid the mentioned problem :
scanf("%s",a);
or
scanf("\n%s",a);
Try this: Don't use \n on scanf, it won't ask you twice and sometimes it might show an error
Your code: scanf("%s\n", a);
Try this on scanf: scanf("%s", a);
use gets() or fgets() instead...alternatively use scanf("%[^\n]s",a);
Don't use the escape sequence in scanf stdio function
scanf ("%s", a);

Resources