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
> 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
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
(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
/* 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
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 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
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.
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
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"
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
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?
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
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();
}
Hi Pete,
I guess it's a good solution to make table as specified by you.
Thanks
Shiv
> 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
> Running with your idea, I have just a few comments:
100% agreed.
[...]