【问题标题】:How to parse command line arguments in c without getopt?如何在没有getopt的情况下解析c中的命令行参数?
【发布时间】:2017-08-28 13:38:03
【问题描述】:

我知道已经有一些关于在 c 中解析命令行参数的其他问题和答案,但我希望有人能告诉我为什么我的代码不起作用。这是我的代码。我想解析我的论点,而不需要像 getopt.h /(unistd.h) 或 args.h

这样的外部头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void showUsage(char *prog) {
  printf("Usage for %s...", prog);
}

int main(int argc, char *argv[]) {

if (argc == 1) {
    showUsage(argv[0]);
    return EXIT_FAILURE;
}
int c;
char *input, *output;

for (c = 0; c < argc; ++c) {
    if (strcmp((char *)argv[c], "-i")) {
        input = (char *)argv[c + 1];
    }
    if (strcmp((char *)argv[c], "-o")) {
        output = (char *)argv[c + 1];
     }
  }
 printf("\nInput %s Output: %s", input, output);
 return EXIT_SUCCESS;
}

【问题讨论】:

  • 你的问题是什么?你期望给定的输入会发生什么?你观察到了什么?
  • 请创建MCVE
  • 您应该从c = 1 开始,因为argv[0] 是程序名称,而不是参数。
  • strcmp 在字符串相等时返回0
  • 如果没有找到一个选项,你应该为你的变量提供有效的默认值。

标签: c arguments getopt


【解决方案1】:

您的代码有几个问题,但导致问题的主要问题是(正如 Weather Vane 指出的那样)您有 strcmp() 的返回值向后 - 如果字符串不同,它返回 true (实际上,它返回一个正数或负数,指示哪个字符串具有较低的第一个不同的字符;如果字符串相同,则返回零。

此外,您无需检查以确保 -i 或 -o 参数后面有参数。考虑一下如果你的代码被称为progname -i

此外,在将 argv[c + 1] 作为文件名之后,您不会递增 c,因此下次通过循环时,您会将 strcmp() 作为选项。例如,如果您碰巧将输入文件命名为 -o,这将中断。考虑一下你将如何解析progname -i -o -o -i(诚然是一个人为的例子,但你应该能够处理这样的事情)。

此外,将 argv[c] 转换为 (char *) 是不必要的(它已经是一个 char *,而 strcmp() 无论如何都需要一个 char *,所以即使它没有,它也会被自动提升。没有)。一般来说,转换完成的所有工作都是向您隐藏错误——如果您将其误写为(比如说)调用strcmp(argv, "-i"),那么转换将向您隐藏错误,因此您将不得不调试而不是让编译器标记它为你。在这种情况下很容易找到,但是当您处理更复杂的代码时,可能需要几天时间才能找到。

【讨论】:

    【解决方案2】:

    多年来我一直在使用以下代码来解析 unix 样式的命令行开关。根据需要进行调整:

    #include <stdio.h>
    
    int  i, files;
    FILE *inf, *outf;
    
    int main (int argc, char *argv[])
    {
    
      /* process switches; other prms are considered files (2)
         that are opened for input/output. Files not specified
         are taken as stdin and stdout.
      */
    
      while (++i < argc)
        switch (argv[i][0]) {
          case '-': while (*++argv[i])
                      switch (*argv[i]) {
                      case 'n': case 'N':
                            ++argv[i]; number= 0;
                            while (isdigit(*argv[i]))
                                number = number *10 + *argv[i]++ - '0';
                            argv[i]--;
                            break;
    
                        case 'P' : printf ("Prm: P\n"); break;
                        case 'O' : printf ("Prm: O\n"); break;
                      default :
                        printf ("Bad switch %c, ignored.\n",*argv[i]);
                      }
                    break;
    
          default :
            switch (files) {
            case 0: if ((inf=fopen(argv[i],"r")) == 0)
                        pexit("Input file %s not found.\n", argv[i]);
                    files++; break;
            case 1: if ((outf=fopen(argv[i],"w")) == 0)
                        pexit (" Error creating output file %s.\n", argv[i]);
                    files++; break;
            case 2: printf ("Too many file arguments: %s ignored.\n",argv[i]);
                    break;
            } /* end switch files */
          } /* end switch argc */
    
        if (files <1) inf = stdin;
        if (files <2) outf = stdout;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-23
      • 2021-07-26
      • 1970-01-01
      • 1970-01-01
      • 2022-09-28
      • 2010-12-15
      • 2015-06-23
      相关资源
      最近更新 更多