LINUX.ORG.RU

Подскажите С-нубасу как банально распарсить строку в массив.

 ,


1

6

Приветствую. Казалось бы, тривиальная в 2023 году вещь - распарсить строку по делимитеру и загнать это в массив. Но нет, просто не будет.

Впрочем вопрос не в этом. Есть код. Описания переменных и прочая, я опущу, перейду сразу к сути.

Алгоритм ну вроде как прост, работает и на питоне, и на пыхе, а вот на С делает какую-то срань, хотя скорее всего я банально не до конца понимаю нюансов С, в связи с чем и прошу помощи.

printf("\n============ Parsing: ");printf(gtk_path);printf(" ========\n");
fg_color = "#888888";
bg_color = "#AAAAAA";

filePointer = fopen(gtk_path, "r");

while(fgets(buffer, bufferLength, filePointer)) {

 if (strstr(buffer, " fg_color ") != NULL)  {
  printf("\nFound fg_color entry: ");
  char **arr = split(buffer, ' ');
  fg_color = trim(arr[2]);
  printf(fg_color); // <<<<
 }

 if (strstr(buffer, " bg_color ") != NULL)  {
  printf("\nFound bg_color entry: ");
  char **arr = split(buffer, ' ');
  bg_color = trim(arr[2]);
  printf(bg_color); // <<<<
 }

}

fclose(filePointer);
printf("\n *** \n");printf("Main color: ");printf(fg_color);printf("BG color: ");printf(bg_color);printf("\n");


// Для информации приведу функции split и trim, хотя дело вряд ли в них.

char **split(char *str, char delim) {
  char **arr = malloc(sizeof(char *) * (strlen(str) + 1));
  int i = 0;
  for (char *p = strtok(str, &delim); p; p = strtok(NULL, &delim)) {
    arr[i++] = p;
  }
  return arr;
}

char *trim(char *s) {
    char *ptr;
    if (!s)
        return NULL;   // handle NULL string
    if (!*s)
        return s;      // handle empty string
    for (ptr = s + strlen(s) - 1; (ptr >= s) && isspace(*ptr); --ptr);
    ptr[1] = '\0';
    return s;
}

Задача блока - прочитать CSS-файл, и выдрать с него полторы строчки в массив.

Сначала присваиваем двум переменным какое-то значение, например #888888 и #AAAAAA;

Читаем построчно файл, ищем в каждой строке нахождение подстроки, если подстрока найдена, тогда парсим ее в массив, и присваиваем нашей главной переменной значение массива с определенным индексом, и ГЛАВНОЕ - тут же выводим эту переменную на экран.

После того, как файл пройден до конца - выводим результирующее значение тех же переменных.

А вот что оно выводит:

============ Parsing: /usr/share/themes/Relax-Light-GTK/gtk-3.0/gtk.css ========

 *** 
Main color: #888888BG color: #AAAAAA

============ Parsing: /usr/share/themes/White - OE2-GTK/gtk-3.0/gtk.css ========

Found fg_color entry: #5C616C;
Found bg_color entry: #FAFAFA;
 *** 
Main color:  #000000;
BG color:  #000000;


Вопрос: откуда нах взялся этот #000000 ?

Когда подстрока не встречается в строке (т.е. файл не содержит ни fg_color ни bg_color) - возвращаются правильные значения того что я установил. Этот кусок работает правильно.

Да, возможно парсер работает криво, но ведь каждое присваивание fg_color = сопровождается printf'ом, и в пределах if'а с парсером видно, что парсер отрабатывает на отлично. #000000 - явно взято откуда-то из файла, но как оно могло пробраться в переменную, и не засветиться в выводе этой переменной ? ЧЯДНТ ?

★★★★★
Ответ на: комментарий от qulinxao3

Cи позволяет обмазыватся своими реализациями строк

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

Работает - да.

Но выглядит уродски, нечитаемо, а кое где трудновыполнимо. Чото типа printf(strcat(malloc(str2,strlen(str1)),str1) вместо printf(str1.str2) - это банально мерзко.

windows10 ★★★★★
() автор топика
Ответ на: комментарий от windows10

Ещё раз, strcat - это не заменитель для s1+s2. И вообще на мой взгляд это устаревшая и плохая функция из 80-х которую лучше нигде не использовать. Правильно эта конструкция будет выглядеть так:

my_print(my_dynamic_strcat(str1,str2))

и при этом str1 и str2 будут не char const * а какого-то сложного структурного типа. Названия функций можно и покороче, выглядеть всё будет более-менее норм, хотя конечно не идеально. Вся сложность будет в реализации этих функций.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от windows10

следуют принимать во внимание:

Ken Thompson interviewed by Brian Kernighan at VCF East 2019 https://youtu.be/EY6q5dv_B-o

при подготовке Керниганом : UNIX: A History and a Memoir

в интерью Томсон расказал что Си вырос в процессе реализации интерпретирующего компилятора для бутстрапинга Фортрана на pdp11

так что ...

qulinxao3 ★☆
()