^ format string

S

Servé Lau

suppose I want to use sscanf get the functionname from a function prototype.
Is the following format string correct then?

char funcname[128];

char *p = "func(void)";

sscanf(p, "%[^(]s", funcname); // "%[^(]s"
 
P

Peter Pichler

Servé Lau said:
suppose I want to use sscanf get the functionname from a function prototype.
Is the following format string correct then?

char funcname[128];

char *p = "func(void)";

sscanf(p, "%[^(]s", funcname); // "%[^(]s"

Almost, but not quite. For example, *I* write function prototypes like this:

int func (void);

Note the return type (I never rely on implicir int), *at least one* space
between the return type and the function name an *at least one* space
between
the function name and the opening parenthesis.

Many people prefer even more spaces, e.g.:

int func ( void ) ;
 
B

Barry Schwarz

suppose I want to use sscanf get the functionname from a function prototype.
Is the following format string correct then?

char funcname[128];

char *p = "func(void)";

sscanf(p, "%[^(]s", funcname); // "%[^(]s"
How do you skip over the function's return type which should be part
of the prototype?


<<Remove the del for email>>
 
K

Kevin Goodsell

Servé Lau said:
suppose I want to use sscanf get the functionname from a function prototype.
Is the following format string correct then?

Absolutely not. There are several problems, both logical and syntactical.
char funcname[128];

char *p = "func(void)";

Never assign a string literal to a (non-const) char *. The array
represented by the string literal is non-modifiable. Any attempt to
modify it results in undefined behavior. String literals aren't const
for historical reasons, but you should treat them as if they are.
sscanf(p, "%[^(]s", funcname); // "%[^(]s"

A %[ format specifier without a field width is as bad as gets().

What's with the 's' in the format string? There doesn't seem to be any
way for it to match, since the next character in the stream must be '('.
%[ and %s are completely different format specifiers that happen to have
some similarities.

The '//' stuff at the end of this line is probably a syntax error,
unless you happen to be using a C99 compiler (which is unlikely).

Finally, this approach is far too simplistic to work in general.
Consider these function prototypes:

int f1(void);

int f2 (void);

long int f3(void);

static long unsigned int f4(void);

int (*f5(void))(void);

I don't believe it's possible to build a scanf format string that can
match a function prototype, in general. You need some real parsing logic
for that.

-Kevin
 
K

Keith Thompson

Peter Pichler said:
Servé Lau said:
suppose I want to use sscanf get the functionname from a function prototype.
Is the following format string correct then?

char funcname[128];

char *p = "func(void)";

sscanf(p, "%[^(]s", funcname); // "%[^(]s"

Almost, but not quite. For example, *I* write function prototypes like this:

int func (void);

Note the return type (I never rely on implicir int), *at least one* space
between the return type and the function name an *at least one* space
between
the function name and the opening parenthesis.

Many people prefer even more spaces, e.g.:

int func ( void ) ;

Of course there are even more possibilities:

int /* comment */ func ( void );

int fu\
nc(void);

#define NAME func
int NAME(void);

If you want 100% reliability, you'll need a full C parser.
 
D

Darrell Grainger

suppose I want to use sscanf get the functionname from a function prototype.
Is the following format string correct then?

char funcname[128];
char *p = "func(void)";
sscanf(p, "%[^(]s", funcname); // "%[^(]s"

First, "%[^(]" will read everything up to the '(' symbol. The 's' after it
is unncessary.

Second, you assume that the function prototype will not indicate the
return value for the function and there will be no extra spaces between
the function name and the '(' symbol.

This second problem will be the hardest part to get around. In some cases
the code might implicitly assume an int return value. In other cases the
return value will be explicitly given. For example,

p = "void srand(unsigned int seed)";

In this case you will get "void srand" as the function name. You could
also have:

p = "unsigned long something(void)";

First thought might be to take the last word of the new string. Even this
does not work since you could have:

p = "void *malloc(size_t size)";

Bottom line, define all your cases before you code a solution.
 
B

Ben Pfaff

suppose I want to use sscanf get the functionname from a function prototype.
Is the following format string correct then?

char funcname[128];
char *p = "func(void)";
sscanf(p, "%[^(]s", funcname); // "%[^(]s"

First, "%[^(]" will read everything up to the '(' symbol. The 's' after it
is unncessary.

Second, you assume that the function prototype will not indicate the
return value for the function and there will be no extra spaces between
the function name and the '(' symbol.

It's a fairly common convention to put the name in a function
definition at the beginning of a line. It makes searching with
stupid tools easy. If the OP is dealing with code structured
this way, his technique should be okay. (He might still want to
strip white space.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,170
Latest member
Andrew1609
Top