оператор switch и функция getopt () в C - PullRequest
0 голосов
/ 26 ноября 2010

Я пытаюсь разобрать аргументы в командной строке, используя switch и getopt().Структура очень проста: у меня есть файлы makefile, .c и .h.Это первый раз, когда я использую переключатель, поэтому я могу сделать несколько основных ошибок.Я использовал эту ссылку в качестве руководства для переключения текста ссылки и текста ссылки Если вы видите какие-либо основные ошибки, пожалуйста, сообщите мне.

makefile:

make:lunar

lunar: lunar.o
    gcc -Wall -std=c99 -g -o lunar lunar.o -lm
lunar.o: lunar.c lunar.h
    gcc -Wall -std=c99 -g -c lunar.c

clean:
    -rm -f *.o lunar core

/////////////////////////////////////

лунный.c

int main (int argc,  char *argv[]){
    int i;
    int c = 0;
    int gravity = 0;
    int thrust = 0;
    opterr = 0;
    while ((c = getopt (argc, argv, "gtf:")) != -1)
        switch (c){
            case 'g':
                gravity = argv[optind];
                break;
            case 't':
                thrust = argv[optind];
                break;
            case 'f':
                argument = argv[optind];
                break;
            case '?':
                if (optopt == 'c')
                    fprintf(stderr, "Option -%c requires 
                            an argument.\n", optopt);
                else if (isprint (optopt))
                    fprintf (stderr, "Unknown option 
                             `-%c'.\n", optopt);
                else
                    fprintf (stderr, "Unknown option 
                             character `\\x%x'.\n", 
                             optopt);
                return 1;
            defult:
                abort ();
        }
    printf ("gravity is %d and thrust is %d.\n", 
            gravity, thrust);
    for (int index = optind ; index < argc ; index++ ){
        printf ("Non-option argument %s\n", argv[index]);
        return 0;
    }
}

/////////////////////////////////////

lunar.h

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <assert.h>

#define MAX_WORD 256

1 Ответ

4 голосов
/ 26 ноября 2010

Не забывайте, что в 'default' есть 'a' - вы просто пометили этот код с помощью (неиспользуемой) метки defult, а не дали переключателю регистр по умолчанию.

Непонятно, почему вы думаете, optopt может быть 'c' или к нему следует обращаться особенно, когда это 'c'; это может быть похмелье из более раннего издания.

Вы обрабатываете опции 'g' и 't', как будто они принимают аргументы, но при вызове getopt() двоеточия после них не отображаются. Если нужно верить переключателю, вам нужно, чтобы аргумент был "g:t:f:".

Кроме того, вы должны использовать char * с именем optarg вместо того, чтобы пытаться использовать argv[optind]. Вы используете optind после завершения цикла для обработки дополнительных ('имя файла') аргументов.

Кроме того, поскольку gravity и thrust являются целыми числами, вам необходимо преобразовать строки в целые числа. Самый простой способ (в значительной степени игнорируя возможные ошибки) с помощью:

gravity = atoi(optarg);

Если вы хотите выполнить обработку ошибок, вызовите функцию для проверки и создания отчетов об ошибках.

Я рекомендую ставить скобки вокруг оператора switch или вокруг тела оператора while:

while ((c = getopt(argc, argv, "g:f:t:")) != -1)
{
    switch (c)
    {
    ...
    }
}

Это не является строго необходимым, но (IMNSHO) легче читать код с помощью дополнительных фигурных скобок. Для однострочного оператора у меня не было бы проблем; но для такого сложного утверждения, как переключатель, я рекомендую дополнительные скобки.

'return 0;' должно быть вне цикла for. В данный момент цикл останавливается на первом неопциональном аргументе.


Makefile в основном в порядке. В конце концов, вы будете использовать больше макросов и больше флагов предупреждения компиляции, но единственные проблемы, которые я обнаружил, что компилятор также обнаружит, это опечатка в случае по умолчанию и отсутствие преобразования строк в целые числа.

PROGRAM = lunar
SOURCE  = lunar.c
HEADER  = ${SOURCE:.c=.h}
OBJECT  = ${SOURCE:.c=.o}
CFLAGS  = -std=c99 -Wall -g
LDFLAGS =
LDLIBS  = -lm

all: ${PROGRAM}

${PROGRAM}: ${OBJECT}
    ${CC} ${CFLAGS} -o $@ ${OBJECT} ${LDFLAGS} ${LDLIBS}

${OBJECT}: ${SOURCE} ${HEADER}
    ${CC} ${CFLAGS} -c ${SOURCE}

clean:
    -rm -f *.o ${PROGRAM} core
...