^ format string

Discussion in 'C Programming' started by Servé Lau, Jan 1, 2004.

  1. Servé Lau

    Servé Lau Guest

    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"
    Servé Lau, Jan 1, 2004
    1. Advertisements

  2. 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
    the function name and the opening parenthesis.

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

    int func ( void ) ;
    Peter Pichler, Jan 1, 2004
    1. Advertisements

  3. How do you skip over the function's return type which should be part
    of the prototype?

    <<Remove the del for email>>
    Barry Schwarz, Jan 1, 2004
  4. Absolutely not. There are several problems, both logical and syntactical.
    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.
    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 Goodsell, Jan 1, 2004
  5. Of course there are even more possibilities:

    int /* comment */ func ( void );

    int fu\

    #define NAME func
    int NAME(void);

    If you want 100% reliability, you'll need a full C parser.
    Keith Thompson, Jan 1, 2004
  6. 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.
    Darrell Grainger, Jan 2, 2004
  7. Servé Lau

    Ben Pfaff Guest

    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.)
    Ben Pfaff, Jan 2, 2004
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.