Как разобрать аргументы командной строки в c без getopt?

Я знаю, что уже есть некоторые другие вопросы и ответы об анализе аргументов командной строки в 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;
}

person Community    schedule 28.08.2017    source источник
comment
В чем дело? Что вы ожидаете от данного ввода? Что вы заметили?   -  person Gerhardh    schedule 28.08.2017
comment
Создайте MCVE.   -  person kocica    schedule 28.08.2017
comment
Вы должны начать с c = 1, так как argv[0] — это имя программы, а не аргумент.   -  person Barmar    schedule 28.08.2017
comment
Вам не нужно преобразовывать argv[c] в (char *), так как это уже его тип.   -  person Barmar    schedule 28.08.2017
comment
Помните: argv[0] не является параметром командной строки. И если вы найдете опцию и используете опцию с параметром, вы должны продвинуться на 2 вместо 1.   -  person Gerhardh    schedule 28.08.2017
comment
strcmp возвращает 0, когда строки равны.   -  person Weather Vane    schedule 28.08.2017
comment
Если опция не найдена, вы должны указать действительные значения по умолчанию для ваших переменных.   -  person Gerhardh    schedule 28.08.2017
comment
Вы также должны проверить if (argc < 3), также argv[c + 1] является неопределенным поведением на последней итерации.   -  person Weather Vane    schedule 28.08.2017


Ответы (2)


Есть несколько проблем с вашим кодом, но основная причина ваших проблем заключается в том (как указывает 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"), приведение скрыло бы от вас ошибку, поэтому вам пришлось бы отлаживать вместо того, чтобы компилятор помечал ее для вас. . В данном случае это было бы легко найти, но когда вы работаете над более сложным кодом, поиск может занять несколько дней.

person Jabberwock    schedule 28.08.2017

Следующий код я использовал в течение многих лет для анализа переключателей командной строки в стиле 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;
}
person Paul Ogilvie    schedule 28.08.2017