Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using scanf to read a string and an int separated by /

Tags:

c

scanf

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?

like image 541
Alcott Avatar asked Oct 16 '12 07:10

Alcott


People also ask

What is the problem with scanf () to read a string?

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.

How do you input a string with numbers?

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.

Can we use scanf () to read string with blank spaces?

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);

What is %d scanf?

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.


2 Answers

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

like image 118
StoryTeller - Unslander Monica Avatar answered Oct 24 '22 23:10

StoryTeller - Unslander Monica


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).

like image 29
paxdiablo Avatar answered Oct 24 '22 21:10

paxdiablo