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?