metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2012-04-22 06:05 pm

C, parse comma-separated line

Кошерен ли такой код для разбиения строки, разделенной запятыми на отдельные строки: http://ideone.com/rhNXq ?

PS: strtok не признаю по идеологическим причинам - она меняет анализируемую строку, что меня крайне пугает, хотя в моем конкретном случае это не мешает.

PPS: безотносительно к strtok, в функции было минимум две ошибки - отсутствие проверки на выход за пределы буфера и попадание eol в последнюю строку (девайсина, с которой приходит строка, терминирует ее \r)

[identity profile] blacklion.livejournal.com 2012-04-22 04:44 pm (UTC)(link)
А этот код разруливает? Вообще, приличного кода с полной поддержкой shell words я как-то не видел ни разу.

[identity profile] lionet.livejournal.com 2012-04-22 04:47 pm (UTC)(link)
А какая нафиг разница, это же не парсинг гигабайтного XML'я. Оптимизация на спичках. На такой основополагающей мелочи, как ковыряние строк, главное – производительность программиста, а не программы.

[identity profile] metaclass.livejournal.com 2012-04-22 04:51 pm (UTC)(link)
Написать нормальный парсер CSV с экранированием это та еще задача. Можно давать на собеседовании и издеваться.

[identity profile] smalgin.livejournal.com 2012-04-22 04:58 pm (UTC)(link)
Я в голове покрутил и там загорелась неонка. :)

int parse_answer(char **buffer_start, char *buffer_end, char **curr_ptr, size_t *curr_size)
{
if(*buffer_start >= buffer_end){
return 0;
}
*curr_ptr = *buffer_start;
while(**buffer_start != ','){
(*buffer_start)++;
}
Где проверка на конец буфера?

(*buffer_start)++;
One-off потому что запятая может быть и последним символом тоже. Вообще на каждом операторе, сдвигающем индекс влево или вправо, нужно неукоснительно проверять boundary conditions. Если сдвиг нетривиален, но инвариантен по отношению к граничным условиям, откомментируйте это в коде. Только так, только двойная итальянская бухгалтерия...

*curr_size=*buffer_start-*curr_ptr-1;

return 1;
}

Вроде так как-то. Код прототипический, так что я не думал заострять на этом внимание более чем в образовательных целях.

PS Я сам грешен, в недавнем коде JSON разбирал именно тупой итерацией по буферу и switch оператором... но уж сильно хотелось самому написать :)

[identity profile] avnik.livejournal.com 2012-04-22 05:13 pm (UTC)(link)
Хм, а там про mmap есть? ;)

[identity profile] blacklion.livejournal.com 2012-04-22 05:24 pm (UTC)(link)
Смотреть надо — понимает ли он заэскейпленные кавычки в кавычках и прочее.

[identity profile] blacklion.livejournal.com 2012-04-22 05:24 pm (UTC)(link)
Угу.

[identity profile] lionet.livejournal.com 2012-04-22 05:27 pm (UTC)(link)
Понимает. И прочее.

[identity profile] lionet.livejournal.com 2012-04-22 05:28 pm (UTC)(link)
На Эрланге примерно так:

extract_value([]) -> novalue;
extract_value([$\r,$\n|Rest]) -> {Rest};
extract_value([$\n|Rest]) -> {Rest};
extract_value([$"|Rest]) -> extract_quoted(Rest, []);
extract_value(Rest) -> extract_nonquoted(Rest, []).

extract_nonquoted([$\n|_]=Rest, V) -> {V, Rest};
extract_nonquoted([$\r,$\n|_]=Rest, V) -> {V, Rest};
extract_nonquoted([$,|Rest], V) -> {V, Rest};
extract_nonquoted([C|Rest], V) -> extract_nonquoted(Rest, [C|V]);
extract_nonquoted([], V) -> {V, []}.

extract_quoted([$",$,|Rest], V) -> {V, Rest};
extract_quoted([$",$\r,$\n|Rest], V) -> {V, [$\n|Rest]};
extract_quoted([$",$\n|Rest], V) -> {V, [$\n|Rest]};
extract_quoted([$",$"|Rest], V) -> extract_quoted(Rest, [$"|V]);
extract_quoted([$"], V) -> {V, []};
extract_quoted([$\r,$\n|Rest], V) -> extract_quoted(Rest, [$\n|V]);
extract_quoted([C|Rest], V) -> extract_quoted(Rest, [C|V]);
extract_quoted([], V) -> {V, []}.

[identity profile] smalgin.livejournal.com 2012-04-22 05:31 pm (UTC)(link)
Не суть, это ж прототип. Я просто пытаюсь донести мысль, что это одна мелочь, которую вы поймали. Еще будет 999.

Как насчет поддержки UTF-16? :)

[identity profile] blackyblack.livejournal.com 2012-04-22 05:38 pm (UTC)(link)
1. В коде косяки - работать не будет.
2. В идеале стоило бы разбить код на две функции: поиск символа в строке и разбиение строки по номеру символа.
3. \r в результате за ошибку не считаем. Откуда нам знать, что она тебе не нужна :)

В итоге, ждём исправленную версию.

[identity profile] metaclass.livejournal.com 2012-04-22 05:46 pm (UTC)(link)
Железо строго ASCII и по некоторым политическим причинам никогда в жизни не будет поддерживать что-то кроме этого :)

[identity profile] metaclass.livejournal.com 2012-04-22 05:47 pm (UTC)(link)
Проблема в том, что работало. Пока я не стал использовать ее вывод для дальнейшего парсинга, и то при этом в первую очередь сломалось на \r в последней строке.

А зачем разбивать на две строки, по моему так понятнее?

[identity profile] blackyblack.livejournal.com 2012-04-22 05:52 pm (UTC)(link)
Ну логика такая. Чтобы разбить строку, разделенную на части запятыми, нужно найти запятую и разбить строку. :)
Edited 2012-04-22 17:52 (UTC)

[identity profile] smalgin.livejournal.com 2012-04-22 05:58 pm (UTC)(link)
Ну, значит, UTF8 :)

Ладно, я гоню уже. Вредно работать по выходным.

[identity profile] metaclass.livejournal.com 2012-04-22 05:58 pm (UTC)(link)
Так мне строки по отдельности не нужны, достаточно указатель на них и размер.

[identity profile] artureg.livejournal.com 2012-04-22 06:10 pm (UTC)(link)
обоснуй

[identity profile] artureg.livejournal.com 2012-04-22 06:11 pm (UTC)(link)
массив, лист, вектор, список сам придумай ещё вариантов

[identity profile] artureg.livejournal.com 2012-04-22 06:16 pm (UTC)(link)
я думаю юра имел ввиду то, что если нету такого понятия как строка, то соотвественно нет сплита для неё

[identity profile] artureg.livejournal.com 2012-04-22 06:17 pm (UTC)(link)
зачем ты изобрёл велосипед и закатил солнце вручную?

[identity profile] metaclass.livejournal.com 2012-04-22 06:22 pm (UTC)(link)
Ты видел либы, на которые мне ссылки дают?
Я их изучать, собирать и ставить буду дольше, чем свою прогу писать :)
Кроме того, я и чужой код с со своими багами вызову, сложно что ле:)

[identity profile] artureg.livejournal.com 2012-04-22 06:23 pm (UTC)(link)
зачем ты используешь язык, в котором на любой примитивный чих надо строить свой велосипед?

[identity profile] metaclass.livejournal.com 2012-04-22 06:31 pm (UTC)(link)
Его не нужно строить. Но я не знаю, как правильно, поэтому и использую, чтобы разобраться.

[identity profile] artureg.livejournal.com 2012-04-22 06:33 pm (UTC)(link)
правильно, не нужно, но зачем ты построил? если заморачиваться на подобных примитивных задачах, время разработки вырастет до бесконечности

Page 2 of 5