Синтаксический разбор csv строчек

Синтаксический разбор csv строчек

GNSS данные в формате CSV

CSV строки можно встретить в различных протоколах, например, в NMEA протоколе от навигационных приемников GNSS. Пример NMEA протокола:

$GNGGA,102030.000,5546.95900,N,03740.69200,E,1,08,2.0,142.0,M,0.0,M,,\*
$GNGLL,5546.95900,N,03740.69200,E,102030.000,A,A\*
$GNGSA,A,3,10,16,18,20,26,27,,,,,,,4.8,2.0,4.3,1\*
$GNGSA,A,3,19, , , , , ,,,,,,,4.8,2.0,4.3,4\*
$GNGSA,A,3,82, , , , , ,,,,,,,4.8,2.0,4.3,2\*
$GPGSV,3,1,12,07,08,343,,08,07,304,,10,28,195,42,13,20,054,,0\*
// другие строки протокола...

CSV в данном случае является простым форматом для передачи данных между устройствами.

URL как CSV строка

Любой URL, например этот, по сути, представляет собой строку CSV, где разделителем выступает символ /.

Прошивка и CSV

Компонент CSV позволяет в одной строке в консоли прошивки запускать несколько shell команд последовательно. Также прошивка может логировать данные в CSV формате на SD карту по SPI, что позволяет легко открыть файл на любом устройстве для анализа.

Функция CSV parser для микроконтроллера

Для работы с CSV строками на микроконтроллере предлагается функция с интерфейсом:

bool csv_parse_text(const char* const text, char separator, uint32_t index, char* const sub_str, uint32_t sub_str_size);

Где:

  • text: входная CSV строка
  • separator: разделитель столбцов
  • index: индекс столбца, который требуется извлечь
  • sub_str: выходной массив для подстроки
  • sub_str_size: размер выходного массива

Функция не изменяет исходную строку text и работает без динамического выделения памяти. Если возникает ошибка (например, выход за пределы памяти или неверный индекс), функция возвращает false.

Этот компонент CSV decoder подходит для выполнения на микроконтроллере и написан на языке C в соответствии со стандартом ISO26262-6.

Извлечение текста из CSV файлов: как написать парсер на языке программирования C

Для человека тут всё очевидно. Однако как заставить компьютерную программу выделять подстроки из CSV строчек?

Извлечение текста из CSV строчек

Можно сказать, что CSV это своеобразный текстовый протокол для упаковки переменных в пакет. Как это обычно и бывает в программировании все задачи решаются золотым шаблоном: конечным автоматом.

Фаза 1. Определить входы конечного автомата

Фаза 2. Определить состояния конечного автомата

  • Конечный автомат только проинициализирован
  • Накапливаем данные в ячейку

Фаза 3. Нарисовать граф переходов между состояниями

Взаимосвязь между состояниями и входными воздействиями показывает граф конечного автомата. Это простой планарный граф.

Граф переходов

Теперь у нас есть всё чтобы начать писать код.

Фаза 4. Написать программный код для парсера CSV строчек

У каждого программного компонента есть свои константы. Вот они для компонента CSV.

У каждого программного компонента есть свои специфические типы данных.

А это API программного компонента CSV. Тут основная функция это csv_parse_text()

  • Инициализация конечного автомата разбора CSV
  • Всю работу делает функция csv_parse_text()
  • Собственно, сами шестерни конечного автомата прокручивает функция csv_cnt_proc()
  • Обработчик входов для состояния сразу после инициализации
  • Обработчик состояния аккумулятора
  • Обработчик из состояния, когда уже был принят какой-либо разделитель
  • Обработчик для состояния завершения обработки строки

Фаза 5. Тестирование

Каждый программный компонент надо тестировать. Вот набор тестовых случаев, которые должны отрабатывать.

  1. 3975, 1.667, 27.50, 21:20:36, 7/8/2023, 1520045092
  2. 4452,0.000,17.00, 00:00:18, 14/7/2023, 1517894674
  3. ll wm8731 debug;ll i2c debug;tsr 127ll wm8731 debug

Сборка и прогон этого кода через модульные тесты на PC показали, что всё работает!

Тестирование

Достоинства CSV протокола и данного парсера в частности

  1. Простота извлечения данных по индексу.
  2. Человеко-читаемость CSV строчек.
  3. Совместим с программами обработки электронных таблиц. Текстовый CSV файл можно загрузить в Google SpreadSheets или Excel.
  4. Благодаря этому конечному автомату, CSV строки можно разбирать в потоковом режиме.
  5. В представленном решении отсутствует нужда в динамическом выделении памяти, что особенно важно в программировании микроконтроллеров.
  6. В каждой функции только 1 return. Это как раз соответствует стандарту ISO26262. Значит этот код можно использовать в автомобильной промышленности.

Как видите, написать надежный парсер CSV строчек не такая уж и тривиальная задача. Надо спроектировать конечный автомат на 4 состояния, подготовить достаточное количество тестов.

Понимание кода программы на языке программирования

При этом даже наличие текста программы на С не всегда достаточно для понимания работы кода. Мораль этого теста в том, что при решении любой задачи в программировании нельзя сразу кидаться писать код. Надо сперва нарисовать схему конечного автомата.

Исходник это не код, исходник это документация.

Выделение подстрок из строк

Вот Вы и научились выделять подстроки из строк. Далее можно применять распознавание числа из строки. Про это у меня есть отдельный текст:

Raspoznavanie Veshchestvennovo Chisla iz Strochki

Надеюсь, что этот текст поможет другим программистам микроконтроллеров решать повседневные задачи.

Тест-case(ы)

Я был бы признателен за набор тест-case(ов) для проверки данного программного компонента.

Справочник программирования

  • Uniform Resource Locator
  • Global Navigation Satellite System
  • Application Programming Interface
  • National Marine Electronics Association

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Синтаксический разбор CSV строчек

Вам приходилось делать синтаксический разбор CSV строчек?

Проголосовали 43 пользователя. Воздержавшихся нет.

Синтаксический разбор NMEA протокола

Вы делали синтаксический разбор NMEA протокола?

Проголосовали 43 пользователя. Воздержался 1 пользователь.

Сейчас ищут техподдержку:  МЧС в Ростове-на-Дону - адреса, телефоны, отзывы