Разбор параметров
Обрабатывайте флаги
«Разбор параметров» — бесплатный урок 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 — локальная установка не требуется.
Все уроки этого курса
- argc и argv
- Разбор параметров
- getopt
- Создание инструмента CLI