The input consists a string and an integer, which are separated by a '/'
, like this:
hello/17
And I want to read the input into a string and an int
, like this:
char str[20];
int num;
scanf("%s/%d", str, &num); // this how I tried to do it.
I can't seem to make it, any advice?
Explanation: The problem with the above code is scanf() reads an integer and leaves a newline character in the buffer. So fgets() only reads newline and the string “test” is ignored by the program. 2) The similar problem occurs when scanf() is used in a loop.
for a singly linked list and implemented the following function to get user input: void user_input(){ char input[10]; while(fgets(input, 9, stdin)){ if(strncmp(input, "add", 3) == 0){ int x; printf("Number to add: "); scanf("%d", &x); push(x); printf("%d added.
Once the character is equal to New-line ('\n'), ^ (XOR Operator ) gives false to read the string. So we use “%[^\n]s” instead of “%s”. So to get a line of input with space we can go with scanf(“%[^\n]s”,str);
The “%d” in scanf allows the function to recognise user input as being of an integer data type, which matches the data type of our variable number. The ampersand (&) allows us to pass the address of variable number which is the place in memory where we store the information that scanf read.
scanf
awaits a whitespace terminated string when it tries to read %s
.
Try to specify the forbidden character set directly:
scanf("%19[^/]/%d", str, &num);
You can read more about the formating codes here
You only need to run the following program:
#include <stdio.h>
int main (void) {
char str[20] = {'\0'};
int count, num = 42;
count = sscanf ("hello/17", "%s/%d", str, &num);
printf ("String was '%s'\n", str);
printf ("Number was %d\n", num);
printf ("Count was %d\n", count);
return 0;
}
to see why this is happening. The output is:
String was 'hello/17'
Number was 42
Count was 1
The reason has to do with the %s
format specifier. From C99 7.19.6.2 The fscanf function
(largely unchanged in C11, and the italics are mine):
s
: matches a sequence of non-white-space characters.
Since /
is not white space, it gets included in the string bit, as does the 17
for the same reason. That's also indicated by the fact that sscanf
returns 1
, meaning that only one item was scanned.
What you'll then be looking for is something that scans any characters other than /
into the string (including white space). The same section of the standard helps out there as well:
[
: matches a nonempty sequence of characters from a set of expected characters (the scanset). The conversion specifier includes all subsequent characters in the format string, up to and including the matching right bracket (]). The characters between the brackets (the scanlist) compose the scanset, unless the character after the left bracket is a circumflex (^), in which case the scanset contains all characters that do not appear in the scanlist between the circumflex and the right bracket.
In other words, something like:
#include <stdio.h>
int main (void) {
char str[20] = {'\0'};
int count, num = 42;
count = sscanf ("hello/17", "%[^/]/%d", str, &num);
printf ("String was '%s'\n", str);
printf ("Number was %d\n", num);
printf ("Count was %d\n", count);
return 0;
}
which gives you:
String was 'hello'
Number was 17
Count was 2
One other piece of advice: never ever use scanf
with an unbounded %s
or %[
; you're asking for a buffer overflow attack. If you want a robust user input function, see this answer.
Once you have it in as a string, you can sscanf
it to your heart's content without worrying about buffer overflow (since you've limited the size on input).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With