5

Is there any function in C or C++ to perform the inverse of an snprintf, such that

 char buffer[256]
 snprintf( buffer, 256, "Number:%i", 10);

 // Buffer now contains "Number:10"

 int i;
 inverse_snprintf(buffer,"Number:%i", &i);

 // i now contains 10

I can write a function that meets this requirement myself, but is there already one within the standard libraries?

Mike DeSimone
  • 41,631
  • 10
  • 72
  • 96
foips
  • 596
  • 5
  • 19

2 Answers2

16

Yes, there is sscanf(). It returns the number of tokens successfully matched to the input, so you can check the return value to see how far it made it into the input string.

if (sscanf(buffer, "Number:%i", &i) == 1) {
    /* The number was successfully parsed */
}
cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • Of course, one needs to make sure the input to `sscanf` is properly null-terminated first. – Mike DeSimone Dec 15 '14 at 15:47
  • @MikeDeSimone Well... yes. That is true of nearly every function accepting a C string. – cdhowie Dec 15 '14 at 15:48
  • 1
    The C++ standard library switched over from using `fscanf` family (C++03) to using e.g. `strtoll` (C++11) in order to avoid certain UB issues. I'd recommend for the OP to use [`strol`](http://en.cppreference.com/w/cpp/string/byte/strtol) instead of `sscanf`. – Cheers and hth. - Alf Dec 15 '14 at 15:49
  • 3
    Alf: `strtol` and friends don't parse the prompt string. The resulting code wouldn't be an "inverse" of `snprintf`. – Mike DeSimone Dec 15 '14 at 15:51
  • 1
    @MikeDeSimone: That's a *very dangerous* view/idea to have. One cannot in general pass a `sprintf` format string to `sscanf`. Consider e.g. `sprintf` `"double %f"` versus `sscanf` `"float %f"`: thinking the specifier means the same type in both cases leads to UB. – Cheers and hth. - Alf Dec 15 '14 at 16:14
  • Recommend `%d` instead of `"%i"`. With `...printf("%i"` or `...printf("%d"` will always print a decimal number and `sscanf("%d"` will always scan as a decimal. `sscanf("%i"` may interpret the string as octal or hexadecimal like "077". – chux - Reinstate Monica Dec 15 '14 at 16:20
  • The return value of `sccanf()` (0, 1, or EOF) only weakly allows code to know how far it made it into the input string. `strtol()` indicates the exact position scanning stopped - but then additional code would be need to skip the "Number:". – chux - Reinstate Monica Dec 15 '14 at 16:22
  • @Alf: "One cannot in general..." -- No, but they can in limited cases. There is a subset of format components which are reversible. So long as they stick to that, they're okay. And the odd cases could be handled with macros or similar, or just left unsupported, if they're even needed. Either way, it's far less work and far less likely to fail than what would be effectively a complete rewrite of `sscanf`. Finally, if a truly robust parser is needed, they should use `boost.spirit`. – Mike DeSimone Dec 16 '14 at 03:46
0

In addition to sscanf(), if you are only going to scan numbers, you can safely scan numeric values using the strto*() functions: strtol(), strtoll(), strtoul(), strtoull(), strtof(), strtod(), strtold(). You can also use atoi(), atol() and atoll(), but note that these functions return 0 if the string is not an integer that can be converted.

RaymondY
  • 23
  • 4