是否可以从C中的数组调用函数?

时间:2018-11-03 17:58:32

标签: c function mingw

在进行终端操作时,我想知道是否可以通过数组调用函数。 (此代码尚未完成,因此,代码有点混乱。)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <unistd.h>
#include <limits.h>
#define true 1
#define false 0
typedef int bool;

/* Static */
static char Input[CHAR_MAX];
static char CurrentDirectory[CHAR_MAX];
static char *Command;
static char *Argument;
static char *Commands[]={"test","test2"};

/* Functions */
int Check_Command();
int test();
int test2();
/* --------- */

int main(){
    printf("#######################\n\tterminal\n\tType \"help\" for the list of commands\n#######################\n");
    prompt:
    printf(">");
    fgets(Input,CHAR_MAX,stdin);
    int res=Check_Command();
    if(res==0){printf("Unknown Command!\n");}
    goto prompt;
}
/* Check_Command() function returns 0 if doesn't suceed and returns 1 of it suceeds */
int Check_Command(){
    //Since input variable is static, no need to send in arguments
    Input[strcspn(Input,"\r\n")]=0;
    Command=strtok(Input," ");
    Argument=strtok(NULL," ");
    int x=0;
    while(x<sizeof(Commands)){
        if(strcmp(Command,Commands[x])==0){
            Commands[x](); <----- Can I call a function like this?
            return 1;
        }
        x++;
    }
    return 0;
}

/* Commands */
int test(){
    printf("Success!\n");
    getchar();
    exit(0);
}

int test2(){
    print("Success [2] \n");
    getchar();
    exit(0);
}

如果可能的话,这将被点亮,我太懒了,无法将命令制作为可执行文件,并对所有命令使用if语句。 如果您懒于阅读整个代码,那么这里是一个基本概念(未测试):

static *Commands[]={"test","test2"};
int main(){
    char *Command="test";
    int x=0;
    while(x<sizeof(Commands)){
        if(strcmp(Command,Commands)==0){
            Commands[x]();
        }
        x++
    }
}
int test(){
   printf("Hi");
}
int test2(){
    printf("hey");
}

编辑:

  

static char Commands [] = {test,test2};不起作用   这也包括“可能重复”的答案。 (我正在使用Windows 10的Mingw)

1 个答案:

答案 0 :(得分:1)

您似乎希望能够从用户那里接收诸如test2之类的字符串,然后调用函数test2()。您可以通过以下两种主要方法进行处理:

  1. 自酿结构将名称映射到函数指针。
  2. 使用“动态库加载”和函数名称解析。

结构数组

首先,您定义一个结构,例如:

struct FuncName
{
    const char *name;
    int (*function)(void);
};

然后您可以定义这些数组:

struct FuncName functions[] =
{
    { "test",  test  },
    { "test2", test2 },
};
enum { NUM_FUNCTIONS = sizeof(functions) / sizeof(functions[0]) };

从用户那里获得名称时,您可以搜索名称数组并找到要调用的匹配函数指针。

int invoke_function(const char *name)
{
    for (int i = 0; i < NUM_FUNCTIONS; i++)
    {
        if (strcmp(name, functions[i].name) == 0)
        {
            return (*functions[i].function)();
            // Or just: return functions[i].function();
        }
    }
    return -1;   // No match found
}

这在所有系统上都能可靠地工作,但是缺点是在编译程序时必须创建函数指针表。

动态库

替代方法是在Unix(POSIX)系统上使用<dlsym.h>标头中的函数dlopen()dlsym(),或者在Windows上使用等效功能。

通常,您希望在装有dlopen()的动态加载的库中找到函数,但是通常可以通过一种方法在主可执行文件中搜索名称(将空指针作为文件名传递给{{1 }}(在POSIX系统上)。然后,您可以调用dlopen()来获取与您指定的名称相对应的函数指针,您可以对其进行调用。

dlsym()

这省略了错误检查,并且您需要将类型转换从对象指针(void *dlh = dlopen(NULL, RTLD_NOW); int (*funcptr)(void) = (int (*)(void))dlsym("test", dlh); return (*funcptr)(); )转换为函数指针,因为C标准并不要求这么做,但是POSIX要求这样做(请参阅 dlsym()已链接到)。

非均匀函数签名

使用这两种解决方案,如果所有可调用函数都具有相同的接口,则生活会很轻松。如果不同的函数具有不同的接口,那么生活会变得更加混乱(因此,有些函数不希望有参数,有些函数希望有一个参数,有些函数希望有两个参数,并且函数之间的参数类型也有所不同,返回类型也一样)。期望使用大量的强制转换,并准备将编译器拖入提交阶段-将代码与其他所有内容隔离开来,以使不可移植的部分与主代码完全分开。

要当心:没有咨询任何编译器以了解这些代码的有效性!