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_MODETREE_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 数字和一个简短的描述性名称)来实现有趣或有用的东西。长的省时省力运行,凡是能让我高效懒惰的东西都在我的书里