Reputation: 93
I am attempting to use atoi on optarg but it might as well be anything. I have been trying to figure out why my getopt_long is not working. When I enter my switch statement optarg is set to null and it stays that way. I have checked my colons and they are correct. This is my code.
static struct option long_options[] =
{
{"algorithm", required_argument, 0, 'a'},
{"reverse", no_argument, 0, 'r'},
{"key", required_argument, 0, 'k'},
{"output", required_argument, 0, 'o'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0}
};
int option_index = 0;
int c;
//Getopt to get the correct options from the command line.
while ((c = getopt_long(argc, argv, "a:rk:o:hV", long_options,
&option_index)) != -1)
{
bool endOption = false;
if (endOption) break;
switch (c)
{
case 0:
{
endOption = true;
break;
}
case 'a':
{
if (optarg == "insertion") algorithm = 0;
break;
}
case 'r':
{
reverseFlag = true;
break;
}
case 'k':
{
while (optarg != " ")
{
if (optarg == ",")
{
optarg++;
}
else
{
sortOrder.push_back(atoi(optarg)); //error here
optarg++;
}
}
}
case 'o':
{
fileFlag = true;
break;
}
case 'h':
case 'V':
default:
{
cerr<<"You have entered an incorrect flag, do it better"<<endl;
break;
}
}
}
//more stuff//
I have tried using double colons and just about everything else.
Upvotes: 1
Views: 3376
Reputation: 754190
You can't compare strings like this:
if (optarg == "insertion") algorithm = 0;
You need to use strcmp()
or equivalent, like this:
if (strcmp(optarg, "insertion") == 0) algorithm = 0;
There may be other problems, but that springs to mind immediately.
Tinkering with optarg
doing optarg++
is probably not a good idea. That is information from the function to you; it is dodgy changing it. You could take a copy of the pointer and then increment that, stepping through the string it points at. There is certainly no guarantee that there will be a space in the argument for -k
, and that is likely the source of your trouble, along with the misuse of character pointer comparisons instead of using strcmp()
or equivalent.
You seem to be missing a break
after case 'k':
.
The bool endOption
inside the body of the loop is odd: it get set to false
on each iteration; it is tested while it is still false
, so the break
is not executed; it is set to true
when getopt_long()
returns 0
; but the value is reset before the next iteration. You should probably declare this variable outside the main while ((c = getopt_long(...)) != -1)
loop. Then it will behave sensibly (though you should probably terminate the loop if it is set before calling getopt_long()
again - so maybe the condition on it should be at the bottom of the main while
loop.
Changing the loop test in -k
handling to while (strcmp(optarg, "") != 0)
(the key difference is a missing space between the two double quotes), and then I get sane behaviour out of it. Notice how I've instrumented the options so that I can see what is being executed. When I ran with the comparison to a string containing a space, I got a fancy dump of my environment before the loop terminated. That's the sort of thing that leads to core dumps.
#include <getopt.h>
#include <vector>
#include <iostream>
#include <cstdlib>
using namespace std;
static struct option long_options[] =
{
{"algorithm", required_argument, 0, 'a'},
{"reverse", no_argument, 0, 'r'},
{"key", required_argument, 0, 'k'},
{"output", required_argument, 0, 'o'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0}
};
int main(int argc, char **argv)
{
vector<int> sortOrder;
int option_index = 0;
int c;
bool reverseFlag = false;
int algorithm = 1;
bool fileFlag = false;
//Getopt to get the correct options from the command line.
while ((c = getopt_long(argc, argv, "a:rk:o:hV", long_options, &option_index)) != -1)
{
bool endOption = false;
if (endOption) break;
switch (c)
{
case 0:
cerr << "Found 0 value\n";
endOption = true;
break;
case 'a':
cerr << "Found -a option: " << optarg << endl;
if (strcmp(optarg, "insertion") == 0)
algorithm = 0;
break;
case 'r':
cerr << "Found -r option\n";
reverseFlag = true;
break;
case 'k':
cerr << "Found -k option: " << optarg << endl;
while (strcmp(optarg, "") != 0)
{
if (strcmp(optarg, ",") == 0)
optarg++;
else
{
cerr << "pushback <<" << optarg << ">>\n";
sortOrder.push_back(atoi(optarg)); //error here
optarg++;
}
}
break;
case 'o':
cerr << "Found -o option: " << optarg << endl;
fileFlag = true;
break;
case 'h':
case 'V':
default:
cerr << "You have entered an incorrect flag, do it better" << endl;
break;
}
}
}
When that's run as:
./getopt -k 2,1
I got the output:
Found -k option: 2,1
pushback <<2,1>>
pushback <<,1>>
pushback <<1>>
It might be that you want to change the comparison from:
if (strcmp(optarg, ",") == 0)
to:
if (*optarg == ',')
You might even reasonably change the loop condition to:
while (*optarg != '\0')
thus avoid strcmp()
altogether. Incidentally, I'm not sure which header pulled in <cstring>
, but one of them did.
For the record, I'm testing on a Mac Mini running MacOS X 10.7.2 (Lion) and using the provide G++ compiler, i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)
.
Upvotes: 2