варианты использования Getopt в C - PullRequest
1 голос
/ 08 декабря 2011

Я хочу поставить подопцию в строку, чтобы я мог использовать ее в качестве имени файла для чтения файла:

char *nvalue = NULL;
char *dvalue = NULL;
char *input = NULL;
char inputfilename[] = "\"";
int ar;

int main(int argc, char *argv[])
{
   while ((ar = getopt(argc, argv, "hn:d:i:")) != -1)
      switch (ar)
      {
         case 'h':
            printf("something");
            break; /* added */
         case 'n':
            nvalue = optarg;
            if (isdigit(nvalue))
               stop = atoi(nvalue);
            else
               printf("something\n");
            break; /* added */
         case 'd':
            dvalue = optarg;
            if (!strcmp(dvalue, "FCFS")   || !strcmp(dvalue, "SSTF") ||
                !strcmp(dvalue, "C-SCAN") || !strcmp(dvalue, "LOOK"))
               ;
            else
               printf("Invalid type of disk scheduling policy entered.\n");
            break; /* added */
         case 'i':
            input = optarg;
            strcpy(inputfilename, optarg);
            printf("Filename :%s\n", inputfilename);
            break;
      }
   /* ... */
}

Так что в командной строке, если я введу:

./foobar -i hello

тогда я смогу прочитать файл с:

FILE *file = fopen(inputfilename, "r" );

какие-нибудь предложения?ответы?спасибо!

1 Ответ

2 голосов
/ 08 декабря 2011

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

char *nvalue = NULL;
char *dvalue = NULL;
char *input = NULL;
char inputfilename[] = "\"";

Это выделило массив из двух байтов как inputfilename. Ненавижу думать о том, что произойдет, когда вы его используете.

int ar;

Есть все причины, по которым эта переменная должна быть локальной для главной функции, и нет видимой причины, по которой она будет глобальной. Если у вас нет заголовка, объявляющего их, другие переменные также должны иметь значение static - при условии, что вам нужно получить доступ к их значениям за пределами main() без удобного способа передать их как локальные. По возможности избегайте глобальных переменных.

int main(int argc, char *argv[])
{
    while ((ar = getopt(argc, argv, "hn:d:i:")) != -1)
    {
        switch (ar)
        {
        case 'h':
            printf("something");

К сожалению, нет break, поэтому код переходит на код case 'n':. С не Паскаль.

        case 'n':
            nvalue = optarg;
            if (isdigit(nvalue))
                stop = atoi(nvalue);

Вы не показали объявление для stop. Если вам действительно не нужна строка, вы можете обойтись без nvalue, избегая глобальной переменной, что всегда желательно.

            else
                printf("something\n");

Еще один пропал без вести break; Я не собираюсь указывать на это снова.

        case 'd':
            dvalue = optarg;
            if (strcmp(dvalue, "FCFS")   == 0 ||
                strcmp(dvalue, "SSTF")   == 0 ||
                strcmp(dvalue, "C-SCAN") == 0 ||
                strcmp(dvalue, "LOOK"    == 0)
            {

Я бы предложил такой комментарий, как /* Nothing - dvalue is OK */. Или инвертируя условие, используя теорему Де Моргана:

            if (strcmp(dvalue, "FCFS")   != 0 &&
                strcmp(dvalue, "SSTF")   != 0 &&
                strcmp(dvalue, "C-SCAN") != 0 &&
                strcmp(dvalue, "LOOK"    != 0)

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

            }
            else
                printf("Invalid type of disk scheduling policy entered.\n");

Было бы вежливо предоставить список допустимых значений - что внезапно становится еще одной причиной наличия массива допустимых значений, которые можно использовать для создания списка. Очень часто об ошибках следует сообщать stderr (используя fprintf()), а не stdout.

        case 'i':
            input = optarg;

Этого назначения достаточно.

            strcpy(inputfilename, optarg);

Если пользователь не вводит односимвольное имя файла, вы просто переполнили массив inputfilename. Вам действительно не нужно было делать копию аргумента, если вы не собираетесь изменять имя (например, чтобы добавить или изменить расширение имени).

             //strcat(inputfilename,"\"");   
             printf("Filename :%s\n", inputfilename);
        }

Вы не включили предложение default. Поскольку ar будет присвоено значение ?, когда предоставленная пользователем опция не будет распознана, обычно это ваша подсказка, чтобы предоставить простое сообщение об использовании и выйти.

...