Da Frenk
Da Frenk

Reputation: 295

Get two parameters to main with one optional argument

I want to pass command line arguments to main. It should be done via a option specifier like -a 4. For single char and a singe value everything works fine, but when trying to pass two values per option it only works when put in last.

The following code works as wanted when used like this ./a.out -a 4 -b 6 -r 2 1

a:4
b:6
x_0:2
y_0:1

However using ./a.out -r 2 3 -a 32 only the default values for a and b are used.

a:1
b:1
x_0:2
y_0:3

Has it to do with the increment of argv and argc?

Thanks for your help.

Code: Compile with g++ main.cc

//--------------------------------------
//  Includes
//--------------------------------------
#include <iostream>
#include <cstdlib>

//--------------------------------------
//  Function Declarations
//--------------------------------------
void getArgsToMain(int argc, char *argv[]);
void showVars();

//--------------------------------------
//  Variable declarations
//--------------------------------------
double a    = 1.;
double b    = 1.;
double x_0  = a;
double y_0  = 0.;

// typedefs and namespace
using namespace std;    

// ===  FUNCTION  ======================
//         Name:  main
//  Description:  
// =====================================
int main ( int  argc , char * argv[] )
{
    getArgsToMain(argc, argv);
    showVars();
    return 0;
}// ----------  end of function main  ----------


//--------------------------------------
//  Main function implementations
//--------------------------------------
void getArgsToMain(int argc, char *argv[])
{
    while ((argc>1) && (argv[1][0]=='-'))
    {
        switch(argv[1][1])
        {
            case 'a':
                 a=atof(argv[2]);
                 break;
            case 'b':
                 b=atof(argv[2]);
                 break;
            case 'r':
                 x_0=atof(argv[2]);
                 if (!argv[3])
                        cout<<"Warning: No y_0 specified. Reverting to default."<<endl;
                 else
                    y_0=atof(argv[3]);
                 break;
            default: 
                 cout<<"Usage: blabla";
                 exit(0);
        }
        argv++;
        argv++;
        argc--;
        argc--;
    }
}

void showVars()
{
    cout << endl;
    cout << "a:" << a << endl;
    cout << "b:" << b << endl;
    cout << "x_0:" << x_0 << endl;
    cout << "y_0:" << y_0 << endl;
}

Upvotes: 1

Views: 891

Answers (2)

Olaf Dietsche
Olaf Dietsche

Reputation: 74018

You need an additional argv++, argc-- for your two values per option case. Test also, if the second value is already the next option.

case 'r':
     x_0=atof(argv[2]);
     if (!argv[3] || argv[3][0] == '-') {
            cout<<"Warning: No y_0 specified. Reverting to default."<<endl;
     } else {
        y_0=atof(argv[3]);
        argv++;
        argc--;
     }
     break;

As @ezod suggested, you might use getopt. See Supplying two arguments to command line option using getopt and C getopt multiple value for similar requirements regarding getopt.

Upvotes: 1

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 153792

You are effectively stepping through the array of arguments received. When you are stepping you need to "consume" as many of the arguments as you used. Each word on the command-line becomes one argument (unless you combine multiple words into one one argument using quotes). When you process something like -r a b as one unit, you are consuming three arguments.

Your code assumes you are always consuming a pair of arguments. Note, that you may fail to process the arguments to your -r flag if you only pass it one argument: there is no check guarding against a missing argument: you check that you have at least two arguments remaining but the -r flag requires a total of three arguments.

Upvotes: 1

Related Questions