【问题标题】:argc/argv in c linked list or binary treec链表或二叉树中的argc/argv
【发布时间】:2018-09-02 13:34:06
【问题描述】:

所以我正在尝试制作一个链表/二叉树并且:

用户应该能够在启动程序时直接从命令行选择数据结构。这应该使用 main() 的 argc 或 argv 参数

我该怎么做?我不明白为什么不直接使用 switch case 语句询问学生。

     option 1: linked list 

     option 2: binary tree?

我们没有真正正确地涵盖 argc argv 谁能帮忙?

显然它是重复的......嗯..我特别询问二叉树/链表用户将如何告诉它选择哪种数据结构?

【问题讨论】:

  • @Tormund Giantsbane Uhh no
  • @Coder 对于试图提供帮助的人,这是一个非常时髦的回应。也许您可以详细说明 Tormund 的链接如何无法回答您的问题。
  • 对不起..我更新了它
  • Switch/Case 和 argc/argv 不是非此即彼。您希望您的开关/案例如何从用户那里获得输入以指示数据结构的类型?
  • 您太专注于在链表或二叉树之间进行选择..他们可能会在香蕉和雨伞之间进行选择,关键是您需要学习如何访问和解析命令行论据。菜单驱动的程序,例如“选择一个选项:\n 1. 链表\n 2. 二叉树\n 3. 退出”就可以了。

标签: c command-line-arguments


【解决方案1】:

用下面的骨架程序做实验,找出答案。

#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,如何调用程序的信息:

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 时,!x 的计算结果为 1;否则发给0

(您可以通过使用!!x 来迷惑人们。如果x 为零,则计算为零,如果x 不为零,则为一。这是合乎逻辑的。通常称为非非操作。)

enum 只是提醒您魔术常数不好;最好使用枚举或预处理器宏(#define NO_MODE 0 等)。在一个地方使用1 来表示树模式,而在另一个地方使用2 会非常容易;这样的错误很难调试,需要人类阅读代码的太多注意力才能找到这样的错误。所以不要使用魔法常量,而是使用枚举或宏。

上面,我决定NO_MODE的值为零,并让编译器将值分配(增加)给LIST_MODETREE_MODE;将它们视为编译时整数常量。 (意思是,您可以在switch 语句中的case 标签中使用它们。)

因为strcmp() 在两个字符串匹配时返回零,所以当且仅当argv[1] 包含字符串baz!strcmp(argv[1], "baz")) 为真(非零)。在比较字符串时,您总是在实际代码中看到它。

如果您在此处查看我的答案,您会经常在我的示例代码中看到 if (argc ...) "usage" 块。这是因为即使是我自己也会经常在几天之内忘记该计划的确切目的是什么。我通常在我的机器上编写了几十个示例程序,而不是查看源代码来查看是否有什么东西让我记忆犹新,我只是简单地运行示例 sn-ps 而不使用命令行参数(或者实际上,使用 @987654359 @ 参数,因为有些是过滤器),看看它们做了什么。速度更快,阅读量更少,我会更快找到相关的sn-p。

总之,在你的所有程序中编写一个用法输出块,尤其是当它只是一个你不会在任何地方发布的测试程序时。它们很有用,特别是当你有一个充满它们的库时,各种代码 sn-ps(每个都在它们自己的目录中;我使用一个四位数字和一个简短的描述性名称)来实现有趣或有用的东西。从长远来看,它可以节省时间和精力,任何让我变得高效和懒惰的东西在我的书中都是好的。

【讨论】:

  • 一个问题 ! 是什么意思在stcmp之前
  • 甚至在它运行之前,用户如何知道要输入什么?我不能执行代码,除非他们输入完全相同
  • @Coder:如果您需要进一步说明,请告诉我。我决定展示一个完整的工作示例,即使您可能会在不理解它的情况下将其逐字用作自己的工作,但存在轻微风险;为了确保不会发生这种情况,我明确表示你的助教/老师会通过简单地问一两个问题来抓住你。一切都在正文中进行了解释,而且一点也不难,因此,如果您费心阅读正文,并了解代码的工作原理和原因,以及为什么它应该以这种方式工作,那么您就遥遥领先。这应该是值得的。
【解决方案2】:

argc = 参数计数,argv = 参数数组。 argv[0] 是正在执行的程序。 argv[1..n] 是传递给可执行文件的参数。

示例:我用 2 个参数 bar 和 bas 调用可执行文件 foo: 富吧巴斯

argc = 3, argv = [foo, bar, bas]

【讨论】:

  • 用户如何选择二叉树或链表?
  • 没有看到你的任务要求,这真的取决于你如何组织和编写你的程序以及你使用参数的目的。
  • @Coder 期望用户传入代表选择的字符串或数字,然后检查给出的内容。
  • 没有任何要求,只是这么说,所以我不知道从哪里开始,也不知道用户如何选择哪种数据结构
  • 所以,如果这是我的任务,我会让用户传递一个参数,比如“1”或“2”来选择结构,然后在程序内部进行测试/打开这个论点,很可能是 argv[1]。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-10
  • 1970-01-01
  • 2014-06-01
  • 2012-03-17
  • 2011-04-15
  • 2020-10-12
  • 1970-01-01
相关资源
最近更新 更多