Eval() in C?

Is there any possible way of evaluating a string in C? If there isn’t, is there a way to call a function with a certain name stored in a string? It seems kind of high-level for C.

Nope, not in standard C, not without writing your own parser; and I’m sure that’s not you wanted.

Maybe if you described the problem in more detail?

There is nothing like that (converting a string to a function address).

To simulate it, you would compare a variable (perhaps a string variable containing the name of your function) to some constant, then use a switch() statement to call the appropriate function. Example:

int foo( int a, int b)
{
return a + b;
}

int bar( int a, int b)
{
return a - b;
}

main()
{
char funcname] = “foo”;

switch (funcname)
{
case “foo”:
foo(a,b);
case “bar”:
bar(a,b);
}

}
}

I basically want to be able to store a string in a struct and then be able to call that method when “the time is right.” It’s almost like Flash’s event based structure, so I can’t really have separate if statements for every string.

EDIT: mluckham, that’ll probably work, thanks.

Actually, what you’re probably looking for is a “function pointer”. Structs can store a pointer to a function call that you assign somewhere programmatically in code, and then when you want to call that function you just dereference the pointer (in a specific way). Check it out: http://www.newty.de/fpt/index.html

-Danny

Pretty advanced (function pointers) but they are certainly useful as ‘action routine pointers’ in a state-action table (look up “Finite State Machine”) provided the argument list to all the routines called is identical.

The way to do this in C is to do the command matching yourself and use function pointers to store a table of the functions you want to use.

The following code compiles with ANSI C. While running it waits for individual characters. If the character matches the command character ‘cmd’ then it de-references the function pointer, and calls the function. It passes no arguments onto the called function. (Hint: that’s an exercise for you).


#include <stdlib.h>
#include <stdio.h>

// Four command functions. They must have identical arguments.

void go_left(void) { printf("Going Left
"); }
void go_right(void) { printf("Going Right
"); }
void stop(void) { printf("Stopped
"); }
void quit(void) { printf("Bye
"); exit(0); }

// An array of a two value structures.

struct {
    char cmd;			// The character
    void (*function)(void);	// a pointer to a function.
} commands] = {
    {'l', &go_left},	// put the address of the function
    {'r', &go_right},	// into the function pointer
    {'s', &stop},
    {'q', &quit},
    {0, 0}		// marks the end of the array.
};

int
main(void) {
    char c; int i;

    while (1) {
        c = getchar();	// not available on FRC
        i = 0;
        while (commands*.cmd) {
	    if (commands*.cmd == c) {
		// dereference the pointer and call the function.
                // note the bracketing
		(*(commands*.function))();
            }
	    i++;
        }
    }
}


You could obviously extend this to match whole strings instead of characters.

You do not have a “getchar()” function in the FRC code instead you’ll have to read a character from one of the serial ports.

The above code is not pretty, badly commented, terse, and follows an arcane indenting style (I’m old).

You should use ‘typedef’ to define the structure instead of using it inline like this.

The structure is initialized after the command functions have been declared. If the command functions are in another file then you’ll have to use ‘extern’ declarations of the functions before initializing the array.

A sample run:


$ cc ex1.c
$ ./a.out
l
Going Left
r
Going Right
q
Bye
$ 


The only limitation is that your functions must take the same datatype. If you need them to take different data types you will need to make them all take a single void pointer to a block of memory then the function will need to reconstruct the data itself. This is probably too complicated and you probably won’t need it. just throwing it out there if the need comes up

void pointers are evil… in a good way.

it is possible to create an eval function, using some derivative of a reverse polish notation format. however, for the purposes of robotics, it probably wont be worth it.

Oi… that’s going to lead you into a world of trouble.
The C language does not allow for direct comparison of a string, because a string isn’t a type, it’s a null-terminated array of characters. “foo” is of type **const char ***, which is an address in your program’s memory. funcname is also of type char *, so switch is going to implicitly compare the addresses of the two “strings” and it will never work, because it cannot compare the data at the addresses.

You need to do the following:


if(strcmp(funcname, "foo") == 0) {
    foo(a, b);
}  else if(strcmp(funcname, "bar")) {
   bar(a, b);
}

Switch only works with strings in PHP and maybe Javascript, as far as I know. You’re right though, function pointers are as close to what he’s looking for as you can get.