【问题标题】:How can I have access into *argv[ ] in C?如何在 C 中访问 *argv[ ]?
【发布时间】:2020-05-28 16:24:48
【问题描述】:

假设我有这部分代码。如果用户没有输入文件名作为命令行参数,我想再次询问他以便现在输入它们,但似乎我无法访问 argv[1] 和 argv[2]。例如,当执行第一个 scanf 时,会发生分段错误。但在这种情况下,我如何读取参数并将它们放入 argv[1] 和 argv[2] 中? 提前感谢您的帮助!

int main (int argc, char **argv)
{
    if (argc != 3)
    {
        printf("You did not enter two files.\n");
        printf("You can now enter those two files.\n");
        printf("file 1: ");
        scanf("%s", argv[1]);
        printf("file 2: ");
        scanf("%s ", argv[2]);
    }

    printf("%s\n", argv[1]);
    printf("%s\n", argv[2]);

    FILE *file1 = fopen(argv[1], "r");
    FILE *file2 = fopen(argv[2], "r");
}

【问题讨论】:

标签: c arguments


【解决方案1】:

你没有。正如流行的说法,计算机科学中的每个问题都可以通过额外的间接层来解决。在这种情况下,间接方法是定义一个干净的接口来打开文件并传递一个char const*。但是这个指针不一定是argv[1]

你必须 malloc 自己的缓冲区(因为 none 存在)并写入它。为此目的使用scanf("%s",...) 可能会导致缓冲区溢出,因为您无法提前知道缓冲区需要多大。

编辑:给你的每一个建议使用char buffer[NUMBER] 作为scanf 的缓冲区的答案都会在你的脸上炸开

【讨论】:

  • 并且可能会指出,在这个问题的答案中看到缓冲区大小升级是多么有趣;首先,一个人建议 20 个字节,然后另一个人建议完全相同的解决方案,但使用 100 个字节,然后是第三个副本,但现在使用 255 个字节。不安全的缓冲区处理是不安全的,不管你的缓冲区大小有多荒谬。
  • Posix-only(但这是很多系统):scanf("%ms", &str); 简化了一切。
【解决方案2】:

发生分段错误是因为 argv 数组的长度是在用户运行程序时确定的。如果你运行这样的程序:

./programName

argv 只有 1 个元素长。之后无法访问 argv[1] 或 argv[2] 。不过,您可以获取必要的数据并将它们保存在常规变量中。

【讨论】:

    【解决方案3】:

    Argv 是从控制台传递的,您在执行程序时传递它。

    首先,你必须编译它,例如:

    gcc program.c -o program

    然后带参数执行,例如:

    ./program arg1 arg2

    如果您希望等待用户通过控制台为您的程序输入参数,您应该使用常规变量。

    【讨论】:

      【解决方案4】:

      请注意,argv[1]argv[2] 仅在 argc >= 3 时有效。 因此访问它们当然是错误的。

      如果你想从标准输入读取参数,你必须确保你有内存来保存这些字符串。 你可能会使用类似的东西

      char filename1[20], filename2[20];
      char *f1, *f2;
      if (argc == 3) {
        f1 = argv[1];
        f2 = argv[2];
      } else {
        f1 = filename1;
        f2 = filename2;
        /* add code to read into filename1 and filename2 */
      }
      /* use f1 and f2 */
      

      你可以看到我只为每个文件名保留了 20 个字节,这是我任意选择的。 此处至关重要的是不要将超过 20 个字节写入这些数组(包括终止 NUL 字符),因此您不应像这样使用 scanf。

      您可以看到,这在 C 中并不是很直接,因此也没有适合所有用途的答案。

      编辑:也请确保永远不要写入任何argc[...] 内存,因为它是由系统提供的。虽然没有标记const,但我宁愿这样考虑。

      【讨论】:

        【解决方案5】:

        您不能这样做,因为 argv[1]argv[2] 是 NULL 指针(如果它们甚至存在于数组中),因此您无法访问它们。

        您需要以不同的方式解决问题。

        不要尝试更改 argv 的成员,而是将它们分配给保存文件名的其他变量。

        int main (int argc, char **argv)
        {
            char file1[100], file2[100];
            if (argc != 3)
            {
                printf("You did not enter two files.\n");
                printf("You can now enter those two files.\n");
                printf("file 1: ");
                scanf("%s", file1);
                printf("file 2: ");
                scanf("%s ", file2);
            } else {
                strcpy(file1, argv[1]);
                strcpy(file2, argv[2]);
            }
        
            printf("%s\n", file1);
            printf("%s\n", file2);
        
            FILE *file1 = fopen(file1, "r");
            FILE *file2 = fopen(file2, "r");
        }
        

        请注意,我对文件名的长度做了一些假设。根据需要进行调整。

        【讨论】:

        • 如果我错了,请纠正我,但我很确定它们根本不存在。它们绝对不是 NULL 指针。如果是,你可以做argv[1] = malloc(size),但你不能。
        • @klutt 实际上,我认为 argv[1] 会存在并且为 NULL。
        • 这看起来很奇怪。假设是真的,数组有多大?
        • @klutt 我相信是argc+1argv[argc] == NULL
        【解决方案6】:

        将它们放在argv 是错误的方法。做这样的事情要好得多:

        int main (int argc, char **argv)
        {
            char f1[255];
            char f2[255];
            if (argc != 3)
            {
                printf("You did not enter two files.\n");
                printf("You can now enter those two files.\n");
                printf("file 1: ");
                scanf("%s", f1);
                printf("file 2: ");
                scanf("%s ", f2);
            } else {
                strcpy(f1, argv[1]);
                strcpy(f2, argv[2]);
            }
            FILE *file1 = fopen(f1, "r");
            FILE *file2 = fopen(f2, "r");
        }
        

        您应该避免写信给argv。这通常是个坏主意。

        【讨论】:

          猜你喜欢
          • 2011-12-19
          • 1970-01-01
          • 2011-12-16
          • 1970-01-01
          • 2012-03-05
          • 2017-06-27
          • 2011-02-16
          • 2011-05-02
          相关资源
          最近更新 更多