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.
So I had a code where I use
scanf("%[^\n]s",a);
and has multiple scanf to take different inputs some being string input. So I understand that scanf("%[^\n]s",a) takes input until new line has been reached, however I was wondering suppose my string can only hold up to 10 characters, then after my string has been filled, but new line hasn't been reached how can i get rid of the extra input before going to new line. I was thinking of doing getchar() until new line has been reached however in order to even check if my 10 spots has been filled I need to use getchar, so doesn't that mess up my next scanf input? Anybody have any other way to do it? Still using scanf() and getchar?
scanf("%[^\n]s",a) is a common mistake; the %[ directive is distinct from the %s directive. What you're asking from scanf is:
A group of non-'\n' characters, followed by...
A literal s character.
Perhaps you intended to write scanf("%[^\n]",a)? Note the deleted s...
You can use the * modifier to suppress assignment for a directive, for example scanf("%10[^\n]", a); followed by scanf("%*[^\n]"); to read and discard up to the next newline and getchar(); to read and discard that newline:
scanf("%10[^\n]", a);
scanf("%*[^\n]"); // read and discard up to the next newline
getchar(); // read and discard that newline
As pointed out, the two format strings could be concatenated to reduce the number of calls to scanf. I wrote my answer this way for the sake of documentation, and I'll leave it as is. Besides, I figure that attempt at optimisation would be negligible; a profiler is likely to indicate much more significant bottlenecks for optimisation in realistic scenarios.
You can use this format to hold the first 10 characters and keep the next lines of input:
scanf("%10[^\n]%*[^\n]",a);
getchar();
I want to ask a specific question and get a Y/N answer read in by the user. I will need to use the character Y or N to change the outcome of the next question eventually, which is why I need the character to be saved so I can retrieve it later. I don't want to use a string or a for/while loop. Also, why do I need to include the * after "%c*"?
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int avgTemp, lowestTemp, temperature;
char choice ='Y';
char decision ='N';
printf("What is the average temperature?\n");
scanf("%d", &avgTemp);
printf("What is the lowest temperature in last 24 hours?\n");
scanf("%d", &lowestTemp);
printf("Has the temperature been over 99 degrees F for more than 30 minutes?
Please answer Y for yes and N for no.\n");
scanf("%c*", &choice);
printf("choice is %c", choice);
return 0;
}
Also, why do I need to include the * after "%c*"?
%c* means to scan for a character and then a * (which it will discard). Maybe you meant %*c which means do the scan but discard it. You don't need either of them.
scanf is a very problematic function and should be avoided. Your program illustrates the problem. scanf does not read a whole line. scanf will only scan stdin up to what you asked for and then stop. This means extra input and newlines can sometimes be left on the input stream for the next unsuspecting scanf. From the man page...
Each successive pointer argument must correspond properly with each
successive conversion specifier (but see the * conversion below). All
conversions are introduced by the % (percent sign) character. The format string may also contain other characters. 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. Scanning stops when an input character does not match such a format character. Scanning also stops when an input conversion cannot be made (see below).
This makes it very easy to accidentally leave characters on the input buffer. Each of your scanf("%d") will read in the number and stop. This leaves a newline on the input buffer. This is fine for %d because...
Before conversion begins, most conversions skip white space
...but not for %c.
Matches a sequence of width count characters (default 1); the next pointer must be a pointer to char, and there must be enough room for all the characters (no terminating NUL is added). The usual skip of leading white space is suppressed. To skip white space first, use an explicit space in the format.
So you need scanf(" %c") to make it work at all.
scanf is to be avoided because it's very, very vulnerable to unexpected input. Try giving "foo" to the first question. All the scanf("%d") will silently fail. And scanf("%c") will read f.
Instead, read the whole line with getline (preferred as it handles memory allocation for you) or fgets and then use sscanf on the resulting string. This avoids all the above problems.
To take input string in c, we can opt for 2 ways(as per my knowledge please add more if i missing something)
char name[10];
scanf(" %s",name); // First case
scanf("%[\n]s",name); // Second case
1st one will consider the string till the first blank space and 2nd will take complete sentence till the new line break as a string but to take input we need to improvise the 2nd statement as
scanf(" %[\n]s",name);
my question is what is extra spacing doing here ?
because sometime my compiler will behave normally even if i will remove the 's' from scanf statement and without extra spacing before '%' but sometime it wont work.
The space before the % operator will make it so that any white-space before the entered string is removed as well as whatever effect the format specifiers after the % operator have on the input.
Ex: "\n\t Hello World" entered with " %[^\n]" will be recorded as "Hello World".
If white space character is left in first input stream and mistakenely read by next input scanf: to delete the white space character from input stream either use space before format string or use fflush (stdin) function.
In my program I must store input characters in variables and then add them to arrays. But is there a way to use the same variable each time?
char str1,str2;
printf("insert character");
scanf("%c",&str1);
printf("%c",str1);
printf("insert character");
scanf("%c",&str2);
printf("%c",str2);
I would like to do something like this but using one variable. Also can I use scanf more than 1 times? It seems the executable stops before the second character is given.
Yes, you can use scanf() more than once. Your problem is not actually because of scanf();, Its with your input, To give input for first scanf() in your program, what we naturally do is we type(through keyboard) a character and hit ENTER KEY,Under the hood when you hit ENTER KEY a '\n' character is produced which is read by your second scanf() ,that's why your second scanf() is not waiting for input from you as you expected, You need to clear this '\n' manually when you use %c.(when %d %f %s are used '\n' are automatically removed that's why we don't face this problem when using them).
To solve problem you can use "%c" like this " %c" (note space before %c, this skips '\n' characters)
scanf(" %c",&str1);
printf("%c",str1);
//code to add them to array's
scanf(" %c",&str1);//Have Re-Used the same variable str1.
printf("%c",str1);