Парсинг текстового файла с SD карты

Тема в разделе "Arduino & Shields", создана пользователем alexval2007, 1 июл 2018.

  1. alexval2007

    alexval2007 Нерд

    Добрый день товарищи.

    Стоит задача разобрать текстовый файл на переменные. Файл лежит на SD карте.
    Удалось считать файл с карты в строку и вывести содержимое строки в монитор для теста.
    теперь некоторый затык с разбором.

    вот содержимое файла:
    Код (C++):
    F:\MUZON.mp3
    № Модуля;№ Канала;Начало;Задержка
    1;1;00:09.207;00:10.207;00:01.000;01.000;;;
    1;2;00:12.207;00:15.207;00:01.000;03.000;;;
    1;3;00:19.142;00:20.142;00:01.000;01.000;;;
    1;4;00:25.108;00:25.108;00:01.000;00.000;;;
    1;5;00:30.000;00:30.000;00:01.000;00.000;;;
    1;6;00:35.000;00:35.000;00:01.000;00.000;;;
    1;7;00:40.000;00:40.000;00:01.000;00.000;;;
    1;8;00:45.000;00:45.000;00:00.000;00.000;;;
    1;9;00:50.000;00:50.000;00:00.000;00.000;;;
    1;10;00:55.000;00:55.000;00:00.000;00.000;;;
    1;11;01:00.000;01:00.000;00:00.000;00.000;;;
    1;12;01:05.000;01:05.000;00:00.000;00.000;;;
    1;13;01:10.000;01:10.000;00:00.000;00.000;;;
    1;14;01:15.000;01:15.000;00:00.000;00.000;;;
    1;15;01:20.000;01:20.000;00:00.000;00.000;;;
    1;16;01:25.000;01:25.000;00:00.000;00.000;;;
    1;17;01:30.000;01:30.000;00:00.000;00.000;;;
    1;18;01:35.000;01:35.000;00:00.000;00.000;;;
    1;19;01:40.000;01:40.000;00:00.000;00.000;;;
    1;20;01:45.000;01:45.000;00:00.000;00.000;;;
    1;21;01:50.000;01:50.000;00:00.000;00.000;;;
    1;22;01:55.000;01:55.000;00:00.000;00.000;;;
    1;23;02:00.000;02:00.000;00:00.000;00.000;;;
    1;24;02:05.000;02:05.000;00:00.000;00.000;;;
    1;25;02:10.000;02:10.000;00:00.000;00.000;;;
    1;26;02:15.000;02:15.000;00:00.000;00.000;;;
    1;27;02:20.000;02:20.000;00:00.000;00.000;;;
    1;28;02:25.000;02:25.000;00:00.000;00.000;;;
    1;29;02:30.000;02:30.000;00:00.000;00.000;;;
    1;30;02:35.000;02:35.000;00:00.000;00.000;;;
    1;31;02:40.000;02:40.000;00:00.000;00.000;;;
    1;32;02:45.000;02:45.000;00:00.000;00.000;;;
     
    Строки под номерами 1 и 2 нужно пропустить и начать брать данные начиная с 3й строки файла.
    переменные разделенные символом ";" группа параметров оканчивается символами ";;;" и переходом на следующую строку.
    вот код что я уже написал
    Код (C++):
    //----------------------------------------------------------------------------------------
    #include <SD.h>
    #include <SPI.h>
    //----------------------------------------------------------------------------------------
    const int chipSelect = 53;  // Номер пина для CD карты для MEGA CS
    File dataFile;
    String buffer;//тут хранится прочитанный из карты текст
    boolean SDfound;
    //----------------------------------------------------------------------------------------
    void setup()
    {
      Serial.begin(9600);         // Инициализируем UART.
      Serial.println("Initializing SD card..."); // Инициализация SD-карты...
     
      pinMode(chipSelect, OUTPUT);// Настроим выход выбора микросхемы на вывод.
                         
      if (SDfound == 0)
      {
        if (!SD.begin(chipSelect))
        {
          Serial.print("The SD card cannot be found");
          while(1);
        }
      }
     
      SDfound = 1;
      dataFile = SD.open("TEST.zpl");//Откроем файл
      Serial.println("SD card ok.");

      if (!dataFile)
      {
        Serial.print("text fail eror"); // Текстовый файл не открывается
        while(1);
      }

      while (dataFile.available()) //Читаем содержимое файла
      {
        buffer = dataFile.readStringUntil('\n');//Считываем с карты весь дотекст в строку до символа окончания.
        Serial.println(buffer); // для отладки отправляем по UART все что прочитали с карты.
      }
      dataFile.close(); //закроем файл
    }

    //----------------------------------------------------------------------------------------
    void loop()
    {
     
    }
    //----------------------------------------------------------------------------------------

    Осталось разобраться как разобрать текст который лежит в строке на группы а их на отдельные параметры.
     
  2. Mitrandir

    Mitrandir Гуру

  3. Daniil

    Daniil Гуру

    Вы прочитали строку (она оканчивается "\n").
    Строка это набор массив символов.
    Нужно в цикле пробежаться по строке и вырезать из нее нужные вам переменные. (Как подсказали выше strok)
    Причём вырезать вы будете символы ascii, т.е. чтобы преобразовать из символа "1" (ascii код символа 1 = 49) в число 1 надо из кода символа вычесть 48.
    Если переменная имеет значение из нескольких цифр (допустим 12), то нужно домножить предыдущее считанное число на 10 и прибавить новое считанное число).
     
  4. alexval2007

    alexval2007 Нерд

    можно подробней о функции strok не совсем понятно как ей скормить полученную строку
     
  5. Mitrandir

    Mitrandir Гуру

    По ссылке что я дал пример есть.
    Передавайте ей строку и разделитель, она откусит от нее кусок
     
  6. alexval2007

    alexval2007 Нерд

    вот что получается
    Код (C++):
    //----------------------------------------------------------------------------------------
    #include <SD.h>
    #include <SPI.h>
    #include <string.h>
    template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; }
    //----------------------------------------------------------------------------------------
    const int chipSelect = 53;  // Номер пина для CD карты для MEGA CS
    File dataFile;
    String buffer;//тут хранится прочитанный из карты текст
    boolean SDfound;
    //----------------------------------------------------------------------------------------
    void setup()
    {
      Serial.begin(9600);         // Инициализируем UART.
      Serial.println("Initializing SD card..."); // Инициализация SD-карты...

      pinMode(chipSelect, OUTPUT);// Настроим выход выбора микросхемы на вывод.
                       
      if (SDfound == 0)
      {
        if (!SD.begin(chipSelect))
        {
          Serial.print("The SD card cannot be found");
          while(1);
        }
      }

      SDfound = 1;
      dataFile = SD.open("TEST.zpl");//Откроем файл
      Serial.println("SD card ok.");

      if (!dataFile)
      {
        Serial.print("text fail eror"); // Текстовый файл не открывается
        while(1);
      }

      while (dataFile.available()) //Читаем содержимое файла
      {
        buffer = dataFile.readStringUntil('\n');//Считываем с карты весь дотекст в строку до символа окончания.
        //Serial.println(buffer); // для отладки отправляем по UART все что прочитали с карты.
      }
      dataFile.close(); //закроем файл
      Serial.println("Test");

      //char str[] ="- This, a sample string.";
      char *pch;
      Serial.println (buffer);
      pch = strtok (buffer," ,.-");
      while (pch != NULL)
      {
        Serial.println (pch);
        pch = strtok (NULL, " ,.-");
      }

      /*
      char str[] ="- This, a sample string.";
      char * pch;
      Serial.println (str);
      pch = strtok (str," ,.-");
      while (pch != NULL)
      {
        Serial.println (pch);
        pch = strtok (NULL, " ,.-");
      }
      */

    }
    //----------------------------------------------------------------------------------------
    void loop()
    {

    }
    //----------------------------------------------------------------------------------------
    сообщение компилятора
    cannot convert 'String' to 'char*' for argument '1' to 'char* strtok(char*, const char*)'
    я так понимаю эта функция char тип данных хочет а у меня string что посоветуете?

    Добавлено позднее
    вот что получилось
    Код (C++):
    //----------------------------------------------------------------------------------------
    #include <SD.h>
    #include <SPI.h>
    #include <string.h>
    template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; }
    //----------------------------------------------------------------------------------------
    const int chipSelect = 53;  // Номер пина для CD карты для MEGA CS
    File dataFile;
    String buffer;//тут хранится прочитанный из карты текст
    boolean SDfound;
    //char charBuf[64];
    //----------------------------------------------------------------------------------------
    void setup()
    {
      Serial.begin(9600);         // Инициализируем UART.
      Serial.println("Initializing SD card..."); // Инициализация SD-карты...
     
      pinMode(chipSelect, OUTPUT);// Настроим выход выбора микросхемы на вывод.
                         
      if (SDfound == 0)
      {
        if (!SD.begin(chipSelect))
        {
          Serial.print("The SD card cannot be found");
          while(1);
        }
      }
     
      SDfound = 1;
      dataFile = SD.open("TEST.zpl");//Откроем файл
      Serial.println("SD card ok.");

      if (!dataFile)
      {
        Serial.print("text fail eror"); // Текстовый файл не открывается
        while(1);
      }

      while (dataFile.available()) //Читаем содержимое файла
      {
        buffer = dataFile.readStringUntil('\n');//Считываем с карты весь дотекст в строку до символа окончания.
        Serial.println(buffer); // для отладки отправляем по UART все что прочитали с карты.
      }
      dataFile.close(); //закроем файл
      Serial.println("Test");
     
      char charBuf[buffer.length()+1];
      buffer.toCharArray(charBuf, buffer.length());
    // Serial.println (charBuf);
      char * pch;
      pch = strtok (charBuf,";");
     
      while (pch != NULL)
      {
        Serial.println (pch);
        pch = strtok (NULL, ";");
      }


    }
    //----------------------------------------------------------------------------------------
    void loop()
    {
     
    }
    //----------------------------------------------------------------------------------------
    на выходе имеем
    F:\MUZON.mp3

    № Модуля;№ Канала;Начало;Задержка

    1;1;00:09.207;00:10.207;00:01.000;01.000;;;

    1;2;00:12.207;00:15.207;00:01.000;03.000;;;

    1;3;00:19.142;00:20.142;00:01.000;01.000;;;

    1;4;00:25.108;00:25.108;00:01.000;00.000;;;

    1;5;00:30.000;00:30.000;00:01.000;00.000;;;

    1;6;00:35.000;00:35.000;00:01.000;00.000;;;

    1;7;00:40.000;00:40.000;00:01.000;00.000;;;

    1;8;00:45.000;00:45.000;00:00.000;00.000;;;

    1;9;00:50.000;00:50.000;00:00.000;00.000;;;

    1;10;00:55.000;00:55.000;00:00.000;00.000;;;

    1;11;01:00.000;01:00.000;00:00.000;00.000;;;

    1;12;01:05.000;01:05.000;00:00.000;00.000;;;

    1;13;01:10.000;01:10.000;00:00.000;00.000;;;

    1;14;01:15.000;01:15.000;00:00.000;00.000;;;

    1;15;01:20.000;01:20.000;00:00.000;00.000;;;

    1;16;01:25.000;01:25.000;00:00.000;00.000;;;

    1;17;01:30.000;01:30.000;00:00.000;00.000;;;

    1;18;01:35.000;01:35.000;00:00.000;00.000;;;

    1;19;01:40.000;01:40.000;00:00.000;00.000;;;

    1;20;01:45.000;01:45.000;00:00.000;00.000;;;

    1;21;01:50.000;01:50.000;00:00.000;00.000;;;

    1;22;01:55.000;01:55.000;00:00.000;00.000;;;

    1;23;02:00.000;02:00.000;00:00.000;00.000;;;

    1;24;02:05.000;02:05.000;00:00.000;00.000;;;

    1;25;02:10.000;02:10.000;00:00.000;00.000;;;

    1;26;02:15.000;02:15.000;00:00.000;00.000;;;

    1;27;02:20.000;02:20.000;00:00.000;00.000;;;

    1;28;02:25.000;02:25.000;00:00.000;00.000;;;

    1;29;02:30.000;02:30.000;00:00.000;00.000;;;

    1;30;02:35.000;02:35.000;00:00.000;00.000;;;

    1;31;02:40.000;02:40.000;00:00.000;00.000;;;

    1;32;02:45.000;02:45.000;00:00.000;00.000;;;

    Test
    1
    32
    02:45.000
    02:45.000
    00:00.000
    00.000

    разобралась последняя строка остальных не видит почему то
     
    Последнее редактирование: 1 июл 2018
  7. Mitrandir

    Mitrandir Гуру

    Есть два варианта:
    1) перевести строку в char*:

    Код (C++):
     char *pch;
      char* cbuffer = buffer.c_str();

      pch = strtok (cbuffer," ,.-");
      while (pch != NULL)
      {
        Serial.println (pch);
        pch = strtok (NULL, " ,.-");
      }
    2) Собирать кусками:
    Код (C++):

    //каким-то образом в str у нас находится строка для разбора

      String str = "1;1;00:09.207;00:10.207;00:01.000;01.000;;;";

      int startpos = 0;
      int endpos;
      int n = 0;
      bool eflag = true;
      do{
        endpos= str.indexOf(";",startpos);

        if(endpos < 0)
        {
          break;
        }
        String part = str.substring(startpos,endpos);
        switch(n++){
          case 0:
            Serial.print("#module ");
            break;
          case 1:
            Serial.print("№ Канала ");
            break;
          case 2:
            Serial.print("Начало ");
            break;
          case 3:
            Serial.print("Задержка ");
            eflag = false;
            break;            
        }
        Serial.println(part);
        startpos = endpos + 1;

      }while(eflag);
      delay (5000);

     
    Второй пример будет спамить:

     
    Последнее редактирование: 1 июл 2018
  8. Daniil

    Daniil Гуру

    После 1ого цикла while у вас в буфере осталась последняя строка, вот он её и обоаботал.
     
  9. alexval2007

    alexval2007 Нерд

    первый пример не компилируется
    Код (C++):
    //----------------------------------------------------------------------------------------
    #include <SD.h>
    #include <SPI.h>
    #include <string.h>
    //----------------------------------------------------------------------------------------
    const int chipSelect = 53;  // Номер пина для CD карты для MEGA CS
    File dataFile;
    String buffer;//тут хранится прочитанный из карты текст
    boolean SDfound;
    //----------------------------------------------------------------------------------------
    void setup()
    {
      Serial.begin(9600);         // Инициализируем UART.
      Serial.println("Initializing SD card..."); // Инициализация SD-карты...
      pinMode(chipSelect, OUTPUT);// Настроим выход выбора микросхемы на вывод.
                       
      if (SDfound == 0)
      {
        if (!SD.begin(chipSelect))
        {
          Serial.print("The SD card cannot be found");
          while(1);
        }
      }
      SDfound = 1;
      dataFile = SD.open("TEST.zpl");//Откроем файл
      Serial.println("SD card ok.");

      if (!dataFile)
      {
        Serial.print("text fail eror"); // Текстовый файл не открывается
        while(1);
      }

      while (dataFile.available()) //Читаем содержимое файла
      {
        buffer = dataFile.readStringUntil('\n');//Считываем с карты весь дотекст в строку до символа окончания.
        Serial.println(buffer); // для отладки отправляем по UART все что прочитали с карты.
      }
      dataFile.close(); //закроем файл
      Serial.println("Test");
      char *pch;
      char *cbuffer = buffer.c_str();

      pch = strtok (cbuffer, " ,.-");
      while (pch != NULL)
      {
        Serial.println (pch);
        pch = strtok (NULL, " ,.-");
      }
    }
    //----------------------------------------------------------------------------------------
    void loop()
    {

    }
    //----------------------------------------------------------------------------------------
    сообщение компилятора
    F:\Projects\SD_test_5.ino: In function 'void setup()':
    SD_test_5:46: error: invalid conversion from 'const char*' to 'char*' [-fpermissive]
    char *cbuffer = buffer.c_str();
     
  10. Mitrandir

    Mitrandir Гуру

    Спасибо за замечание, я ошибся.
    надо писать так:

    Код (C++):
    const char* cbuffer = buffer.c_str();
    но это тоже не поможет.

    Купился на текст описания с офф сайта ардуино:

    но по факту метод c_str возвращает указатель на константу, и менять его содержимое нельзя. т.е передать его функции strtok не выйдет

    Код (C++):

    string str = ".....";

    char *cstr = new char[str.length() + 1]; //выделяем память под строку в формате char*
    strcpy(cstr, str.c_str()); //копируем

    //работаем со строкой
    pch =strtok(cstr, " ,.-");
    while(pch !=NULL)
    {
        Serial.println(pch);
        pch =strtok(NULL, " ,.-");
    }
    //чистим память
    delete [] cstr;

     
     
  11. alexval2007

    alexval2007 Нерд

    есть такой вариант даже работоспособный только допилить немного надо
    Код (C++):
    //----------------------------------------------------------------------------------------
    #include <string.h>
    //----------------------------------------------------------------------------------------
      char *s = (char *)
        "F:\MUZON.mp3\n"
        "№ Модуля;№ Канала;Начало;Задержка\n"
        "1;1;00:12.207;00:15.207;00:01.000;03.000;;;\n"
        "1;2;00:19.142;00:20.142;00:01.000;01.000;;;\n"
        "1;3;00:25.108;00:25.108;00:01.000;00.000;;;\n"
        "1;4;00:30.000;00:30.000;00:01.000;00.000;;;\n"
        "1;5;00:35.000;00:35.000;00:01.000;00.000;;;\n"
        "1;6;00:40.000;00:40.000;00:01.000;00.000;;;\n"
        "1;7;00:45.000;00:45.000;00:00.000;00.000;;;\n";
    //----------------------------------------------------------------------------------------
    void setup(void)
    {
      Serial.begin(9600);
      for (char *p = strtok(s, ";"); p; p = strtok(NULL, ";\n"))
      {
        Serial.println(p);
      }
    }
    //----------------------------------------------------------------------------------------
    void loop()
    {
     
    }
    //----------------------------------------------------------------------------------------
    Выводит
    Код (C++):
    F:MUZON.mp3
    № Модуля
    № Канала
    Начало
    Задержка
    1
    1
    00:12.207
    00:15.207
    00:01.000
    03.000
    1
    2
    00:19.142
    00:20.142
    00:01.000
    01.000
    1
    3
    00:25.108
    00:25.108
    00:01.000
    00.000
    1
    4
    00:30.000
    00:30.000
    00:01.000
    00.000
    1
    5
    00:35.000
    00:35.000
    00:01.000
    00.000
    1
    6
    00:40.000
    00:40.000
    00:01.000
    00.000
    1
    7
    00:45.000
    00:45.000
    00:00.000
    00.000
     
    в принципе это то что надо, нужно только Serial.println(p); заменить на сохранение в массив чтобы дальше можно было результат парсинга распихать по переменным.
     
    Mitrandir нравится это.
  12. alexval2007

    alexval2007 Нерд

    Что посоветуете Daniil ?
     
  13. b707

    b707 Гуру

    а сами-то как думаете? :)
    ответ очевиден - не читайте весь файл в цикле while.
    Читайте одну строчку, потом обрабатывайте. Потом следующую - ее обрабатывайте... и так далее, построчно.
     
  14. b707

    b707 Гуру

    ну так замените. Вам этот код целиком написали - неужели и сохранение переменных в массив тоже за вас делать?
    Кстати, что за ардуина у вас? Если это Нано/Уно - все эти строчки в массив вы не распихаете - памяти не хватит. Нужно придумать другой алгоритм работы, чтобы не хранить эти данные в памяти, а сразу обрабатывать.
     
  15. alexval2007

    alexval2007 Нерд

    По поводу построчного чтения можно пример, потому как немного непонятно как его реализовать если через for то как указать количество строк в файле ведь оно не постоянно может быть одна а может и за сотню. По второму посту пытался сохранить переменную p массив char но неполучается компилятор ругается.
    Код написан хитро я неполностью понимаю его работу.
    Char data[250];
    for(char*p =strtok(s,";"); p; p =strtok(NULL, ";\n"))
    {
    Serial.println(p);
    data[p]=p;
    }
    Возможно что-то делаю не так.
     
  16. b707

    b707 Гуру

    да причем тут цикл for. Оставте while, просто измените порядок обработки.
    Посмотрите на свой код - вы сейчас в цикле while читаете строку за строкой в буфер, поэтому каждая следующая строка затирает предыдущую. А обработку начинаете только после чтения всего файла - поэтому обрабатывается только последняя строка. А надо - считали одну строку - тут же обработали. Для этого надо всего лишь перетащить код обработки внутрь цикла while
    Примерно вот так
    Код (C++):
     while (dataFile.available()) //Читаем содержимое файла
      {
        buffer = dataFile.readStringUntil('\n');//Считываем с карты весь дотекст в строку до символа окончания.
        Serial.println(buffer); // для отладки отправляем по UART все что прочитали с карты.
        char charBuf[buffer.length()+1];
        buffer.toCharArray(charBuf, buffer.length());

        char * pch;
        pch = strtok (charBuf,";");
        while (pch != NULL)
          {
          Serial.println (pch);
          pch = strtok (NULL, ";");
         }
       }
      dataFile.close(); //закроем файл
      Serial.println("Test");
     
     
  17. alexval2007

    alexval2007 Нерд

    Спасибо за дельный совет с картой получилось но дальше небольшие проблемки
    вот что получилось это если читать из константы.
    Код (C++):
    //----------------------------------------------------------------------------------------
    struct kv {
    char *value;
    char *Slat;
    char *Cue;
    char *Time;
    };
    //----------------------------------------------------------------------------------------
    void setup()
    {
       Serial.begin(9600);
       while (!Serial);
     
       char S[] =
       "1;1;00:09.207;00:10.207;00:01.000;01.000;;;\n"
       "1;2;00:12.207;00:15.207;00:01.000;03.000;;;\n"
       "1;3;00:19.142;00:20.142;00:01.000;01.000;;;\n"
       "1;4;00:25.108;00:25.108;00:01.000;00.000;;;\n"
       "1;5;00:30.000;00:30.000;00:01.000;00.000;;;\n"
       "1;6;00:35.000;00:35.000;00:01.000;00.000;;;\n"
       "1;7;00:40.000;00:40.000;00:01.000;00.000;;;\n"
       "1;8;00:45.000;00:45.000;00:00.000;00.000;;;\n"
       "1;9;00:50.000;00:50.000;00:00.000;00.000;;;\n"
       "1;10;00:55.000;00:55.000;00:00.000;00.000;;;\n"
       "1;11;01:00.000;01:00.000;00:00.000;00.000;;;\n"
       "1;12;01:05.000;01:05.000;00:00.000;00.000;;;\n"
       "1;13;01:10.000;01:10.000;00:00.000;00.000;;;\n"
       "1;14;01:15.000;01:15.000;00:00.000;00.000;;;\n"
       "1;15;01:20.000;01:20.000;00:00.000;00.000;;;\n"
       "1;16;01:25.000;01:25.000;00:00.000;00.000;;;\n"
       "1;17;01:30.000;01:30.000;00:00.000;00.000;;;\n"
       "1;18;01:35.000;01:35.000;00:00.000;00.000;;;\n"
       "1;19;01:40.000;01:40.000;00:00.000;00.000;;;\n"
       "1;20;01:45.000;01:45.000;00:00.000;00.000;;;\n"
       "1;21;01:50.000;01:50.000;00:00.000;00.000;;;\n"
       "1;22;01:55.000;01:55.000;00:00.000;00.000;;;\n"
       "1;23;02:00.000;02:00.000;00:00.000;00.000;;;\n"
       "1;24;02:05.000;02:05.000;00:00.000;00.000;;;\n"
       "1;25;02:10.000;02:10.000;00:00.000;00.000;;;\n"
       "1;26;02:15.000;02:15.000;00:00.000;00.000;;;\n"
       "1;27;02:20.000;02:20.000;00:00.000;00.000;;;\n"
       "1;28;02:25.000;02:25.000;00:00.000;00.000;;;\n"
       "1;29;02:30.000;02:30.000;00:00.000;00.000;;;\n"
       "1;30;02:35.000;02:35.000;00:00.000;00.000;;;\n"
       "1;31;02:40.000;02:40.000;00:00.000;00.000;;;\n"
       "1;32;02:45.000;02:45.000;00:00.000;00.000;;;\n";

       Serial.println("test data: ");
       Serial.println(S);
       Serial.println();

        struct kv parsed[192]; // 192 место для ввода для 32 каналов по 6 параметров
        int nparsed = 0;

        for (char *p = strtok(S, ";"); p; p = strtok(NULL, ";\n"))
        {
          parsed[nparsed].value = p;
          nparsed++;
        }

        Serial.print("Pole ");
        Serial.println(nparsed);
        Serial.println("value");

        for (int i = 0; i < nparsed; i++)
        {
           Serial.print(parsed[i].value);
           Serial.println();
        }
     
         Serial.println();
         Serial.println("test2 ");
         Serial.print("Slat: "); Serial.println(parsed[186].value);
         Serial.print("Cue:  "); Serial.println(parsed[187].value);
         Serial.print("None: "); Serial.println(parsed[188].value);
         Serial.print("Time: "); Serial.println(parsed[189].value);
         Serial.print("None: "); Serial.println(parsed[190].value);
         Serial.print("None: "); Serial.println(parsed[191].value);
    }
    //----------------------------------------------------------------------------------------
    void loop()
    {

    }
    //----------------------------------------------------------------------------------------
    на выходе получим
    Код (C++):
    test data:
    1;1;00:09.207;00:10.207;00:01.000;01.000;;;
    1;2;00:12.207;00:15.207;00:01.000;03.000;;;
    1;3;00:19.142;00:20.142;00:01.000;01.000;;;
    1;4;00:25.108;00:25.108;00:01.000;00.000;;;
    1;5;00:30.000;00:30.000;00:01.000;00.000;;;
    1;6;00:35.000;00:35.000;00:01.000;00.000;;;
    1;7;00:40.000;00:40.000;00:01.000;00.000;;;
    1;8;00:45.000;00:45.000;00:00.000;00.000;;;
    1;9;00:50.000;00:50.000;00:00.000;00.000;;;
    1;10;00:55.000;00:55.000;00:00.000;00.000;;;
    1;11;01:00.000;01:00.000;00:00.000;00.000;;;
    1;12;01:05.000;01:05.000;00:00.000;00.000;;;
    1;13;01:10.000;01:10.000;00:00.000;00.000;;;
    1;14;01:15.000;01:15.000;00:00.000;00.000;;;
    1;15;01:20.000;01:20.000;00:00.000;00.000;;;
    1;16;01:25.000;01:25.000;00:00.000;00.000;;;
    1;17;01:30.000;01:30.000;00:00.000;00.000;;;
    1;18;01:35.000;01:35.000;00:00.000;00.000;;;
    1;19;01:40.000;01:40.000;00:00.000;00.000;;;
    1;20;01:45.000;01:45.000;00:00.000;00.000;;;
    1;21;01:50.000;01:50.000;00:00.000;00.000;;;
    1;22;01:55.000;01:55.000;00:00.000;00.000;;;
    1;23;02:00.000;02:00.000;00:00.000;00.000;;;
    1;24;02:05.000;02:05.000;00:00.000;00.000;;;
    1;25;02:10.000;02:10.000;00:00.000;00.000;;;
    1;26;02:15.000;02:15.000;00:00.000;00.000;;;
    1;27;02:20.000;02:20.000;00:00.000;00.000;;;
    1;28;02:25.000;02:25.000;00:00.000;00.000;;;
    1;29;02:30.000;02:30.000;00:00.000;00.000;;;
    1;30;02:35.000;02:35.000;00:00.000;00.000;;;
    1;31;02:40.000;02:40.000;00:00.000;00.000;;;
    1;32;02:45.000;02:45.000;00:00.000;00.000;;;

    Pole 192
    value
    1
    1
    00:09.207
    00:10.207
    00:01.000
    01.000
    1
    2
    00:12.207
    00:15.207
    00:01.000
    03.000
    1
    3
    00:19.142
    00:20.142
    00:01.000
    01.000
    1
    4
    00:25.108
    00:25.108
    00:01.000
    00.000
    1
    5
    00:30.000
    00:30.000
    00:01.000
    00.000
    1
    6
    00:35.000
    00:35.000
    00:01.000
    00.000
    1
    7
    00:40.000
    00:40.000
    00:01.000
    00.000
    1
    8
    00:45.000
    00:45.000
    00:00.000
    00.000
    1
    9
    00:50.000
    00:50.000
    00:00.000
    00.000
    1
    10
    00:55.000
    00:55.000
    00:00.000
    00.000
    1
    11
    01:00.000
    01:00.000
    00:00.000
    00.000
    1
    12
    01:05.000
    01:05.000
    00:00.000
    00.000
    1
    13
    01:10.000
    01:10.000
    00:00.000
    00.000
    1
    14
    01:15.000
    01:15.000
    00:00.000
    00.000
    1
    15
    01:20.000
    01:20.000
    00:00.000
    00.000
    1
    16
    01:25.000
    01:25.000
    00:00.000
    00.000
    1
    17
    01:30.000
    01:30.000
    00:00.000
    00.000
    1
    18
    01:35.000
    01:35.000
    00:00.000
    00.000
    1
    19
    01:40.000
    01:40.000
    00:00.000
    00.000
    1
    20
    01:45.000
    01:45.000
    00:00.000
    00.000
    1
    21
    01:50.000
    01:50.000
    00:00.000
    00.000
    1
    22
    01:55.000
    01:55.000
    00:00.000
    00.000
    1
    23
    02:00.000
    02:00.000
    00:00.000
    00.000
    1
    24
    02:05.000
    02:05.000
    00:00.000
    00.000
    1
    25
    02:10.000
    02:10.000
    00:00.000
    00.000
    1
    26
    02:15.000
    02:15.000
    00:00.000
    00.000
    1
    27
    02:20.000
    02:20.000
    00:00.000
    00.000
    1
    28
    02:25.000
    02:25.000
    00:00.000
    00.000
    1
    29
    02:30.000
    02:30.000
    00:00.000
    00.000
    1
    30
    02:35.000
    02:35.000
    00:00.000
    00.000
    1
    31
    02:40.000
    02:40.000
    00:00.000
    00.000
    1
    32
    02:45.000
    02:45.000
    00:00.000
    00.000

    test2
    Slat: 1
    Cue:  32
    None: 02:45.000
    Time: 02:45.000
    None: 00:00.000
    None: 00.000
     
    Последнее редактирование: 2 июл 2018
  18. alexval2007

    alexval2007 Нерд

    тут всё прекрасно а вот при чтение того же с карты проблемы вот тут просто читаю и делаю парсинг с выводом в порт
    Код (C++):
    //----------------------------------------------------------------------------------------
    #include <SD.h>
    #include <SPI.h>
    #include <string.h>
    //----------------------------------------------------------------------------------------
    struct kv {
    char *value;
    char *Slat;
    char *Cue;
    char *Time;
    };
    //----------------------------------------------------------------------------------------
    const int chipSelect = 53;  // Номер пина для CD карты для MEGA CS
    File dataFile;
    String buffer;//тут хранится прочитанный из карты текст
    boolean SDfound;
    //----------------------------------------------------------------------------------------
    void setup()
    {
       Serial.begin(9600); // Инициализируем UART.
       while (!Serial);
       
      char S[] = " ";
      struct kv parsed[192]; // 192 место для ввода для 32 каналов по 6 параметров
      int nparsed = 0;

      Serial.println("Initializing SD card..."); // Инициализация SD-карты...
      pinMode(chipSelect, OUTPUT);// Настроим выход выбора микросхемы на вывод.
                       
      if (SDfound == 0)
      {
        if (!SD.begin(chipSelect))
        {
          Serial.print("The SD card cannot be found");
          while(1);
        }
      }
      SDfound = 1;
      dataFile = SD.open("TEST.zpl");//Откроем файл
      Serial.println("SD card ok.");

      if (!dataFile)
      {
        Serial.print("text fail eror"); // Текстовый файл не открывается
        while(1);
      }

    Serial.println("Test-1");
    while (dataFile.available()) //Читаем содержимое файла
    {
        buffer = dataFile.readStringUntil('\n');//Считываем с карты весь дотекст в строку до символа окончания.
        Serial.println(buffer); // для отладки отправляем по UART все что прочитали с карты.
       
        char charBuf[buffer.length()+1];
        buffer.toCharArray(charBuf, buffer.length());

        char *pch;
        pch = strtok (charBuf,";");
        while (pch != NULL)
        {
          parsed[nparsed].value = pch;
          nparsed++;
          Serial.println (pch);
          pch = strtok (NULL, ";");
        }
      }
      dataFile.close(); //закроем файл
    }
    //----------------------------------------------------------------------------------------
    void loop()
    {

    }
    //----------------------------------------------------------------------------------------
    а вот тут попытался добавить сохранение в массив и пошли проблемы
    Код (C++):
    //----------------------------------------------------------------------------------------
    #include <SD.h>
    #include <SPI.h>
    #include <string.h>
    //----------------------------------------------------------------------------------------
    struct kv {
    char *value;
    char *Slat;
    char *Cue;
    char *Time;
    };
    //----------------------------------------------------------------------------------------
    const int chipSelect = 53;  // Номер пина для CD карты для MEGA CS
    File dataFile;
    String buffer;//тут хранится прочитанный из карты текст
    boolean SDfound;
    //----------------------------------------------------------------------------------------
    void setup()
    {
       Serial.begin(9600); // Инициализируем UART.
       while (!Serial);
       
      char S[] = " ";
      struct kv parsed[192]; // 192 место для ввода для 32 каналов по 6 параметров
      int nparsed = 0;

      Serial.println("Initializing SD card..."); // Инициализация SD-карты...
      pinMode(chipSelect, OUTPUT);// Настроим выход выбора микросхемы на вывод.
                       
      if (SDfound == 0)
      {
        if (!SD.begin(chipSelect))
        {
          Serial.print("The SD card cannot be found");
          while(1);
        }
      }
      SDfound = 1;
      dataFile = SD.open("TEST.zpl");//Откроем файл
      Serial.println("SD card ok.");

      if (!dataFile)
      {
        Serial.print("text fail eror"); // Текстовый файл не открывается
        while(1);
      }

    Serial.println("Test-1");
    /*
    while (dataFile.available()) //Читаем содержимое файла
    {
        buffer = dataFile.readStringUntil('\n');//Считываем с карты весь дотекст в строку до символа окончания.
        Serial.println(buffer); // для отладки отправляем по UART все что прочитали с карты.
       
        char charBuf[buffer.length()+1];
        buffer.toCharArray(charBuf, buffer.length());

        char *pch;
        pch = strtok (charBuf,";");
        while (pch != NULL)
        {
          parsed[nparsed].value = pch;
          nparsed++;
          Serial.println (pch);
          pch = strtok (NULL, ";");
        }
      }
    */


    while (dataFile.available()) //Читаем содержимое файла
    {
        buffer = dataFile.readStringUntil('\n');//Считываем с карты весь дотекст в строку до символа окончания.
        char charBuf[buffer.length() + 1];
        buffer.toCharArray(charBuf, buffer.length());

       
        for (char *p = strtok(charBuf, ";"); p; p = strtok(NULL, ";\n"))
        {
          parsed[nparsed].value = p;
          nparsed++;
        }

        Serial.print("Pole ");
        Serial.println(nparsed);
        Serial.println("value");

        for (int i = 0; i < nparsed; i++)
        {
           Serial.print(parsed[i].value);
           Serial.println();
        }
    }

      dataFile.close(); //закроем файл

         Serial.println();
         Serial.println("test2 ");
         Serial.print("Slat: "); Serial.println(parsed[186].value);
         Serial.print("Cue:  "); Serial.println(parsed[187].value);
         Serial.print("None: "); Serial.println(parsed[188].value);
         Serial.print("Time: "); Serial.println(parsed[189].value);
         Serial.print("None: "); Serial.println(parsed[190].value);
         Serial.print("None: "); Serial.println(parsed[191].value);
    }
    //----------------------------------------------------------------------------------------
    void loop()
    {

    }
    //----------------------------------------------------------------------------------------
    в терминале сообщения бегут без остановок да и с ошибками
     
  19. Daniil

    Daniil Гуру

    Какие?
    Мне кажется, что будет удобнее для тестов взять файл состоящий из 2-3 строк. (Сейчас листинги шибко большие).
    В вашем случае, когда вы постите по 2 листинга в сообщении, пишите для каждого что на входе, что на выходе и что хотели получить. И самое главное, когда вы пишите по 2 листинга, нам тоже анализировать их оба или всё таки акцентируем внимание на одной программе? Я понимаю, что вы хотите снабдить нас полной информацией, но оформляйте её чётче.
    Я правильно понимаю, что из всех листингов можно смотреть только те, что в последнем сообщении?
    2ой листинг:
    Цикл for написан опасно. Его можно переписать:
    Код (C++):
    char *p = strtok(charBuf, ";");
    while p
        {
          parsed[nparsed].value = p;
          nparsed++;
          p = strtok(NULL, ";\n"));
        }
    Как обрабатывается условие while?
    И в 1ом листинге нет "\n" для поиска.
    Это самые заметные отличия, которые я увидел и не знаю как влияют на результат. Рекомендую изменять программу медленно и фиксировать правильные результаты.
     
  20. alexval2007

    alexval2007 Нерд

    Немного о том что я хочу сделать в результате это будет по сути многоканальный таймер который берет настройки каналов из текстового файла на SD карте формат данных похож на CSV файл создает программа редактор на ПК. как я представляю процесс читаем файл с карты в буфер (в моем представленнии это строка) в файле несколько строк их может быть и одна и 60, в каждой строке есть группа параметров разделенных ";" и заканчивается строка ";;;" и переходом на новую строку. Эти параметры нужно разобрать на переменные и сохранить в массив ну или структуру в которой будет некоторое количество групп по 6 параметров.

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