I want to read some user input and do something with each input. I do that using this code:
char c;
while(1){
printf("input");
c = scanf ( "%s", &c ) ;
}
This works fine . But I need it to accept even an empty input. But it just continues to next line and expects an not-empty input. How could I do that?
Current situation:
input:asdf
input:b
input:c
input:d
input:e
input:
fjhkjh
Expected :
input:asdf
input:b
input:c
input:d
input:e
input:blabla
input:f
input:
input:
Just how the cmd console works like...
UPDATE: I don't read only one single charcater, that was an example
First of all You shouldn't use %s to store input in a single character as %s is for string of characters terminated by null character(\0).
Don't use & with %s in scanf().
To store a single character make use of:
scanf("%c",&c);
or
c = getchar();
It doesn't internally work like that, you have declared it as single char but you have used %s which is a char array. the char you get as input are stored as null values.. every character you gave a b c d e are taken as null..
if you have doubt, add a printf("%s",c); below the scanf();
First of all, in your code,
scanf ( "%s", &c ) ;
invokes undefined behavior.
, as you cannot fit an incoming string inside a char.
That said, %s skips the leading white-spaces and reads the non-white-spaces up to the immediate white-space and ignores the last white-space, so you cannot read only white-spaces using %s.
Quoting C11, chapter §7.21.6.2, fscanf(), (emphasis mine)
s Matches a sequence of non-white-space characters.
If no l length modifier is present, the corresponding argument shall be a
pointer to the initial element of a character array large enough to accept the
sequence and a terminating null character, which will be added automatically.
So, we can clearly see, c is no sufficient to hold even a single char input, either, it will be out of bound access to store the terminating null.
You seem to be in need to getchar() or similar.
First you must have to use getchar(); or %c in scanf for a single character
then you can use a if for test which is the input character
char c;
while(1)
{
c=getchar();
if(c==' ')
break();
}
This is only for single character input.
Related
I've been trying to read some input from the user in C, but it doesn't seem to work as I wish it would have. I try to read a string until the user writes a colon, and then assign the colon (':') into a different variable. It works perfectly unless the colon is the first character. In that case, it simply assigns a value of -52 to both variables and reads the colon in the next scanf. I try to make it so the colon will be assigned to the second variable, even when it's first. I've tried looking online but couldn't find any solution... Any tip will be very appriciated, thanks!
My attempt:
char ch, name[200];
scanf("%[^:]%c", &name, &ch);
printf("%s\n%c\n", name, ch);
for a valid input such as:
Nadav Freedman: rest_of_input
it works and assigns "Nadav Freedman" to name and ':' to ch
but for an invalid input such as:
: rest_of_input
it simply doesn't assign any value to the variables, although I would like to save the colon to ch.
scanf stops reading as soon as any of the specifier provided doesn't match the input, so in your case if the %[^:] fails the function stops reading and the %c specifier isn't processed.
So to force it to read the colon use 2 scanfs instead of 1:
char ch, name[200];
if(scanf(" %199[^:]", name) != 1) name[0] = '\0';
scanf("%c", &ch);
printf("%s\n%c\n", name, ch);
OBS: I've also added the leading space to eliminate leading blank characters. And limited it to read up to 199 characters, so as not to exceed the size of the array name. And also changed it to update the array name to store an empty string if the first scanf fails to read anything.
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.
I know for a fact that [^\n] is a delimiter that makes scanf to scan everything until "enter" key is hit. But I don't know what the remainder of "%[^\n]%*c" is used for. Also why do we have to mention "&s" instead of "s" in the scanf function.
I tried running this:
char s[100];
scanf("%[^\n]s",s);
scanf("%[^\n]s",&s);
Both the above scanf statements worked exactly the same for me. If there is any difference between them, What is it?
Also Why should I prefer scanf("%[^\n]%*c", &s); to the above declarations?
scanf("%[^\n]s",&s); has many troubles:
No check of return value.
No overrun protection
No consumption of '\n'
No assignment of s on '\n' only
No need for s in "%[^\n]s"
Wrong type &s with format.
scanf("%[^\n]s",s); only has one less problem (last one).
Use fgets(s, sizeof s, stdin)
if (fgets(s, sizeof s, stdin)) {
s[strcspn(s, "\n")] = 0; // Lop off potential ending \n
// Success
} else {
// failure
}
No check of return value.
Without checking the return value, success of reading is unknown and the state of s indeterminate.
No overrun protection
What happens when the 100th character is inputted? - "Very bad. Not good. Not good." Necron 99, Wizards 1977
No consumption of '\n'
'\n' remains in stdin to foul up the next read.
No assignment of s on '\n' only
If the input begin with '\n', scanf() returns and s unchanged. It is not assigned "".
No need for "s" in "%[^\n]s"
The "s" is not part of the specifier "%[^\n]". Drop it.
Wrong type &s with format.
%[...] matches a char *, not a pointer to a char[100] like &s (UB).
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.
Note: After inputting the character and the string, inputting the sentence by the above mentioned statement won't work. This is because, at the end of each line, a new line character (\n) is present. So, the statement: scanf("%[^\n]%*c", s); will not work because the last statement will read a newline character from the previous line. This can be handled in a variety of ways and one of them being: scanf("\n"); before the last statement.
I had to do a program for college in which I should separate, between a certain amount of people, those who liked and the ones who disliked something.
so I did this:
char like[100];
printf("Like? Y or N \n");
scanf ("%c", like);
The program compiled, but didn't work the way it should. The user was not able to write "y or n" when asked "Like?"
So I tried this:
char like[100];
printf("Like? Y or N \n");
scanf ("%s", like);
And it worked. But I don't know why it worked. Can somebody please explain me the difference between %c and %s in a scanf?
First, please do some basic research before coming here - questions like this can usually be answered with a quick Google search or checking your handy C reference manual.
char inputChar; // stores a single character
char inputString[100] = {0}; // stores a string up to 99 characters long
scanf( " %c", &inputChar ); // read the next non-whitespace character into inputChar
// ^ Note & operator in expression
scanf( "%s", inputString ); // read the next *sequence* of non-whitespace characters into inputString
// ^ Note no & operator in expression
You would use %c when you want to read a single character from the input stream and store it to a char object. The %c conversion specifier will not skip over any leading whitespace, so if you want to read the next non-whitespace character, you need a blank before the %c specifier in your format string, as shown above.
You would use %s when you want to read a sequence of non-whitespace characters from the input stream and store them to an array of char. Your target array must be large enough to store the input string plus a terminating 0-valued character. The %s conversion specifier skips over any leading whitespace and stops reading at the first whitespace character following the non-whitespace characters.
Both %c and %s expect their corresponding argument to have type char * (pointer to char); however, in the first case, it's assumed that the pointer points to a single object, whereas in the second case, it's assumed that the pointer points to the first element of an array. For inputChar, we must use the unary & operator to obtain the pointer value. For inputString, we don't, because under most circumstances an expression of type "array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
Your code works fine as it is, but it's a bit confusing to read a single character and store it to an array.
Using %s without an explicit field width is risky; if someone types in more than 100 non-whitespace characters, scanf will happily store those extra characters to memory following inputString, potentially clobbering something important. It's generally safer to write something like
scanf( "%99s", inputString ); // reads no more than 99 characters into inputString
or to use fgets() to read input strings instead:
fgets( inputString, sizeof inputString, stdin );
Please check §7.21.6.2 of the online draft of the C language standard for a complete description of all of the conversion specifiers for the *scanf functions.
%s is used for string of characters and reads subsequent characters until it finds a whitespace(blank, newline or tab). Whereas %c is used for single character and reads the next character. If there are more than 1 character, including any whitespace character, it is read and stored in next iteration.
What does %[^\n] mean in C?
I saw it in a program which uses scanf for taking multiple word input into a string variable. I don't understand though because I learned that scanf can't take multiple words.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
int main() {
char line[100];
scanf("%[^\n]",line);
printf("Hello,World\n");
printf("%s",line);
return 0;
}
[^\n] is a kind of regular expression.
[...]: it matches a nonempty sequence of characters from the scanset (a set of characters given by ...).
^ means that the scanset is "negated": it is given by its complement.
^\n: the scanset is all characters except \n.
Furthermore fscanf (and scanf) will read the longest sequence of input characters matching the format.
So scanf("%[^\n]", s); will read all characters until you reach \n (or EOF) and put them in s. It is a common idiom to read a whole line in C.
See also §7.21.6.2 The fscanf function.
scanf("%[^\n]",line); is a problematic way to read a line. It is worse than gets().
C defines line as:
A text stream is an ordered sequence of characters composed into lines, each line consisting of zero or more characters plus a terminating new-line character. Whether the last line requires a terminating new-line character is implementation-defined.
The scanf("%[^\n]", line) has the specifier "%[^\n]". It scans for unlimited number of characters that match the scan-set ^\n. If none are read, the specifier fails and scanf() returns with line unaltered. If at least one character is read, all matching characters are read and saved and a null character is appended.
The scan-set ^\n implies all character that are not (due to the '^') '\n'.
'\n' is not read
scanf("%[^\n]",.... fails to read a new line character '\n'. It remains in stdin. The entire line is not read.
Buffer overflow
The below leads to undefined behavior (UB) should more than 99 characters get read.
char line[100];
scanf("%[^\n]",line); // buffer overflow possible
Does nothing on empty line
When the line consists of only "\n", scanf("%[^\n]",line); returns a 0 without setting line[] - no null character is appended. This can readily lead to undefined behavior should subsequent code use an uninitialized line[]. The '\n' remains in stdin.
Failure to check the return value
scanf("%[^\n]",line); assumes input succeeded. Better code would check the scanf() return value.
Recommendation
Do not use scanf() and instead use fgets() to read a line of input.
#define EXPECTED_INPUT_LENGTH_MAX 49
char line[EXPECTED_INPUT_LENGTH_MAX + 1 + 1 + 1];
// \n + \0 + extra to detect overly long lines
if (fgets(line, sizeof line, stdin)) {
size_t len = strlen(line);
// Lop off potential trailing \n if desired.
if (len > 0 && line[len-1] == '\n') {
line[--len] = '\0';
}
if (len > EXPECTED_INPUT_LENGTH_MAX) {
// Handle error
// Usually includes reading rest of line if \n not found.
}
The fgets() approach has it limitations too. e.g. (reading embedded null characters).
Handling user input, possible hostile, is challenging.
scanf("%[^\n]",line);
means: scan till \n or an enter key.
scanf("%[^\n]",line);
Will read user input until enter is pressed or a newline character is added (\n) and store it into a variable named line.
Question: what is %[^\n] mean in C?
Basically the \n command prints the output in the next line, but in
case of C gives the Null data followed by the above problem only.
Because of that to remove the unwanted data or null data, need to add
Complement/negotiated symbol[^\n]. It gives all characters until the next line
and keeps the data in the defined expression.
Means it is the Complemented data or rewritten data from the trash
EX:
char number[100]; //defined a character ex: StackOverflow
scanf("%[^\n]",number); //defining the number without this statement, the
character number gives the unwanted stuff `���`
printf("HI\n"); //normaly use of printf statement
printf("%s",number); //printing the output
return 0;