argc/argv在c链表或二叉树中
argc/argv in c linked list or binary tree
所以我正在尝试创建链接的 list/binary 树并且:
用户应该可以在启动程序时直接从命令行选择数据结构。这应该使用 argc 或 argv 参数到 main()
我该怎么做?我不明白为什么不直接使用 switch case 语句问学生。
option 1: linked list
option 2: binary tree?
我们没有真正正确地涵盖 argc argv 谁能帮忙?
显然它是重复的...嗯..好吧,我特别询问二进制 tree/linked 列表,用户将如何告诉它选择哪种数据结构?
argc = 参数计数,argv = 参数数组。 argv[0] 是正在执行的程序。 argv[1..n] 是传递给可执行文件的参数。
示例:我用 2 个参数 bar 和 bas 调用可执行文件 foo:
foo bar bas
argc = 3, argv = [foo, bar, bas]
用下面的框架程序进行试验,找出答案。
#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 command-line 实用程序可能使用 /?
或类似的。)
假设用户可以通过以下方式运行编译程序,program
:
./program list
./program tree
./program -h
./program --help
./program
第一种形式告诉程序使用链表;第二种形式告诉程序使用树;而其他形式只是输出usage,如何调用程序的信息:
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 中是 short-circuited:如果左侧为假,则根本不会评估右侧。因此,在上面,第一个 strcmp()
检查仅在 argv == 2
时执行,第二个 argv == 2
时执行,第一个 strcmp()
返回非零(不匹配)。
换句话说,usage部分的正文只有运行当argv != 2
(有少于两个,或多于两个命令行项目,将程序名称计为一个);或者如果唯一的 command-line 参数匹配 -h
或 --help
.
!
是 C 中的 not 运算符。当且仅当 x
为零时,!x
计算为 1
或空;否则 0
。
(您可以使用 !!x
来迷惑人。如果 x
为零,则计算为零,如果 x
不为零,则计算为一。这是合乎逻辑的。它通常称为 not-not 操作。)
enum
只是提醒你魔法常量是不好的;最好使用枚举或预处理器宏(#define NO_MODE 0
等)。在一个地方使用 1
来表示 树模式 ,在另一个地方使用 2
会非常容易;这样的错误很难调试,需要人类阅读代码的注意力太多才能找到这样的错误。所以不要使用魔术常量,而是使用枚举或宏。
上面,我决定NO_MODE
的值为零,让编译器给LIST_MODE
和TREE_MODE
赋值(递增);将它们视为 compile-time 整数常量。 (意思是,您可以在 switch
语句的 case
标签中使用它们。)
因为如果两个字符串匹配 strcmp()
returns 为零,当且仅当 argv[1]
包含字符串 baz
时 !strcmp(argv[1], "baz"))
为真(非零)。当比较字符串时,您总是在 real-world 代码中看到它。
如果您在这里查看我的回答,您会经常在我的示例代码中看到 if (argc ...)
"usage" 块。这是因为即使是我自己也会经常在几天内忘记该程序的确切目的。我通常在我的机器上编写了几十个示例程序,而不是查看源代码以查看是否有什么东西让我记忆犹新,我只是 运行 没有 command-line 参数的示例片段(或者实际上,带有 -h
参数,因为有些是 filters),看看它们做了什么。它更快,阅读更少,我会更快地找到相关片段。
总而言之,在你所有的程序中写一个usage输出块,尤其是当它只是一个测试程序时你不会在任何地方发布。它们很有用,尤其是当你有一个充满各种代码片段的库时(每个代码片段都在它们自己的目录中;我使用 four-digit 数字和一个简短的描述性名称)来实现有趣或有用的东西。长的省时省力运行,凡是能让我高效懒惰的东西都在我的书里
所以我正在尝试创建链接的 list/binary 树并且:
用户应该可以在启动程序时直接从命令行选择数据结构。这应该使用 argc 或 argv 参数到 main()
我该怎么做?我不明白为什么不直接使用 switch case 语句问学生。
option 1: linked list
option 2: binary tree?
我们没有真正正确地涵盖 argc argv 谁能帮忙?
显然它是重复的...嗯..好吧,我特别询问二进制 tree/linked 列表,用户将如何告诉它选择哪种数据结构?
argc = 参数计数,argv = 参数数组。 argv[0] 是正在执行的程序。 argv[1..n] 是传递给可执行文件的参数。
示例:我用 2 个参数 bar 和 bas 调用可执行文件 foo: foo bar bas
argc = 3, argv = [foo, bar, bas]
用下面的框架程序进行试验,找出答案。
#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 command-line 实用程序可能使用 /?
或类似的。)
假设用户可以通过以下方式运行编译程序,program
:
./program list
./program tree
./program -h
./program --help
./program
第一种形式告诉程序使用链表;第二种形式告诉程序使用树;而其他形式只是输出usage,如何调用程序的信息:
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 中是 short-circuited:如果左侧为假,则根本不会评估右侧。因此,在上面,第一个 strcmp()
检查仅在 argv == 2
时执行,第二个 argv == 2
时执行,第一个 strcmp()
返回非零(不匹配)。
换句话说,usage部分的正文只有运行当argv != 2
(有少于两个,或多于两个命令行项目,将程序名称计为一个);或者如果唯一的 command-line 参数匹配 -h
或 --help
.
!
是 C 中的 not 运算符。当且仅当 x
为零时,!x
计算为 1
或空;否则 0
。
(您可以使用 !!x
来迷惑人。如果 x
为零,则计算为零,如果 x
不为零,则计算为一。这是合乎逻辑的。它通常称为 not-not 操作。)
enum
只是提醒你魔法常量是不好的;最好使用枚举或预处理器宏(#define NO_MODE 0
等)。在一个地方使用 1
来表示 树模式 ,在另一个地方使用 2
会非常容易;这样的错误很难调试,需要人类阅读代码的注意力太多才能找到这样的错误。所以不要使用魔术常量,而是使用枚举或宏。
上面,我决定NO_MODE
的值为零,让编译器给LIST_MODE
和TREE_MODE
赋值(递增);将它们视为 compile-time 整数常量。 (意思是,您可以在 switch
语句的 case
标签中使用它们。)
因为如果两个字符串匹配 strcmp()
returns 为零,当且仅当 argv[1]
包含字符串 baz
时 !strcmp(argv[1], "baz"))
为真(非零)。当比较字符串时,您总是在 real-world 代码中看到它。
如果您在这里查看我的回答,您会经常在我的示例代码中看到 if (argc ...)
"usage" 块。这是因为即使是我自己也会经常在几天内忘记该程序的确切目的。我通常在我的机器上编写了几十个示例程序,而不是查看源代码以查看是否有什么东西让我记忆犹新,我只是 运行 没有 command-line 参数的示例片段(或者实际上,带有 -h
参数,因为有些是 filters),看看它们做了什么。它更快,阅读更少,我会更快地找到相关片段。
总而言之,在你所有的程序中写一个usage输出块,尤其是当它只是一个测试程序时你不会在任何地方发布。它们很有用,尤其是当你有一个充满各种代码片段的库时(每个代码片段都在它们自己的目录中;我使用 four-digit 数字和一个简短的描述性名称)来实现有趣或有用的东西。长的省时省力运行,凡是能让我高效懒惰的东西都在我的书里