Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

calling function in C

0 views
Skip to first unread message

Shiv Ranjan

unread,
May 28, 2008, 6:12:15 AM5/28/08
to
Hi,
Lets say I have some 10 functions named -

display1()
display2()
display3()
display4()
.....
.....
display10()

Assume that all these functions have been defined. Now we have to
modify the program so that whatever function name is entered by
keyboard will be invoked. For example if we are accepting string
display5 from the keyboard then display5() method should be invoked.
The flow should be generic so that the code need not be modified even
though some more functions are added.

If any one has any idea do let me know.

Regards
Shiv

Richard Heathfield

unread,
May 28, 2008, 6:20:29 AM5/28/08
to
Shiv Ranjan said:

> Hi,
> Lets say I have some 10 functions named -
>
> display1()
> display2()
> display3()
> display4()
> .....
> .....
> display10()
>
> Assume that all these functions have been defined. Now we have to
> modify the program so that whatever function name is entered by
> keyboard will be invoked.

Construct a lookup table (e.g. hash table, binary search tree, or something
like that) whose entries are structures containing a key (the name of the
function, expressed as a string) and a payload (a pointer to the function
associated with that string). Yes, you will have to recompile whenever you
add a new entry to the table.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999

Bartc

unread,
May 28, 2008, 6:24:52 AM5/28/08
to
Richard Heathfield wrote:
> Shiv Ranjan said:
>
>> Hi,
>> Lets say I have some 10 functions named -
>>
>> display1()
>> display2()
>> display3()
>> display4()
>> .....
>> .....
>> display10()
>>
>> Assume that all these functions have been defined. Now we have to
>> modify the program so that whatever function name is entered by
>> keyboard will be invoked.
>
> Construct a lookup table (e.g. hash table, binary search tree, or
> something like that)

Any of these will be overkill for this task I think, and likely to give more
trouble than the main assignment.

A simple linear search should be fine. Especially as it seems there will be
one search per keyboard entry.

--
Bartc


Szabolcs Borsanyi

unread,
May 28, 2008, 6:33:08 AM5/28/08
to
On Wed, May 28, 2008 at 10:20:29AM +0000, Richard Heathfield wrote:
> Shiv Ranjan said:
>
> > Hi,
> > Lets say I have some 10 functions named -
> >
> > display1()
[snip]

> > display10()
> >
> > Assume that all these functions have been defined. Now we have to
> > modify the program so that whatever function name is entered by
> > keyboard will be invoked.
>
> Construct a lookup table (e.g. hash table, binary search tree, or something
> like that) whose entries are structures containing a key (the name of the
> function, expressed as a string) and a payload (a pointer to the function
> associated with that string). Yes, you will have to recompile whenever you
> add a new entry to the table.
>
> --
> Richard Heathfield <http://www.cpax.org.uk>

(you=OP)
The nice thing with Richard's solution is that you will not have to recompile
the part that accesses the lookup table, just the part that builds it.
Nonetheless, whenever you write a function in C, you'll have to compile it
sooner or later to get that work. The table itself has to be recomplied too,
since in standard C you cannot spot a function pointer by the function's name.

You may want to restrict the portability of your application to
systems where there is a system-specific way to get a function pointer
from a string if the funtion is defined in a shared library
(such as dlsym() on unices.)

Szabolcs


pete

unread,
May 28, 2008, 8:54:53 AM5/28/08
to

/* BEGIN new.c */

#include <stdio.h>
#include <string.h>

void display1(void);
void display2(void);
void display3(void);
void display4(void);
void display5(void);

int main(int argc, char **argv)
{
struct {
char *string;
void (*func)(void);
} table[] = {
{"display1", display1},
{"display2", display2},
{"display3", display3},
{"display4", display4},
{"display5", display5},
{ NULL, NULL}
}, *p = table;

putchar('\n');
if (argc > 1) {
while (p -> string != NULL) {
if (strcmp(argv[1], p -> string) == 0) {
p -> func();
break;
}
++p;
}
if (p -> string == NULL) {
puts("Function not found.");
}
} else {
puts("Not enough argc.");
}
return 0;
}

void display1(void)
{
puts("A");
}

void display2(void)
{
puts("B");
}

void display3(void)
{
puts("C");
}

void display4(void)
{
puts("D");
}

void display5(void)
{
puts("E");
}

/* END new.c */

--
pete

Szabolcs Borsanyi

unread,
May 28, 2008, 9:12:20 AM5/28/08
to
On Wed, May 28, 2008 at 07:54:53AM -0500, pete wrote:
> Shiv Ranjan wrote:
>> Hi,
>> Lets say I have some 10 functions named -
>>
>> display1()
[snip]
>> display10()

>>
> struct {
> char *string;
> void (*func)(void);
> } table[] = {
> {"display1", display1},
> {"display2", display2},
> {"display3", display3},
> {"display4", display4},
> {"display5", display5},
> { NULL, NULL}
> }, *p = table;
Surely, you will want to define macros:
#define F(x) {#x,x}
#define G(x) F(display ##x)
{G(1),G(2),G(3),{NULL,NULL}}
rather ther writing everything twice.

Szabolcs

Bartc

unread,
May 28, 2008, 10:19:33 AM5/28/08
to

"Szabolcs Borsanyi" <s.bor...@sussex.ac.uk> wrote in message
news:20080528131...@kroto.pact.cpes.susx.ac.uk...

I think these are just example function names and bodies. The real names
could be all different. Anyway as this is homework you don't want to appear
too clever.

--
Bartc


Richard Heathfield

unread,
May 28, 2008, 3:55:04 PM5/28/08
to
Bartc said:

> Richard Heathfield wrote:

<snip>

>> Construct a lookup table (e.g. hash table, binary search tree, or
>> something like that)
>
> Any of these will be overkill for this task I think, and likely to give
> more trouble than the main assignment.
>
> A simple linear search should be fine.

A linear search through *what*? Well, gee, a lookup table.

Bartc

unread,
May 28, 2008, 5:52:46 PM5/28/08
to

"Richard Heathfield" <r...@see.sig.invalid> wrote in message
news:Q4mdnSqGmuFRKqDV...@bt.com...

> Bartc said:
>
>> Richard Heathfield wrote:
>
> <snip>
>
>>> Construct a lookup table (e.g. hash table, binary search tree, or
>>> something like that)
>>
>> Any of these will be overkill for this task I think, and likely to give
>> more trouble than the main assignment.
>>
>> A simple linear search should be fine.
>
> A linear search through *what*? Well, gee, a lookup table.

I was referring to your suggestions of using hash tables and binary trees.
But, did I really have to clarify that?

-- bartc


Richard Heathfield

unread,
May 28, 2008, 6:22:20 PM5/28/08
to
Bartc said:

Each of those suggestions is perfectly reasonable, and they offer solutions
that are scalable, whereas a linear search is very much an inferior
stopgap solution - adequate (barely) if all you want is a pass mark for a
college assignment, but not a tool you'd want to use very often for this
problem in the Real World. You see, lookup tables have a habit of growing.
(See "The Practice of Programming" for a fine example of how adopting a
stopgap solution can be costly in the long term.)


> But, did I really have to clarify that?

I am at a loss to understand what you thought you were clarifying.

Bartc

unread,
May 28, 2008, 8:26:28 PM5/28/08
to
"Richard Heathfield" <r...@see.sig.invalid> wrote in message
news:YJqdnaKY4-LNR6DV...@bt.com...

> Bartc said:
>
>>
>> "Richard Heathfield" <r...@see.sig.invalid> wrote in message
>> news:Q4mdnSqGmuFRKqDV...@bt.com...
>>> Bartc said:
>>>
>>>> Richard Heathfield wrote:
>>>
>>> <snip>
>>>
>>>>> Construct a lookup table (e.g. hash table, binary search tree, or
>>>>> something like that)
>>>>
>>>> Any of these will be overkill for this task I think, and likely to give
>>>> more trouble than the main assignment.
>>>>
>>>> A simple linear search should be fine.
>>>
>>> A linear search through *what*? Well, gee, a lookup table.
>>
>> I was referring to your suggestions of using hash tables and binary
>> trees.
>
> Each of those suggestions is perfectly reasonable, and they offer
> solutions
> that are scalable, whereas a linear search is very much an inferior
> stopgap solution - adequate (barely) if all you want is a pass mark for a
> college assignment, but not a tool you'd want to use very often for this
> problem in the Real World.

I use linear searches all the time. You need a *big* table and/or a *lot* of
searches to make those fancy lookups worth the trouble.

As described, the OP's problem would need 10 to 100 million function names
before a linear search shows a noticeable delay. And at that point I'd
suggest a binary search on a pre-sorted table as still being simpler.

Possibly there could be extra marks for using a more sophisticated search --
provided the OP hasn't been distracted from finishing the main task -- but
code which is short, simple, works as intended, and uses an appropriate
search method also would have merit.

--
Bartc


Keith Thompson

unread,
May 28, 2008, 9:01:22 PM5/28/08
to
"Bartc" <b...@freeuk.com> writes:
[...]

> I use linear searches all the time. You need a *big* table and/or a *lot* of
> searches to make those fancy lookups worth the trouble.
>
> As described, the OP's problem would need 10 to 100 million function names
> before a linear search shows a noticeable delay. And at that point I'd
> suggest a binary search on a pre-sorted table as still being simpler.
[...]

As described, IIRC, each lookup is done in response to user input.
But I wouldn't bet against the program being changed so it needs to do
multiple lookups automatically. Once you do that, the difference
between, say, half a million comparisons for a linear search vs. 20
for a binary search becomes quite significant.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Bill Reid

unread,
May 28, 2008, 9:05:29 PM5/28/08
to

Richard Heathfield <r...@see.sig.invalid> wrote in message
news:Q4mdnSqGmuFRKqDV...@bt.com...
> Bartc said:
>
> > Richard Heathfield wrote:
>
> <snip>
>
> >> Construct a lookup table (e.g. hash table, binary search tree, or
> >> something like that)
> >
> > Any of these will be overkill for this task I think, and likely to give
> > more trouble than the main assignment.
> >
> > A simple linear search should be fine.
>
> A linear search through *what*? Well, gee, a lookup table.

Hey, make it an even simpler direct menu-driven "lookup" as follows:

void test_number_1(void) { }
void test_number_2(void) { }
void test_number_3(void) { }

int main(void) {
func_menu test_func_menu=
{3,3,"Test Menu",
{{"Test Number 1",test_number_1},
{"Test Number 2",test_number_2},
{"Test Number 3",test_number_3}}};

puts(program_title);

TestFunction :

test_func_menu.func_item[run_func_menu(&test_func_menu)].function();

if((get_yn_input("\nRun another test?",DEF_NO))==YES)
goto TestFunction;

return 0;
}

This is how I run "unit tests" on my libraries, as well as
other places I need simple quick "function menus"...

"func_menu" is of course a struct typedef that contains the
number of menu items, the "default" item (you can select it
by just pressing RETURN), the menu title, and a list of pairs
of menu descriptions and their associated functions.

run_func_menu(func_menu *func_menu) displays the
numbered menu selections to the user, and allows the
user to select one, which is the return value (-1) that
indexes directly to the function you want to run:

test_func_menu.func_item[run_func_menu(&test_func_menu)].function();

Actual code omitted for the sake of the OP learning to do stuff
like this on his own...

---
William Ernest Reid

Chris Thomasson

unread,
May 28, 2008, 9:47:51 PM5/28/08
to
"Shiv Ranjan" <kum...@gmail.com> wrote in message
news:b7db7a4f-df46-484f...@b5g2000pri.googlegroups.com...

You could define a common monotonic sequence number from 1 to N and postfix
that on your function names. You extract the sequence number, do a range
check, subtract 1 and that's your index. Here is example:
____________________________________________________________________
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define SEQ_MAX_BUFSIZE 3
#define SEQ_MAX 5


void display_001() { puts("display_001"); }
void display_002() { puts("display_002"); }
void display_003() { puts("display_003"); }
void display_004() { puts("display_004"); }
void display_005() { puts("display_005"); }


typedef void (*fp_func_type) (void);


static fp_func_type g_func_table[SEQ_MAX] = {
display_001,
display_002,
display_003,
display_004,
display_005
};


int main(void) {
char func_name[] = "display_005";
size_t const size = strlen(func_name);
if (size >= SEQ_MAX_BUFSIZE) {
int const idx = atoi(func_name + size - SEQ_MAX_BUFSIZE);
if (idx > 0 && idx <= SEQ_MAX) {
g_func_table[idx - 1]();
} else {
fprintf(stderr, "Bad Function Sequence Number!\n");
}
} else {
fprintf(stderr, "Bad Function Name!\n");
}
return 0;
}

____________________________________________________________________

Just make sure that every function has a different monotonically increasing
sequence number, and make sure they the minimum amount is 1, and this scheme
can be made to work in certain fairly narrow scenarios...


Any thoughts?

Martin

unread,
May 29, 2008, 4:59:56 AM5/29/08
to
On Thu, 29 May 2008 02:47:51 +0100, Chris Thomasson <cri...@comcast.net>
wrote:

> You could define a common monotonic sequence number from 1 to N and
> postfix that on your function names. You extract the sequence number, do
> a range check, subtract 1 and that's your index. Here is example:

Running with your idea, I have just a few comments:

> void display_001() { puts("display_001"); }
> void display_002() { puts("display_002"); }
> void display_003() { puts("display_003"); }
> void display_004() { puts("display_004"); }
> void display_005() { puts("display_005"); }

I would specify 'void' to specify the functions have no parameters:

void display_001(void) { puts("display_001"); }
/* etc */


> static fp_func_type g_func_table[SEQ_MAX] = {
> display_001,
> display_002,
> display_003,
> display_004,
> display_005
> };

I would let the compiler calculate the number of elements:

static fp_func_type g_func_table[] = {


display_001,
display_002,
display_003,
display_004,
display_005
};

Then, I would calculate the number of elements and store them:

#define NELEMENTS(a) (sizeof(a) / sizeof(a[0]))

static const size_t func_tab_max = NELEMENTS(g_func_table);

> if (idx > 0 && idx <= SEQ_MAX) {

The above line then would become:

if (idx > 0 && idx <= func_tab_max) {

--
Martin

Laurent Deniau

unread,
May 29, 2008, 5:36:35 AM5/29/08
to

The code below is as efficient as if you were using an AVL, but much
simpler.

a+, ld.

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

typedef const char* STR;
typedef void (*const FCT)(void);

struct lookup {
STR str;
FCT fct;
};

void display1(void);
void display2(void);

#define FCT(name) { #name, name }

static const struct lookup lookup[] = {
FCT(display1),
FCT(display2)
};

static int compare(const void *e1_, const void *e2_) {
const struct lookup *e1 = e1_;
const struct lookup *e2 = e2_;
return strcmp(e1->str, e2->str);
}

void invoke(STR str) {
const size_t s = sizeof lookup[0];
const size_t n = sizeof lookup / s;
FCT fct = bsearch(str, lookup, n, s, compare);

if (!fct) {
fprintf(stderr, "unknown function %s\n", str);
exit(EXIT_FAILURE);
}

fct();
}

Shiv Ranjan

unread,
May 29, 2008, 6:04:39 AM5/29/08
to
> pete- Hide quoted text -
>
> - Show quoted text -

Hi Pete,
I guess it's a good solution to make table as specified by you.

Thanks
Shiv

pete

unread,
May 29, 2008, 7:28:16 AM5/29/08
to

> Hi Pete,


> I guess it's a good solution to make table as specified by you.

I've done it before:

http://www.mindspring.com/~pfilandr/C/e_driver/e_driver.c

--
pete

Chris Thomasson

unread,
May 31, 2008, 4:33:17 AM5/31/08
to
"Martin" <m@b.c> wrote in message
news:op.ubwq9...@ukmp4792.pbi.global.pvt...

On Thu, 29 May 2008 02:47:51 +0100, Chris Thomasson <cri...@comcast.net>
wrote:
> > You could define a common monotonic sequence number from 1 to N and
> > postfix that on your function names. You extract the sequence number, do
> > a range check, subtract 1 and that's your index. Here is example:

> Running with your idea, I have just a few comments:

100% agreed.

[...]

0 new messages