Параметры strcat выдают ошибки указателя в моем приложении tcp server/parser

Я пытаюсь использовать плату Arduino Uno WiFi Rev2 для интеграции отдельных данных. Я буду использовать набор микросхем NINA WiFi и связанные библиотеки для запуска сервера, который будет периодически запрашивать и получать клиентскую информацию, размещенную на нескольких типах устройств, которые будут работать одновременно; таким образом, он в значительной степени разделен на 2 раздела: 1.) Управляйте клиентскими соединениями и их символьными массивами 2.) Анализ информации и соответствующий ответ с точки зрения контроля

Это то, что у меня есть на данный момент, и то, что я собирал на днях:

#include <stdlib.h>
#include <SPI.h>
#include <WiFiNINA.h>

char ssid[] = "***";                // Дом -- SSID сети (имя)
char pass[] = "***";              // Дом -- пароль SSID (WPA2-PSK)

#define MAX_CLIENTS 5
#define MAX_LINE_LEN 50 
char inputs[MAX_CLIENTS][MAX_LINE_LEN] = {0}; // Создаем двумерный массив
client/received data
int msg_array[] = {0,0};
int net_status = WL_IDLE_STATUS;              // Состояние радио Wi-Fi
WiFiServer server(80);           // Создаем серверный объект на порту WiFi
                                 // сервер, который будет использоваться для
                                 // отвечаем на команды

WiFiClient *clients[MAX_CLIENTS] = {NULL};    // Создаем клиентские объекты
                                              // ограничен размером
                                              // МАКСИМАЛЬНОЕ_КЛИЕНТОВ


byte mac[] = {0xDE,0xAD,0xBE,0xEF,0xFE,0xED}; // физический MAC-адрес Arduino
byte ip[] = {192,168,9,25};              // IP этого контроллера
byte gateway[] = {192,168,0,1};          // Адрес маршрутизатора (интернет)
byte subnet[] = {255,255,0,0};           // Маска подсети

unsigned long wd_Dside, wd_Cside = millis();   // Собираем текущий tstamp
unsigned long wd_Delap, wd_Celap = 0;          // Создаем прошедшее время
                                               //прилавок


void setup(){

   pinMode(4, OUTPUT);                 // вывод, выбранный для управления D SIDE
   pinMode(5, OUTPUT);                 // вывод, выбранный для управления C SIDE

   //включаем последовательную печать данных
   Serial.begin(9600); 
   while (!Serial){
       Serial.println("No serial.");
   }

      Serial.println("Serial.begin was initiated."); 


   if (WiFi.status() == WL_NO_SHIELD) {  // проверяем модуль WiFi:
      Serial.println("Wi-Fi: Communication with NINA has failed!");
      // здесь ничего не делаем
      while (true);
   }

   String fv = WiFi.firmwareVersion();
   if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
      Serial.println("Please upgrade the firmware");
   }

   while (net_status != WL_CONNECTED) {
      Serial.print("Attempting to connect to WPA SSID: ");
      Serial.println(ssid);

      // Подключиться к сети WPA/WPA2:
      net_status = WiFi.begin(ssid, pass); // Попытка присоединиться к этому SSID

      // ждем 5 секунд соединения:
      delay(5000);

      listNetworks(); 

      server.begin();                      // Запускаем Wi-Fi сервер
      Serial.print("Server started on ");
      Serial.println(WiFi.localIP()); 
    }
}


void loop() {

    delay(5);

    WiFiClient newClient = server.available(); // начинаем слушать
                                               // клиентские сообщения
    if (newClient) {
        Serial.println("New client discovered."); // Можно использовать как
                                                  // ACK/рукопожатие
                                                  // хост на стороне клиента
        for (int i=0; i<MAX_CLIENTS; i++) {
          if (clients[i] == NULL) {
            clients[i] = new WiFiClient(newClient);
            break;
      }
   }
}

    for (int i=0; i<MAX_CLIENTS; i++){      // Проверяем клиент на наличие данных
      if (clients[i] != NULL && clients[i]->available()){  
         // Если данные не мусор и данные доступны..
    
        char newChar = clients[i]->read();                            
        // Чтение данных
                                           
        if (newChar == 'x') {                                         
        // Проверяем символ завершения для разделения
      
        // Теперь проанализируем с помощью strtok, чтобы получить параметризацию
          char delimiters[] = ",";                                    
          char* valIndex;
          valIndex = strtok(inputs[i], delimiters);
          for (int j=0; j < 2; j++){                                  
            // Расширение позже до наибольшего ожидаемого количества символов
            msg_array[j] = atoi(valIndex); 
            Serial.print(msg_array[j]);
            valIndex = strtok(NULL, delimiters);
          }

          switch(msg_array[0]) {          
          // Определяем тип полученного сообщения (символ 0 анализируется как
          // Тип сообщения)
        
            case '3':                                                 
            // Проверить строку на наличие команд клиента, чтобы включить или выключить стороны.
            if(msg_array[1] == '1')                                   
            // Тип сообщения 3, Инструкция 1: включить сторону D
              {
                digitalWrite(4, HIGH);                                
                // Установить вывод 4 в высокий уровень
                Serial.println("Dside started.");
                wd_Delap = 0;                                         
                // Сбросить значение сторожевого таймера истекшего времени для стороны D.
                wd_Dside = millis();                                  
                // Последний тактовый импульс от клиентского устройства на стороне D.
              }
            if(msg_array[1] == '2')                                   
            // Тип сообщения 3, Инструкция 2: ВЫКЛЮЧИТЕ сторону D
              {
                digitalWrite(4, LOW);                                 
                // Установить на выводе 4 низкий уровень
                Serial.println("Dside stopped");
                wd_Delap = 0;                                         
                // Сбросить значение сторожевого таймера истекшего времени для стороны D.
                wd_Dside = millis();                                  
                // Последний тактовый импульс от клиентского устройства на стороне D.
              } 
            if(msg_array[1] == '3')                                   
                // Тип сообщения 3, Инструкция 3: включить сторону C
              {
                digitalWrite(5, HIGH);                                
                // Установить вывод 5 в высокий уровень
                Serial.println("C side started.");
                wd_Celap = 0;                                         
                // Сброс значения времени сторожевого таймера истекшего времени для стороны C.
                wd_Cside = millis();                                  
                // Последний тактовый импульс от клиентского устройства на стороне C.
              }
            if(msg_array[1] == '4')                                   
                // Тип сообщения 3, Инструкция 4: Выключите сторону C
              {
                digitalWrite(5, LOW);                                 
                // Установить на выводе 5 низкий уровень
                Serial.println("C side stopped.");
                wd_Celap = 0;                                         
                // Сброс значения времени сторожевого таймера истекшего времени для стороны C.
                wd_Cside = millis();                                  
                // Последний тактовый импульс от клиентского устройства на стороне C.
              }
            break;
        
            case '6':
                                                                  
                // Проверяем строку на наличие другого типа сообщения TBD
            break; 
        
            default: 
              Serial.println("Default break. Received crap.");
            break;
        
          }
      
        inputs[i][0] = '\0';                                          
        // Очистить этот элемент массива для следующего сообщения
        // клиенты[i]->stop();
        // По умолчанию завершаем сеанс клиента, просто ждем открытия нового TCP
        // удалить клиентов[i];
        // Удалить данные клиентского элемента
        // клиенты[i] = NULL;
        // Сброс в NULL
    
        }
    
        else {
      
           if (strlen(inputs[i]) > MAX_LINE_LEN) {                    
                // Первая проверка на соответствие размеру
           Serial.println("Max line length exceeded from client.");
           inputs[i][0] = '0';                                        
                // Очистить этот элемент массива для следующего сообщения
           }
           else {
           **strcat(inputs[i], newChar);**                                
                // Добавляем символ в полученную строку
           }
  
          Serial.println(); 
          Serial.println(newChar);
        }
      }

    // Обновить сторожевые таймеры

    wd_Delap += (millis()-wd_Dside);
    wd_Celap += (millis()-wd_Cside); 
      
    if (wd_Delap>=60000)
          {
            Serial.print("Elapsed time on watchdog, D side: ");
            Serial.println(wd_Delap);
            Serial.print("Last message received: ");
            Serial.println(wd_Dside);
            digitalWrite(4, LOW);    // устанавливаем на выводе 4 низкий уровень
            Serial.println("D side didn't hear from a client in 60s; 
                           defaulting to OFF.");
          } 
          
    if (wd_Celap>=60000)
          {
            Serial.print("Elapsed time on watchdog, C side: ");
            Serial.println(wd_Celap);
            Serial.print("Last message recieved: ");
            Serial.println(wd_Cside);
            digitalWrite(5, LOW);    // устанавливаем на выводе 5 низкий уровень
            Serial.println("C side didn't hear from a client in 60s; 
                            defaulting to OFF.");
          } 
     
   } 
}
            

Ранее у меня это компилировалось и запускалось, хотя и с проблемами, которые я намеревался итеративно устранять. Теперь он не будет компилироваться из-за следующей ошибки:

arduino:302:37: ошибка: неверное преобразование из 'char' в 'const char*' [-fpermissive]

strcat(inputs[i], newChar); // Добавляем символ в полученную строку

.. который я попытался выделить жирным шрифтом выше в последнем предложении else. Я понимаю, что для этих параметров требуются указатели, но похоже, что некоторые другие функции, такие как strtok и strlen, которые также запрашивают указатели, работают нормально в моем коде.

Есть ли какие-либо предложения или альтернативы strcat() относительно того, как я могу заставить это работать? Я в основном придерживался массивов символов вместо объявления объектов String. Я также, очевидно, довольно ржавый в C (++), так как я не работал с ним активно какое-то время.

Спасибо

, 👍0


1 ответ


Лучший ответ:

1

strcat — это функция для объединения строк. Он ожидает массив символов в качестве второго параметра. У вас есть только один символ newChar для добавления к вашей строке.

size_t l = strlen(inputs[i]);  
inputs[i][l] = newChar;    
inputs[i][l + 1] = 0;

Примечание. Было бы лучше отслеживать длину input, а затем использовать strlen. strlen перебирает массив, пока не завершится нулем.

,

Спасибо. Я думаю, это сработает. Вопрос, нужна ли третья строчка? Разве это не добавило бы символ «0» в конце, или вы говорите, что это символ для завершения, который, как я думал, был «\ 0», @user8585939

следующий strlen не будет работать без завершающего нуля. ascii-код '\0' равен 0. некоторые используют NULL, который тоже равен 0, @Juraj