views:

46

answers:

1

Is there a good way to loop over a string with sscanf?

Let's say I have a string that looks like this:

char line[] = "100 185 400 11 1000";

and I'd like to print the sum. What I'd really like to write is this:

int n, sum = 0;
while (1 == sscanf(line, " %d", &n)) {
  sum += n;
  line += <number of bytes consumed by sscanf>
}

but there's no clean way to get that information out of sscanf. If it return the number of bytes consumed, that'd be useful. In cases like this, one can just use strtok, but it'd be nice to be able to write something similar to what you can do from stdin:

int n, sum = 0;
while (1 == scanf(" %d", &n)) {
  sum += n;
  // stdin is transparently advanced by scanf call
}

Is there a simple solution I'm forgetting?

+8  A: 

Look up the %n conversion specifier. It gives you the information you need.

#include <stdio.h>

int main(void)
{
    char line[] = "100 185 400 11 1000";
    char *data = line;

    int offset, n, sum = 0;
    while (1 == sscanf(data, " %d%n", &n, &offset)) {
        sum += n;
        data += offset;
        printf("read: %5d; sum = %5d; offset = %5d\n", n, sum, offset);
    }

    printf("sum = %d\n", sum);
    return 0;
}

Changed 'line' to 'data' because you can't increment the name of an array.

Jonathan Leffler
+1, you beat me to it.
schot
+1, how did you know this???
Green Code
@Green Code: In my case `man sscanf`.
schot
@Green Code: I've read, and reread, and re-reread, the manual pages for the function over the years, on many machines, and using my copy of the C standard, etc. I think it is actually the first time I've used the `%n` notation, but it works fine. **Beware**: `%n` also exists in `printf()` and has the analogous meaning. It becomes a risk factor because it is an *output* value in a function that predominantly reads values. It is also banned by the secure versions of `printf()` for TR24731. And `%n` can be used with devastating effect by people who manage format string attacks on programs.
Jonathan Leffler
I'm actually aware of %n, yeah, but am wary of using it for security reasons. But if it's the only way...
Andrew H. Hunter