Variable number of format arguments?

In my program, I use sscanf to check if a string has a given format. To do this, I provide the number of arguments in the format string and check if sscanf returns the same number when parsing the input.

As part of a primitive analyzer, I want to check if a string matches one of many formats. The sscanf function is variational, so how can I deal with a variable number of arguments that I need to pass?

Currently, I just pass a very large number of arguments (e.g. 50) to the function and hope that the format strings do not contain more arguments.

Is there a better way to do this?

+4
source share
6 answers

You really need something harder than scanf . You must tell scanf what format your input is in; he cannot understand anything on his own.

If you have access to POSIX, check out regex.h , perhaps all you need.

Otherwise, you are stuck on your own. lex and yacc are good if the format is quite complicated, but otherwise strtok or ( getchar + switch ) is possible.

Edit: Since you can use POSIX, here is a simple example of how to extract data from a regular expression in c. (error checking is excluded for brevity.)

 char txt[] = "232343341235898dfsfgs/.f"; regex_t reg; regmatch_t refs[MAX_REFS]; //as in, the maximum number of data you want to extract regcomp(&reg, "3433\\([0-5]*\\).*", 0); //replace 0 with REG_EXTENDED if desired regexec(&reg, txt, MAX_REFS, refs, 0); regfree(&reg); txt[refs[0].rm_eo+1] = '\0'; int n = atoi(txt+refs[0].rm_so); printf("%d\n", n); 

Print

 41235 
+3
source

You should probably use lex / yacc to create the right parser. Alternatively, first string tokenization with strtok can simplify your problem. (Caution: using strtok correctly - read its documentation carefully.)

0
source

I'm not sure if it answers your question, but you use varargs in C to allow a variable number of function arguments.

 void myscanf(const char *fmt, ...) { } 
0
source

The immediate answer is: "Don't do this, write the parser correctly, perhaps using lex and / or yacc or bison ."

The answer to your question: "Yes, you could do that." I do not believe that there is any reason why there cannot be more variational parameters than is required for the format, although for a few it would be bad. I assume that you have an array or a list of possible formats and you call sscanf in a loop.

0
source

You can write a validation function using variable-length arguments using the macros available in stdarg.h .

For instance,

 int my_validation_func(const char *format, ...) { va_list ap; char *p, *sval; int ival; float fval; va_start(ap, format); for(p=format; *p ; p++) { if (*p != '%') { continue; } switch(*++p) { case 'd': ival = va_arg(ap, int); break; case 'f': fval = va_arg(ap, float); break; case 's': for (sval = va_arg(ap, char *); *sval; sval++); break; default: break; } } va_end(ap); } 

Hope this helps!

0
source

If you do not know when you write the code, the number and type of arguments, sscanf() cannot safely do what you are trying to do.

Passing 50 arguments to sscanf() in order (arguments that are not consumed by the format string are evaluated but ignored otherwise), but the arguments corresponding to the format string must be of the expected type after the move; otherwise, the behavior is undefined. Therefore, if you want to determine whether you can scan a string using "%d" or "%f" , you cannot safely do this with a single call to sscanf() . (You could probably get away with passing void* , which points to a sufficiently large buffer, but the behavior is still undefined.)

Another nasty problem with sscanf() is that it does not handle numeric overflow. It:

 char *s = "9999999999999999999999999"; int n; int result = sscanf(s, "%d", &n); printf("result = %d, n = %d\n", result, n); 

has undefined behavior (provided that 99999999999999999999999999999 is too large to store in int ).

Something you could do is find an open source sscanf implementation and modify it so that it just checks the string in format without saving anything. (Working with the license for implementation is left as an exercise.) This makes sense if you find sscanf style strings that are especially convenient for your problem. Otherwise, regular expressions are probably suitable (not in the C standard, but it's easy enough to find an implementation).

0
source

Source: https://habr.com/ru/post/1388520/


All Articles