Как вы получаете значения флагов в getopt, я пробовал использовать его в googling, но все, что у меня есть, это о том, как переключать случаи и устанавливать флаги. Я получил код ниже и то, что я пытаюсь сделать, это иметь три флага: -a, -b, -c, но передаются только два флага, например ./filename -a somevalue -c anothervalue
или ./filename -b somevalue -c anothervalue
любая помощь?
int main(int argc, char *argv[])
{
int flagA = 0;
int flagB = 0;
while (1) {
char c;
c = getopt (argc, argv, "abc:");
if (c == -1) {
break;
}
switch (c) {
case 'a':
flagA = 1;
//cout<<optarg<<endl; //I tried printing the value but it only prints the second flag value
break;
case 'b':
flagB = 1;
cout<<optarg<<endl;
break;
case 'c':
cout<<optarg<<endl;
break;
case '?':
default:
cout<<"Usage: %s [-a] [-b <something>].\n", argv[0]<<endl;
}
if(flagA > 0){
//do something using the values of flagA and flagC
}
else if(flagB > 0){
//do something using the values of flagB and flagC
}
}
return 0;
}
Если вы намерены использовать optarg
с флагом, флаг должен иметь :
после него в строке опций.
c = getopt(argc, argv, "a:b:c:");
Вывод вывода использования не должен компилироваться для вас. Кроме того, вы пытаетесь смешивать спецификаторы формата стиля C в выходной поток C++, что неверно.
cout << "Usage: " << argv[0] << " [-a] [-b <something>].\n";
Существует несколько проблем с кодом, но ключевой заключается в вызове getopt()
. У вас есть строка управления опцией "abc:"
, что означает, что ни -a
ни -b
имеют опции.
Предполагая, что вы используете стандартную версию POSIX getopt()
а не GNU getopt()
, тогда при запуске:
./filename -a somevalue -c anothervalue
./filename -b somevalue -c anothervalue
somevalue
после первого флага означает, что параметры завершены, а остальные аргументы являются аргументами без опций. GNU getopt()
, в отсутствие переменной POSIXLY_CORRECT
-c anothervalue
список аргументов, чтобы еще -c anothervalue
распознано (и аргументы переставляются таким образом, что somevalue
заканчивается в конце).
Ваш код будет лучше написан:
#define _XOPEN_SOURCE 600
#include <iostream>
#include <unistd.h>
using namespace std;
int main(int argc, char *argv[])
{
int flagA = 0;
int flagB = 0;
int opt;
char *c_opt = 0;
while ((opt = getopt(argc, argv, "abc:")) != -1)
{
switch (opt)
{
case 'a':
flagA = 1;
cout << "A: " << flagA << "\n";
break;
case 'b':
flagB = 1;
cout << "B: " << flagB << "\n";
break;
case 'c':
c_opt = optarg;
cout << "C: " << c_opt << "\n";
break;
default:
cerr << "Usage: " << argv[0] << " [-a] [-b] [-c <something>]\n";
return -1;
}
}
if (flagA)
{
// do something using the values of flagA and c_opt (if set)
}
else if (flagB)
{
// do something using the values of flagB and c_opt (if set)
}
else if (c_opt)
{
// do something using just c_opt (neither flagA nor flagB is set)
}
else
{
// do something if no options are specified (report error?)
}
for (int i = optind; i < argc; i++)
cout << "File: " << i << ": " << argv[i] << "\n";
return 0;
}
Код выше (с поправками) компилируется с GCC 4.9.1 в Mac OS X 10.10 (Yosemite):
g++ -O3 -g -std=c++11 -Wall -Wextra -Werror opt.cpp -o opt
BSD-ish getopt()
рядом с стандартом POSIX, поэтому я получаю:
$ ./opt -a 5 -c something
A: 1
File: 2: 5
File: 3: -c
File: 4: something
$
Я хочу, чтобы
-a
и-b
принимали аргумент. То, что я пытаюсь сделать, состоит в том, что у меня есть две функции, которые принимают два аргумента, поэтому, если установлен-a
, я хотел бы вызвать функциюa
else, если-b
затем вызывает функциюb
. Мне нужны два значения для вызова функций.
Учитывая это разъяснение, код может выглядеть так:
#define _XOPEN_SOURCE 600
#include <cstdlib>
#include <iostream>
#include <unistd.h>
using namespace std;
static void usage(const char *arg0)
{
cerr << "Usage: " << arg0 << " [-a filename | -b filename] -c <something>\n";
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{
char *a_opt = 0;
char *b_opt = 0;
char *c_opt = 0;
int opt;
while ((opt = getopt(argc, argv, "a:b:c:")) != -1)
{
switch (opt)
{
case 'a':
a_opt = optarg;
cout << "A: " << a_opt << "\n";
break;
case 'b':
b_opt = optarg;
cout << "B: " << b_opt << "\n";
break;
case 'c':
c_opt = optarg;
cout << "C: " << c_opt << "\n";
break;
default:
cerr << "Unknown option: " << optopt << "\n";
usage(argv[0]);
break;
}
}
if (optind != argc || c_opt == 0 || (a_opt && b_opt) || (a_opt == 0 && b_opt == 0))
usage(argv[0]);
else if (a_opt)
cout << "A&C: " << a_opt << " " << c_opt << "\n";
else
cout << "B&C: " << b_opt << " " << c_opt << "\n";
return 0;
}
Пример прогона:
$ ./opt -a option -c something
A: option
C: something
A&C: option something
$
./filename -a 5 -c "sometext"
я получаю Usage: ./project [-a] [-b] [-c <something>]
cout<<optarg<<endl;
это все, что я делаю так же, как у меня в коде.