Вопрос или проблема
Я пытаюсь реализовать обработку опций, похожую на FFmpeg. В частности, я хочу поддерживать два типа опций палитры:
-
Прямое указание палитры:
-p "255,0,0 0,255,0"
-
Палитра из конфигурационного файла:
-p:c blackwhite
Подобно тому, как FFmpeg обрабатывает опции кодека:
ffmpeg -i input.mp4 -c:v libx264 -c:a copy output.mp4
В настоящее время мой код использует getopt:
static struct option long_options[] = {
{"palette", required_argument, 0, 'p'},
// другие опции...
};
int main(int argc, char** argv) {
while ((c = getopt_long(argc, argv, "p:h", long_options, &option_index)) != -1) {
switch (c) {
case 'p':
if (optarg[0] == 'c' && optarg[1] == ':') {
// Это не работает так, как задумано - optarg становится ":c"
load_palette_from_config(optarg + 2);
} else {
parse_numeric_palette(optarg);
}
break;
}
}
}
Проблема в том, что при использовании -p:c blackwhite
getopt воспринимает :c
как аргумент к -p
, что приводит к сбою загрузки палитры. Есть ли способ добиться подобной обработки опций, как в FFmpeg, используя getopt?
Ответ или решение
Для реализации обработки опций, аналогичной FFmpeg с использованием getopt
, мы можем немного изменить подход к обработке опции -p
. Когда мы используем -p:c filename
, getopt
воспринимает -p:c
как одно целое, и это может привести к непониманию, так как опция должна содержать аргумент после символа :
.
Для достижения подобного поведения, как в FFmpeg, можно воспользоваться простым обходным путем, рассчитывая длину optarg
и корректно обрабатывая его. Ниже представлен пример реализации с нужной обработкой:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
void load_palette_from_config(const char *config_name) {
printf("Загрузка палитры из конфигурации: %s\n", config_name);
// Здесь вам нужно добавить код для обработки конфигурации.
}
void parse_numeric_palette(const char *palette) {
printf("Обработка прямой палитры: %s\n", palette);
// Здесь вам нужно добавить код для обработки числовой палитры.
}
static struct option long_options[] = {
{"palette", required_argument, 0, 'p'},
{0, 0, 0, 0}
};
int main(int argc, char** argv) {
int c;
int option_index = 0;
while ((c = getopt_long(argc, argv, "p:h", long_options, &option_index)) != -1) {
switch (c) {
case 'p':
// Если аргумент начинается с 'c:' и имеет длину больше 2
if (strncmp(optarg, "c:", 2) == 0 && strlen(optarg) > 2) {
load_palette_from_config(optarg + 2); // Пропускаем 'c:'
} else {
parse_numeric_palette(optarg); // Обработка обычной палитры
}
break;
case 'h':
// Вывод справки
printf("Используйте: %s -p \"255,0,0 0,255,0\" или -p:c <имя_конфигурации>\n", argv[0]);
break;
default:
fprintf(stderr, "Используйте -h для справки.\n");
return EXIT_FAILURE;
}
}
// Обработка иных аргументов...
return EXIT_SUCCESS;
}
Объяснение приведенного кода:
-
Аргументы опции:
- При помощи
getopt_long
мы обрабатываем опцию-p
с необходимыми аргументами.
- При помощи
-
Проверка аргумента:
- Мы используем
strncmp
для проверки, начинается ли аргумент с'c:'
. Если это так, то передаем управляющую строку в функциюload_palette_from_config
, игнорируя первые два символа (так как они идентифицируют тип опции). - В противном случае вызываем
parse_numeric_palette
для обработки числовой палитры.
- Мы используем
-
Пользовательский интерфейс:
- В случае вызова
-h
выводится краткая справка о доступных аргументах.
- В случае вызова
Эта структура позволяет гибко обрабатывать как прямую спецификацию палитры, так и конфигурацию из файла, аналогично тому, как это реализовано в FFmpeg. Таким образом, ваше приложение будет более устойчивым и отзывчивым к вводимым пользователем данным.