所以我想创建一个链表/二叉树并且:
用户应该能够在启动程序时直接从命令行选择数据结构。这应该使用main()
的argc或argv参数我该怎么做?我不明白为什么不只是使用switch case语句询问学生。
option 1: linked list
option 2: binary tree?
我们没有真正覆盖argc argv,任何人都可以帮忙吗?
显然它是重复的......嗯......我特别想问一下二叉树/链表如何用户告诉它选择哪种数据结构?
答案 0 :(得分:4)
尝试以下骨架程序,并找出答案。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "Usage: %s COMMAND\n", argv[0]);
return EXIT_FAILURE;
}
if (!strcmp(argv[1], "foo")) {
printf("Doing foo.\n");
} else
if (!strcmp(argv[1], "bar")) {
printf("Doing bar.\n");
} else {
fprintf(stderr, "Unknown command line parameter '%s'.\n", argv[1]);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
通知实用程序用户执行操作的最常用方法是运行不带参数的实用程序,或使用-h
或--help
作为唯一参数。 (Windows命令行实用程序可能使用/?
或类似的。)
让我们说用户可以通过以下方式运行已编译的程序program
:
./program list
./program tree
./program -h
./program --help
./program
第一个表单告诉程序使用链表;第二种形式告诉程序使用树;而其他形式只输出用法,有关如何调用程序的信息:
Usage: ./program [ -h | --help ]
./program MODE
Where MODE is one of:
list Linked-list mode
tree Tree mode
Further details on what the program actually does...
用很少的代码实现这一目标:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
enum {
NO_MODE = 0,
LIST_MODE,
TREE_MODE
};
int main(int argc, char *argv[])
{
int mode = NO_MODE;
if (argc != 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
printf("Usage: %s [ -h | --help ]\n", argv[0]);
printf(" %s MODE\n", argv[0]);
printf("\n");
printf("Where MODE is one of\n");
printf(" list for linked list mode\n");
printf(" tree for tree mode\n");
printf("\n");
printf("Further details on what the program actually does...\n");
printf("\n");
return EXIT_SUCCESS;
}
if (!strcmp(argv[1], "list"))
mode = LIST_MODE;
else
if (!strcmp(argv[1], "tree"))
mode = TREE_MODE;
else {
fprintf(stderr, "%s: Unknown MODE.\n", argv[1]);
return EXIT_FAILURE;
}
/* mode == LIST_MODE or TREE_MODE here,
depending on the first command line parameter.
*/
return EXIT_SUCCESS;
}
请注意,||
运算符在C中是短路的:如果左侧为假,则根本不对右侧进行求值。因此,在上面,第一次strcmp()
检查仅在argv == 2
时完成,第二次argv == 2
和第一次strcmp()
返回非零(不匹配)。
换句话说, usage 部分的主体仅在argv != 2
运行时(少于两个或两个以上的命令行项,将程序名称计为一个);或者,如果唯一的命令行参数与-h
或--help
匹配。
!
是C中的 not 运算符。当且仅当!x
为零或NULL时,1
计算为x
;到0
否则。
(您可以使用!!x
来混淆用户。如果x
为零,则评估为零;如果x
不为零则评估为1。这是合乎逻辑的。\ n&#39;经常被称为not-not操作。)
enum
就是在那里提醒你魔法常数是坏的;最好使用枚举或预处理器宏(#define NO_MODE 0
等)。在一个地方使用1
表示树模式,在另一个地方使用2
非常容易;这样的错误很难调试,需要从人类阅读代码的过多集中,找到这样的错误。所以不要使用魔术常量,而是使用枚举或宏。
上面,我决定NO_MODE
的值为零,让编译器将值(增加)分配给LIST_MODE
和TREE_MODE
;考虑它们的编译时整数常量。 (意思是,您可以在case
语句中的switch
标签中使用它们。)
如果strcmp()
在两个字符串匹配时返回零,则!strcmp(argv[1], "baz"))
为真(非零)当且仅当argv[1]
包含字符串baz
时。在比较字符串时,你会在真实世界的代码中一直看到它。
如果你在这里查看我的答案,你经常会看到if (argc ...)
&#34;用法&#34;在我的示例代码中阻止。这是因为即使我自己也会在几天之内忘记该计划的目的。我通常在我编写的机器上有几十个示例程序,而不是查看源代码以查看是否有什么东西慢跑我的内存,我只是在没有命令行参数的情况下运行示例代码段(或实际上,使用{{ 1}}参数,因为有些是过滤器),看看他们做了什么。它的速度更快,读数更少,而且我会更快地找到相关的代码段。
总之,在所有程序中编写使用输出块,尤其是,只要它是您在任何地方都无法发布的测试程序。它们很有用,特别是当你有一个充满它们的库时,各种代码片段(每个都在他们自己的目录中;我使用一个四位数字和一个简短的描述性名称)来实现有趣或有用的东西。从长远来看,它可以节省时间和精力,在我的书中,任何让我高效和懒惰的东西都很好。
答案 1 :(得分:0)
argc =参数count,argv =参数数组。 argv [0]是执行程序。 argv [1..n]是传递给可执行文件的参数。
示例:我使用2个参数调用可执行文件foo,bar和bas: foo bar bas
argc = 3,argv = [foo,bar,bas]