【发布时间】:2017-07-09 01:25:20
【问题描述】:
这个问题是关于如何在我设计程序的层面上解决我的问题。对于一个学校项目,我正在构建一个外壳,它具有几个内置功能。这些函数的目的之一 (cmd_type) 是检查提供的参数是否在该函数列表中。这是它的部分实现:
int cmd_type(int argc, char *argv[]) {
if (argc == 2) {
for (int i = 0; i < BUILTIN_FUNC_COUNT; i++) {
if (strcmp(cmds_name[i], argv[1]) == 0) {
printf("%s is a shell builtin\n", argv[1]);
return 0; // found it
}
}
// still need to search path, call stat(path/cmd)
errmsg("not implemented! type", 1);
} else {
err_msg("type", 1);
}
}
为我的 shell 支持的每个函数定义手动 if 语句听起来是个糟糕的选择,因为列表可能会随着时间的推移而扩展,而且我无论如何都需要存储函数名称列表。所以最初,我打算定义一个函数名数组和一个它们的指针数组,如下所示:
char cmds_name[BUILTIN_FUNC_COUNT-1][16];
char (*cmds_ptr)(int,*char[])[BUILTIN_FUNC_COUNT-1];
// make list of built-in funcs
strcpy(cmds_name[0], "exit");
strcpy(cmds_name[1], "cd");
// make list of func pointers
cmds_ptr[0] = &cmd_exit;
cmds_ptr[1] = &cmd_cd;
它们的访问方式如下:
// try builtin cmds
for (int i = 0; i < BUILTIN_FUNC_COUNT; i++) {
if (strcmp(cmds_name[i], argv[0]) == 0) {
last_cmd_err = (*cmds_ptr[i])(argc, argv);
continue; // we found it, so next loop
}
}
然后他们每个人都会很高兴地将 (int argc, char *argv[]) 作为参数。但是除了这些参数之外, cmd_path() 还需要访问列表,所以我必须将它定义为全局,或者定义一个指向它的全局指针......在研究这个的过程中,我找到了这个答案,说类似的方法真的很糟糕:https://stackoverflow.com/a/41425477/5537652
所以我的问题是:这是解决这个问题的好方法,还是我应该只做 if/else 语句/有更好的方法吗?你会推荐一个指向函数名数组的全局指针吗?
【问题讨论】:
-
解决它的一种方法是定义一个结构数组(而不是两个独立的名称和指针数组),并使用
int builtin_cmd(int argc, char **argv, void *extra);的原型定义函数。额外的指针指向函数需要的任何额外信息。如果你能设计一个类型——可能是某种结构指针——而不是空泛的void *,那会更好,但这是最通用的类型。不需要额外信息的函数可以传递一个空指针,也可以忽略它们传递的指针。 -
在全局化或隐藏之前,将具有名称和函数指针的结构设为对结构,并通过按名称在数组中对它们进行排序来使用二进制搜索。
-
OT:此
char (*cmds_ptr)(int,*char[])[BUILTIN_FUNC_COUNT-1];与此for (int i = 0; i < BUILTIN_FUNC_COUNT; i++) { if (strcmp(cmds_name[i], ...不太对应。
标签: c