2

I`ve been trying to this for quite a while now and after some research I had no success, so my last resort was asking a question. My input looks like this:

1.0.0.0/255.0.0.0/127.0.0.1/1112 
1.2.0.0/255.255.0.0/2.4.6.9/1112
1.2.3.0/255.255.255.0/1.2.3.1/111

I need to extract 4 strings from each line, so for exemple the first line would give me

s1 = 1.0.0.0
s2 = 255.0.0.0
s3 = 127.0.0.1
s4 = 1112

Here is what I have tried:

scanf("%s/%s/%s/%s", str1, str2, str3, str4); // This doesn't consume the "/"
scanf("%[^/]s%[^/]s%[^/]s%[^/]s", str1, str2, str3, str4); // This only gets the first string
scanf(""%[^\n]s%*c%s%*c%s%*c%s", str1, str2, str3, str4); // Hera %*c was supposed to consume the "/" and do not store it, it doen't happen tho

How can I get the 4 strings from each input line using a single scanf inside a while (!feof(fileIn)) ? Thank you.

Alexandre Krabbe
  • 727
  • 1
  • 13
  • 33
  • 2
    [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – Eugene Sh. Nov 22 '17 at 22:59
  • 2
    The first doesn't consume the `'/'` because `%s` format reads up to the next whitespace character, so the `'/'` characters have already been read. Use `fgets` and break up the string with `strtok` or similar. The second stalls, as it would with `\n` because that was not removed. Note too, the string format is either `%[]` or `%s` but not the newbie hybrid of both which you have as `%[]s`. – Weather Vane Nov 22 '17 at 23:03
  • Replace the `s` – Jonathan Leffler Nov 22 '17 at 23:10
  • @WeatherVane But can it be done with a single scanf? Even if it is "noob" to do so, I don't want unnecessary lines. – Alexandre Krabbe Nov 22 '17 at 23:13
  • 1
    Write as many lines as you need. – Weather Vane Nov 22 '17 at 23:14

2 Answers2

3

There are a few issues with the posted code. The scanset directive is %[]; there is no s in this. The format strings using %[^/]s are attempting to match a literal s in the input. But this will always fail because %[^/] matches any character except for /. When a / is encountered, the match fails and the / character is left in the input stream. It is this character which must be consumed before continuing on to the next input field.

Also, note that while(!feof(file)){} is always wrong. Instead, try fetching input by lines using fgets(), and parsing with sscanf(). The fgets() function returns a null pointer when end-of-file is reached.

Further, you should always specify a maximum width when reading strings with scanf() family functions to avoid buffer overflow.

Here is an example program:

#include <stdio.h>

int main(void)
{
    char input[4096];
    char str1[100];
    char str2[100];
    char str3[100];
    char str4[100];

    while (fgets(input, sizeof input, stdin)) {
        sscanf(input, " %99[^/]/ %99[^/]/ %99[^/]/ %99[^/]",
               str1, str2, str3, str4);

        puts(str1);
        puts(str2);
        puts(str3);
        puts(str4);
    }

    return 0;
}

Sample interaction using sample input from the question:

λ> ./a.out < readstring_test.txt 
1.0.0.0
255.0.0.0
127.0.0.1
1112 

1.2.0.0
255.255.0.0
2.4.6.9
1112

1.2.3.0
255.255.255.0
1.2.3.1
111
ad absurdum
  • 19,498
  • 5
  • 37
  • 60
1

You already got quite close: you missed to consume the delimiter in your second approach:

scanf("%[^/]/%[^/]/%[^/]/%[^/]", str1, str2, str3, str4);

should do the job.

Marcel
  • 1,688
  • 1
  • 14
  • 25
  • `%[^/]s` is not the format you imagine it to be. It wants to match an `'s'` from the input. The string format is either `%[]` or `%s`. So it does not consume the `'/'` delimiter, which remains in the input. – Weather Vane Nov 22 '17 at 23:07
  • Thank you for your reply, but this did not work, it only got the first string, the other 3 remained blank. – Alexandre Krabbe Nov 22 '17 at 23:12
  • Sorry, I missed to remove the 's' characters. Try again, please. – Marcel Nov 22 '17 at 23:18