Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C getopt multiple value

Tags:

c

input

getopt

My argument is like this

./a.out -i file1 file2 file3

How can I utilize getopt() to get 3 (or more) input files? I'm doing something like this:

while ((opt = getopt(argc, argv, "i:xyz.."))!= -1){
  case 'i':
     input = optarg; 
     break;
  ...
}

I get just the file1; how to get file2, file3?

like image 999
w00d Avatar asked Oct 15 '10 02:10

w00d


People also ask

What does getopt do in C?

The getopt() function is a builtin function in C and is used to parse command line arguments. Syntax: getopt(int argc, char *const argv[], const char *optstring) optstring is simply a list of characters, each representing a single character option.

What does getopt return?

RETURN VALUE The getopt() function returns the next option character specified on the command line. A colon (:) is returned if getopt() detects a missing argument and the first character of optstring was a colon (:).

What is Optind in getopt?

The variable optind is the index of the next element of argv to be processed. It is initialized to 1, and getopt() updates it as it processes each element of argv[]. The getopt() function returns the next option character (if one is found) from argv that matches a character in optstring, if any.

What does the getopt function return when there is no more work to do?

RETURN VALUE The getopt() function shall return the next option character specified on the command line. A colon ( ':' ) shall be returned if getopt() detects a missing argument and the first character of optstring was a colon ( ':' ).


3 Answers

I know this is quite old but I came across this in my search for a solution.

while((command = getopt(argc, argv, "a:")) != -1){

    switch(command){
        case 'a':

        (...)

        optind--;
        for( ;optind < argc && *argv[optind] != '-'; optind++){
              DoSomething( argv[optind] );         
        }

        break;
    }

I found that int optind (extern used by getopt() ) points to next position after the 'current argv' selected by getopt(); That's why I decrease it at the beginning.

First of all for loop checks if the value of current argument is within boundaries of argv (argc is the length of array so last position in array argv is argc-1). Second part of && compares if the next argument's first char is '-'. If the first char is '-' then we run out of next values for current argument else argv[optind] is our next value. And so on until the argv is over or argument runs out of values.

At the end increment optind to check for the next argv.

Note that because we are checking 'optind < argc' first second part of condition will not be executed unless first part is true so no worries of reading outside of array boundaries.

PS I am a quite new C programmer if someone has an improvements or critique please share it.

like image 140
GoTTimw Avatar answered Oct 09 '22 06:10

GoTTimw


If you must, you could start at argv[optind] and increment optind yourself. However, I would recommend against this since I consider that syntax to be poor form. (How would you know when you've reached the end of the list? What if someone has a file named with a - as the first character?)

I think that it would be better yet to change your syntax to either:

/a.out -i file1 -i file2 -i file3

Or to treat the list of files as positional parameters:

/a.out file1 file2 file3
like image 32
jamesdlin Avatar answered Oct 09 '22 07:10

jamesdlin


Note that glibc's nonconformant argument permutation extension will break any attempt to use multiple arguments to -i in this manner. And on non-GNU systems, the "second argument to -i" will be interpreted as the first non-option argument, halting any further option parsing. With these issues in mind, I would drop getopt and write your own command line parser if you want to use this syntax, since it's not a syntax supported by getopt.

like image 6
R.. GitHub STOP HELPING ICE Avatar answered Oct 09 '22 08:10

R.. GitHub STOP HELPING ICE