我想实现一个具有可变数量参数的函数。这个函数允许我使用可选参数列表调用另一个函数。这个函数的目的是根据某些条件调用任何函数(取决于被调用的函数,如果两个第一个参数相等,我们调用该函数)。我的问题是,可以调用的函数没有相同数量的参数,因此,我不知道每次有不同的函数时如何传递参数
例如,如果我有这个:
void func(int value_to_compare, int compared_value, int arg_number, char *arg_types, char *function_name, ...)
我可以这样称呼:
char arg1;
int arg2, arg3;
int condition1;
func(condition1, 1, 1, "c", func1, arg1);
func(condition1, 0, 2, "ci", func2, arg1, arg2);
func(arg2, 0 , 3, "cii", func3, arg1, arg2, arg3);
并且调用的函数如下:
func1(char);
func2(char, int);
func3(char, int, int);
我试着解释一下,如果我有例如:
struct element_list {
char *element_type;
char *element_name;
}
我的结构中的结构有很多元素,条件必须作为参数传递给函数,条件值取决于上下文,所以我必须能够在任何上下文中调用'func' ,我只给出条件和值,然后用相应的参数调用一个函数,所以它会像
func(element_list.element_type, "CHAR", func1, "s", element_list.element_name);
除此之外,我有大量的功能和大量的条件,所以我需要尽可能通用的东西。
答案 0 :(得分:4)
无论你在做什么,现在你正在使用类型系统。没有类型安全的方式在C中做你想做的事。
考虑到这一点:
一种可能的解决方案是使所有相同类型的函数:typedef void my_func_type(void*)
并让每个函数自己“解密”参数。
另一种解决方案是重新考虑您的设计 - 这是我真诚推荐给您的解决方案。但首先你需要多说一点你想在这里实现的目标...一个好的起点是展示你打算如何使用这样的功能。有可能你最终根本不需要这个......
续,#1
根据我的理解,您需要编写此代码<{1}}
func
表现得像:
char arg1;
int arg2, arg3;
int condition1;
func(condition1, 1, 1, "c", func1, arg1);
func(condition1, 0, 2, "ci", func2, arg1, arg2);
func(arg2, 0 , 3, "cii", func3, arg1, arg2, arg3);
坦率地说......最好的方法就是这样写。 : - )
既然你问这个问题,你可能想要更复杂的东西。情况是这样的:您希望在代码的控制流上构建一些抽象。这就是函数式编程风格派上用场的地方......实际上,在C ++中,事情会很简单(好吧,不是很简单,但可以通过类型安全和可移植的方式进行,有一些模板魔术奇怪的功能, if (condition1 == 1) func1(arg1);
if (condition1 == 0) func2(arg1, arg2);
if (arg2 == 0) func3(arg1, arg2, arg3);
在他们的名字中。)
我们谈论的是C而不是C ++,没有模板,没有仿函数......所以问题可能比这更复杂。但首先要做的事情是什么 - 什么阻止你使用简单的解决方案if ifs ?回答这个问题是一个好的开始。
答案 1 :(得分:1)
你有两个选择。首选的是通过struct
传递您的输入,该struct
具有输入类型和为该类型的输入定义的各种值。然后你只需将va_start
传递给你的函数(通过引用/指针)。
第二个选项是格式化参数,以便您可以使用va_arg
,va_end
和printf
来阅读它们。要使用它,您需要知道下一个arg的类型,因此您需要将其作为输入传递。您还需要提前知道何时到达最后一个arg,所以再次,您需要将其作为输入传递。这与printf
的工作方式相同,以及为什么需要将格式字符串传递给{{1}}。
答案 2 :(得分:0)
好的,这就是我的做法
void func(int value_type, void *value_to_compare, void *compared_value, char *arg_types, void (*function_name)(), ...)
我在value_type上进行了切换,根据类型,我在value_to_compare上进行了强制转换,并且compare_value,我将这些值存储在两个不同的联合中,然后我将它们进行比较,在值相等的情况下,我调用函数function_name。关于要调用的函数,我根据arg_types进行强制转换,然后我做了一些非常愚蠢的事情,这是一个像这样的开关:
switch(strlen(arg_types)) {
case 0:
function_name();
break;
case 1:
function_name(args[0]);
break;
case 2:
function_name(args[0], args[1]);
break;
...
}
其中args是
void* args[MAX_NUMBER_ARGS];
我接受了数组args的每个元素,并且根据arg_types,我做了一个演员,但我找不到更好的解决方案......