0Pricing
C Academy · Урок

Разбор параметров

Обрабатывайте флаги

«Разбор параметров» — бесплатный урок C Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C Academy содержит 4 уроков всего.

Опции и позиционные аргументы

Аргументы командной строки бывают двух видов. Позиционные аргументы — это значения, например имена файлов. Опции (также называемые флагами) начинаются с дефиса, например -v или --help.

В этом уроке показано, как вручную обнаруживать флаги и обрабатывать их.

#include <stdio.h>

int main(int argc, char *argv[]) {
    for (int i = 1; i < argc; i++) {
        if (argv[i][0] == '-')
            printf("option: %s\n", argv[i]);
        else
            printf("value:  %s\n", argv[i]);
    }
    return 0;
}

Обнаружение флага

Чтобы проверить наличие определённого флага, сравнивайте каждый аргумент с помощью strcmp.

Здесь при обнаружении -v устанавливается логическое значение для подробного режима.

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    int verbose = 0;
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-v") == 0)
            verbose = 1;
    }
    printf("verbose = %d\n", verbose);
    return 0;
}

Поддержка длинных опций

Многие инструменты принимают как короткую форму (-h), так и длинную (--help).

Проверяйте оба варианта написания с помощью двух сравнений, объединённых оператором ||.

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-h") == 0 ||
            strcmp(argv[i], "--help") == 0) {
            printf("Usage: prog [options]\n");
            return 0;
        }
    }
    printf("No help requested\n");
    return 0;
}

Опции, принимающие значение

Некоторым флагам нужен аргумент, например -o output.txt. Когда встречается такой флаг, следующий элемент argv является его значением.

Увеличьте индекс цикла и проверьте, что Вы не вышли за конец.

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    const char *output = "default.txt";
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-o") == 0 && i + 1 < argc) {
            output = argv[++i];
        }
    }
    printf("Output file: %s\n", output);
    return 0;
}

Обработка отсутствующего значения

Если -o является последним аргументом, значения после него нет. Чтение argv[i+1] выйдет за границы массива.

Всегда проверяйте i + 1 < argc перед извлечением следующего токена и сообщайте об ошибке в противном случае.

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-n") == 0) {
            if (i + 1 >= argc) {
                printf("Error: -n needs a value\n");
                return 1;
            }
            printf("n = %s\n", argv[++i]);
        }
    }
    return 0;
}

Объединение логических флагов и значений

Реальный анализатор аргументов одновременно отслеживает несколько флагов: некоторые являются логическими, а другие принимают значения. Используйте отдельную переменную для каждого параметра.

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    int verbose = 0;
    const char *name = "world";
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-v") == 0) verbose = 1;
        else if (strcmp(argv[i], "-name") == 0 && i+1 < argc) name = argv[++i];
    }
    if (verbose) printf("verbose mode\n");
    printf("Hello, %s\n", name);
    return 0;
}

Распознавание конца опций

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

Это позволяет пользователям передавать имена файлов, начинающиеся с -.

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    int opts_done = 0;
    for (int i = 1; i < argc; i++) {
        if (!opts_done && strcmp(argv[i], "--") == 0) {
            opts_done = 1;
            continue;
        }
        printf("%s: %s\n", opts_done ? "value" : "token", argv[i]);
    }
    return 0;
}

Сбор позиционных аргументов

Часто требуется принимать флаги и список файлов. Пропускайте распознанные опции, а остальные сохраняйте как позиционные аргументы.

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    for (int i = 1; i < argc; i++) {
        if (argv[i][0] == '-') continue;
        printf("file: %s\n", argv[i]);
    }
    return 0;
}

Обработка неизвестных опций

Удобный инструмент сообщает о неизвестных флагах, а не молча игнорирует их. Сравнивайте аргументы с известными опциями и в противном случае выводите предупреждение.

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    for (int i = 1; i < argc; i++) {
        if (argv[i][0] != '-') continue;
        if (strcmp(argv[i], "-v") != 0)
            printf("Unknown option: %s\n", argv[i]);
    }
    return 0;
}

Преобразование значений опций

Значения опций передаются как строки. Преобразуйте числовые значения с помощью strtol: эта функция также сообщает об ошибках разбора через указатель на конец.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
    int count = 1;
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-c") == 0 && i+1 < argc)
            count = (int) strtol(argv[++i], NULL, 10);
    }
    printf("count = %d\n", count);
    return 0;
}

Зачем нужен настоящий анализатор

Ручной разбор работает, но становится запутанным при объединённых коротких флагах (-vf), синтаксисе с = (--name=foo) и правилах порядка.

Стандартная функция getopt, которую мы рассмотрим далее, берёт эти соглашения на себя.

#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("Parsed %d tokens manually\n", argc - 1);
    return 0;
}

Быстрая проверка

Проверьте, насколько хорошо Вы поняли типичные проблемы разбора опций.

Повторение

Вы научились вручную разбирать опции:

  • Флаги начинаются с -; сравнивайте их с помощью strcmp.
  • Поддерживайте короткие и длинные формы с помощью ||.
  • Опции, принимающие значение, используют следующий токен — проверяйте условие i + 1 < argc.
  • -- завершает разбор опций; сообщайте о неизвестных флагах; преобразуйте числовые значения с помощью strtol.

Часто задаваемые вопросы

Урок «Разбор параметров» бесплатный?

Да — полный текст урока «Разбор параметров» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C Academy, подпишись на CoddyKit PRO. Курс C Academy содержит 4 уроков всего.

Чему я научусь в уроке «Разбор параметров»?

Обрабатывайте флаги Ты практикуешь C Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C Academy?

Предыдущий опыт не требуется. C Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Разбор параметров»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C Academy?

Да. Каждый урок C Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. argc и argv
  2. Разбор параметров
  3. getopt
  4. Создание инструмента CLI
← Назад к C Academy