#c #parsing #ini
#c #синтаксический анализ #ini
Вопрос:
В своем коде я использую iniparser (https://github.com/ndevilla/iniparser ) для синтаксического анализа double, int и строк. Однако меня интересует синтаксический анализ массивов, разделенных запятой, таких как
arr = val1, val2, ..., valn
Любой простой и быстрый способ, как описанный выше синтаксический анализатор?
Комментарии:
1. Просто проанализируйте их как double, int, strings и т.д. И добавьте их в массив.
2. C на самом деле не имеет массивов общего назначения, поэтому вам нужно будет изобрести свою собственную структуру, чтобы представить их в осмысленной форме.
3. @tadman Он не спрашивает о том, чтобы поместить разные типы в один и тот же массив.
4. @Fredrik — OP может спрашивать о размещении разных типов в одном массиве. Неясно (по крайней мере, для меня), какие типы
val1
и т.д. Существуют. Они могут быть одного типа, а могут и нет. В любом случае, вероятно, потребуется создать какую-то структуру данных для представления массива переменной длины, какие бы типы он ни содержал, поскольку C на самом деле не имеет встроенной поддержки для этого.5. @Fredrik Дело не в типах, а в том, что в C массивы не имеют компонента integral size. Невозможно сказать «некоторое произвольное количество
int
значений» на C без пользовательской структуры.
Ответ №1:
Лучший способ — создать свою собственную структуру. Вы можете легко найти в веб-структурах, которые вы можете импортировать для своего кода. Другое решение, не такое замечательное, — поместить ваши значения в виде указателей void. И когда вы хотите вернуть свои значения обратно, вы берете указатель void и присваиваете ему значение того типа, которое вы хотите (int, double, char и т. Д.). Но это может привести к конфликту значений, поэтому вы должны быть осторожны. Вы должны знать, какое значение вида находится в какой ячейке указателя. Это не идеальный способ, но это обманчивый способ избежать создания собственной структуры.
Комментарии:
1. Он не спрашивает о размещении разных типов в одном массиве.
2. Хотя в нем не хватает некоторых деталей, в целом это правильный ответ. Если вы хотите смоделировать сложную структуру данных (и она не обязательно должна быть очень сложной) на C, вам нужно написать или получить некоторый код для этого. OP уже нашел что-то для обработки базового синтаксического анализа, но это недостаточно умно для новой работы. Итак, выбор сводится к (1) расширению, (2) написанию нового или (3) поиску лучшего.
Ответ №2:
Вы можете использовать libconfini, который поддерживает массивы.
test.conf:
arr = val1, val2, ..., valn
test.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <confini.h>
struct my_conf_T {
size_t arrlen;
char ** arr;
};
static int my_listnr (IniDispatch * this, void * v_conf) {
#define conf ((struct my_conf_T *) v_conf)
if (ini_string_match_si("arr", this->data, this->format)) {
conf->arrlen = ini_array_get_length(this->value, INI_COMMA, this->format);
if (!conf->arrlen || !this->v_len) {
/* Array is empty */
return 0;
}
conf->arr = (char **) malloc(conf->arrlen * sizeof(char *) this->v_len 1);
if (!conf->arr) {
fprintf(stderr, "malloc() failedn");
exit(1);
}
char * remnant = (char *) ((char **) conf->arr conf->arrlen);
memcpy(remnant, this->value, this->v_len 1);
for (size_t idx = 0; idx < conf->arrlen; idx ) {
conf->arr[idx] = ini_array_release(amp;remnant, INI_COMMA, this->format);
ini_string_parse(conf->arr[idx], this->format);
}
}
return 0;
#undef conf
}
int main () {
struct my_conf_T my_conf = (struct my_conf_T) { 0 };
if (load_ini_path("test.conf", INI_DEFAULT_FORMAT, NULL, my_listnr, amp;my_conf)) {
fprintf(stderr, "Sorry, something went wrong :-(n");
return 1;
}
if (my_conf.arr) {
/* Do something with `my_conf.arr`... */
for (size_t idx = 0; idx < my_conf.arrlen; idx ) {
printf("arr[%zu] = %sn", idx, my_conf.arr[idx]);
}
free(my_conf.arr);
}
return 0;
}
Вывод:
arr[0] = val1
arr[1] = val2
arr[2] = ...
arr[3] = valn
P.S. Так получилось, что я автор.