user8495585
user8495585

Reputation:

How to parse command line arguments in c without getopt?

I know there are already some other questions and answers about parsing command line args in c, but I hope that somebody can tell me why my code is not working. Here's my code. I want to parse my arguments without external headers like getopt.h /(unistd.h) or 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;
}

Upvotes: 0

Views: 5946

Answers (2)

One Guy Hacking
One Guy Hacking

Reputation: 1291

There are several problems with your code, but the main one that is causing your problems is (as Weather Vane points out) that you have the return value of strcmp() backwards--it returns true if the strings are different (actually, it returns a positive or negative number indicating which of the strings has the lower first-character-that-differs; or zero if the strings are identical).

Additionally, you do not check to ensure that there is an argument following the -i or -o argument. Consider what your code will do if it gets called as progname -i

Further, after taking argv[c + 1] as a filename, you don't increment c, so the next time through the loop you will strcmp() it as an option. This will break if you happen to name your input file -o, for example. Consider how you will parse progname -i -o -o -i (admittedly a contrived example, but you ought to be able to handle such things).

Also, the cast of argv[c] to (char *) is unnecessary (it is already a char *, and strcmp() takes a char * anyways, so it would have been auto-promoted even if it hadn't been). In general, all that casting accomplishes is hiding bugs from you--had you miswritten this as (say) calling strcmp(argv, "-i") the cast would have hidden the error from you, so you would have had to debug instead of having the compiler flag it for you. It would have been an easy find in this case, but when you are working on more complex code it could take you days to find.

Upvotes: 1

Paul Ogilvie
Paul Ogilvie

Reputation: 25286

The following code I have been using for years to parse unix-style command line switches. Adapt as needed:

#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;
}

Upvotes: 0

Related Questions