sscanf wrapping function to advance string pointer in C

c, scanf, variadic-functions

Solution

You're right - you can't stuff extra parameters into a `va_list`. The best you can do is probably some macro trickery like this:

int _newSscanf ( char ** str, int *length, const char * format, ...)
{
  int rv;
  va_list args;

  va_start(args, format);
  rv = vsscanf(*str, format, args);
  va_end(args);
  *str += *length;

  return rv;
}

#define NEW_SSCANF_INIT int _ss_len
#define newSscanf(str, fmt, ...) _newSscanf(str, &_ss_len, fmt "%n", __VA_ARGS__, &_ss_len)

...and require the caller to do:

NEW_SSCANF_INIT;

if (newSscanf(&str, "%d", &fooInt) != 1)
{ 
   // error handling
}

If you can use GCC extensions, you can use "statement expressions" to do away with the `NEW_SSCANF_INIT` part, making it cleaner:

#define newSscanf(str, fmt, ...) ({int _ss_len; _newSscanf(str, &_ss_len, fmt "%n", __VA_ARGS__, &_ss_len);})

Problem

I have a function that makes a series of calls to `sscanf()` and then, after each, updates the string pointer to point to the first character not consumed by `sscanf()` like so: ``` if(sscanf(str, "%d%n", &fooInt, &length) != 1) { // error handling } str+=length; ``` In order to clean it up and avoid duplicating this several times over, i'd like to encapsulate this into a nice utility function that looks something like the following: ``` int newSscanf ( char ** str, const char * format, ...) { int rv; int length; char buf[MAX_LENGTH]; va_list args; strcpy(buf, format); strcat(buf, "%n"); va_start(args, format); rv = vsscanf(*str, buf, args, &length); //Not valid but this is the spirit va_end(args); *str += length; return rv; } ``` Then I could simplify the calls as below to remove the additional parameter/bookkeeping: ``` if(newSscanf(&str, "%d", &fooInt) != 1) { // error handling } ``` Unfortunately, I can't find a way to append the `&length` parameter onto the end of the arg list directly or otherwise inside `newSscanf()`. Is there some way to work around this, or am I just as well off handling the bookkeeping by hand at each call?

Original source