Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing optional command line arguments in C

I have a program that takes in optional arguments. The necessary arguments are a file and integers (1 or more). The optional arguments are a mix of strings and integers.

So a correct input on the command line could be:

./main trace_file 8 12 # (only necessary arguments)

./main –n 3000000 –p page.txt trace_file 8 7 4 # (with optional arguments)

I need to get the integers after trace_file into an array. I'm having trouble figuring out how to do this when the optional arguments are enabled, because another integer is on the command line. A push in the right direction would be greatly appreciated, because I cannot figure out how to do this.

EDIT: so far, all I have for parsing the arguments is this:

for(j=2, k=0; j<argc; j++, k++) {
    shift += atoi(argv[j]);
    shiftArr[k] = 32 - shift;
    bitMaskArr[k] = (int)(pow(2, atoi(argv[j])) - 1) << (shiftArr[k]);
    entryCnt[k] = (int)pow(2, atoi(argv[j]));
}

But this will only work when no optional arguments are entered.

like image 694
Ybarra Avatar asked Apr 28 '15 03:04

Ybarra


1 Answers

I don't see any major problems if you use a reasonably POSIX-compliant version of getopt().

Source code (goo.c)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

/*
   ./main trace_file 8 12 # (only necessary arguments)

   ./main –n 3000000 –p page.txt trace_file 8 7 4 # (with optional arguments)
 */

static void usage(const char *argv0)
{
    fprintf(stderr, "Usage: %s [-n number][-p pagefile] trace n1 n2 ...\n", argv0);
    exit(EXIT_FAILURE);
}

int main(int argc, char **argv)
{
    int number = 0;
    char *pagefile = "default.txt";
    char *tracefile;
    int opt;

    while ((opt = getopt(argc, argv, "n:p:")) != -1)
    {
        switch (opt)
        {
        case 'p':
            pagefile = optarg;
            break;
        case 'n':
            number = atoi(optarg);
            break;
        default:
            usage(argv[0]);
        }
    }

    if (argc - optind < 3)
    {
        fprintf(stderr, "%s: too few arguments\n", argv[0]);
        usage(argv[0]);
    }

    tracefile = argv[optind++];
    printf("Trace file: %s\n", tracefile);
    printf("Page file:  %s\n", pagefile);
    printf("Multiplier: %d\n", number);
    for (int i = optind; i < argc; i++)
        printf("Processing number: %d (%s)\n", atoi(argv[i]), argv[i]);
    return 0;
}

Compilation

$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
>      -Wold-style-definition -Werror goo.c -o goo

Example runs

$ ./goo trace_file 8 12
Trace file: trace_file
Page file:  default.txt
Multiplier: 0
Processing number: 8 (8)
Processing number: 12 (12)
$ ./goo -n 3000000 -p page.txt trace_file 8 7 4
Trace file: trace_file
Page file:  page.txt
Multiplier: 3000000
Processing number: 8 (8)
Processing number: 7 (7)
Processing number: 4 (4)
$
like image 50
Jonathan Leffler Avatar answered Nov 16 '22 05:11

Jonathan Leffler