optarg установлен в ноль - PullRequest
       15

optarg установлен в ноль

1 голос
/ 13 февраля 2012

Я пытаюсь использовать atoi на optarg, но это может быть что угодно. Я пытался выяснить, почему мой getopt_long не работает. Когда я вхожу в мой оператор switch, для optarg устанавливается значение null, и оно остается таким же. Я проверил свои двоеточия, и они правильные. Это мой код.

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;
        }
    }
}

// больше вещей //

Я пытался использовать двойные двоеточия и почти все остальное.

1 Ответ

2 голосов
/ 13 февраля 2012

Нельзя сравнивать строки, подобные этой:

 if (optarg == "insertion") algorithm = 0;

Вам нужно использовать strcmp() или эквивалентный, например:

if (strcmp(optarg, "insertion") == 0) algorithm = 0;

Могут быть и другие проблемы, но это сразу приходит на ум.


Работа с optarg выполнением optarg++, вероятно, не очень хорошая идея. Это информация из функции для вас; это глупо менять его. Вы можете взять копию указателя, а затем увеличить его, шагая по строке, на которую он указывает. Конечно, нет никакой гарантии, что в аргументе для -k будет пробел, и это, вероятно, является источником вашей проблемы, наряду с неправильным использованием сравнения указателей символов вместо использования strcmp() или эквивалентного.

Вы, похоже, пропускаете break после case 'k':.

* * * * * bool endOption внутри тела цикла нечетно: оно устанавливается равным false на каждой итерации; оно проверяется, пока оно еще false, поэтому break не выполняется; устанавливается true, когда getopt_long() возвращает 0; но значение сбрасывается до следующей итерации. Возможно, вам следует объявить эту переменную вне основного цикла while ((c = getopt_long(...)) != -1). Тогда он будет вести себя разумно (хотя вам, вероятно, следует прекратить цикл, если он установлен перед повторным вызовом getopt_long(), поэтому, возможно, условие для него должно быть в нижней части основного цикла while.


Изменение проверки цикла при обработке -k на while (strcmp(optarg, "") != 0) (ключевое отличие - пропущенный пробел между двумя двойными кавычками), и затем я получаю вменяемое поведение. Обратите внимание на то, как я описал параметры, чтобы видеть, что выполняется. Когда я запустил сравнение со строкой, содержащей пробел, я получил необычный дамп своего окружения до того, как цикл завершился. Именно такие вещи приводят к дампам ядра.

#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;
        }
    }
}

Когда он запускается как:

./getopt -k 2,1

Я получил вывод:

Found -k option: 2,1
pushback <<2,1>>
pushback <<,1>>
pushback <<1>>

Возможно, вы захотите изменить сравнение с:

if (strcmp(optarg, ",") == 0)

до:

if (*optarg == ',')

Вы можете даже разумно изменить условие цикла на:

while (*optarg != '\0')

Таким образом, избегайте strcmp() в целом. Кстати, я не уверен, какой заголовок вытащил в <cstring>, но один из них сделал.


Для справки, я тестирую на Mac Mini с MacOS X 10.7.2 (Lion) и использую компилятор G ++, i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00).

...