Arduino копирует строку в символ * и использует внешнюю функцию

#c #string #arduino #char

Вопрос:

Я разрабатываю программу с микроконтроллером ESP32 WIFI, в которой мне нужно сканировать доступные близлежащие сети Wi-Fi и сохранять их в списке, чтобы я мог использовать их позже вне функции. Поначалу мне удавалось все легко делать с помощью переменной типа String, но я слышу много плохих слов об использовании String в Arduino, поэтому теперь я пытаюсь все делать с помощью char*, что я нахожу немного более сложным, чем String.

Я нашел статью, в которой описывается, как преобразовать строку в массив символов: https://circuits4you.com/2018/03/08/arduino-convert-string-to-character-array/

 // Define 
String str = "This is my string"; 

// Length (with one extra character for the null terminator)
int str_len = str.length()   1; 

// Prepare the character array (the buffer) 
char char_array[str_len];

// Copy it over 
str.toCharArray(char_array, str_len);
 

В моем коде:
Я инициализирую массив символов глобальной переменной, в котором хочу хранить свою информацию.

 char* list_strings[10];
 

Затем я вызываю функцию для сканирования сетей:

 int scan_wifi_networks(){

  Serial.println("scan start");
    // WiFi.scanNetworks will return the number of networks found
    int n = WiFi.scanNetworks();
    Serial.println("scan done");
    if (n == 0) {
        Serial.println("no networks found");
    } else {
        Serial.print(n);
        Serial.println(" networks found");
        for (int i = 0; i < n;   i) {
            
            int str_len = WiFi.SSID(i).length()   1;  // this is to know the the length of the string  1
            char temp_buffer[str_len]; // create a temporary storage to copy the string to char array
            WiFi.SSID(i).toCharArray(temp_buffer, str_len); // converts string to char array 
            Serial.print("temp buffer is set to=");
            Serial.println(temp_buffer);
            list_strings[i] = temp_buffer;
        }
    }
    Serial.print("list of strings inside scanning function");
    for(int i=0 ; i<=n ; i  ){
      Serial.println(list_strings[i]); // prints a lot of garbage??
    }
    return n;
}
 

Функция выше будет сканировать сети и, как предполагается, преобразует строковую переменную (WiFi.SSID) в массив символов, который я затем сохраняю в своем списке:

 list_strings[i] = temp_buffer;
 

Мой последовательный монитор :
изображение последовательного монитора

Он может правильно распечатать имена Wi-Fi в цикле for, но как только он выходит из цикла for, он печатает какой-то мусор.

Буду признателен за любую помощь

UPDATE1

I am trying to print the address of temp_buffer:

 char temp_buffer[str_len]; // create a temporary storage to copy the string to char array
int ptr =  amp;temp_buffer;
Serial.print("Pointer :" );
Serial.println(ptr);
 

Но безрезультатно. Я получаю недопустимое преобразование из символа* в ошибку int

ОБНОВЛЕНИЕ 2

Я привел свой temp_buffer к int, и он компилируется, однако я не знаю, правильно это или нет.

             char temp_buffer[str_len]; // create a temporary storage to copy the string to char array
            int ptr =  (int)amp;temp_buffer;
            Serial.print("Pointer :" );
            Serial.println(ptr);
 

Последовательный монитор:

 Pointer :1073422080
temp buffer is set to=Telia-33F8A3-Greitas
Pointer :1073422080
temp buffer is set to=HUAWEI-STOLYARCHUK
Pointer :1073422080
temp buffer is set to=Telia-E619A5-Greitas
Pointer :1073422080
temp buffer is set to=Telia-ED7E29-Greitas
Pointer :1073422096
temp buffer is set to=MEZON_1156F3
Pointer :1073422080
temp buffer is set to=Carolyne’s iPhone
Pointer :1073422080
temp buffer is set to=Teo-E6A379-Greitasis
Pointer :1073422096
temp buffer is set to=HH40V_BE2F
Pointer :1073422096
temp buffer is set to=Fishman
Pointer :1073422096
temp buffer is set to=MEZON_9EE8
Pointer :1073422096
temp buffer is set to=4G-Gateway-4981
Pointer :1073422080
temp buffer is set to=HUAWEI-B525-C466
Pointer :1073422096
temp buffer is set to=DGD
Pointer :1073422096
temp buffer is set to=4G-Gateway-D29C
Pointer :1073422096
temp buffer is set to=WIFI 2021
Pointer :1073422080
temp buffer is set to=Telia-E79C95-Greitas
Pointer :1073422080
temp buffer is set to=Telia-E5E1B9-Greitas
Pointer :1073422096
temp buffer is set to=#Telia-1E6E7A
list of strings inside scanning function

 

По какой-то странной причине указатель время от времени меняется с 1073422080 на 1073422096

Комментарии:

1. Где вы хотите хранить строку?

2. Я хочу сохранить информацию в глобальной переменной, которую я создаю : char* list_strings[10];

3. однако это всего лишь набор указателей. В нем хранятся только указатели на другие переменные. Какая другая переменная должна содержать строку?

4. Извините, я не совсем понимаю, что вы имеете в виду 🙁 Вы спрашиваете о временной переменной, в которой я храню строку, прежде чем скопировать ее в свой массив?

5. char* list_strings[10]; не могу держать никаких ниточек. Он может содержать только указатели на строки.

Ответ №1:

Проблема char temp_buffer[str_len]; в том . Это выделяет память в стеке (почти наверняка один и тот же бит памяти на каждой итерации цикла for. Я удивлен, что это скомпилировано, так как я ожидал бы получить сообщение об ошибке с жалобой на то, что str_len не является константой. В любом случае вы сохраняете адрес области стека, которая будет доступна для повторного использования на каждой итерации, а также после выхода из цикла. Возможно, было бы полезно печатать адрес temp_buffer на каждой итерации.

Вместо этого вы могли бы выделить память в куче с помощью new() и не забыть освободить ее с помощью delete (), когда закончите.

Еще лучше было бы использовать строки и векторы из STL.

Комментарии:

1. Спасибо за ответ. К сожалению, печать адреса tempo_buffer в среде IDE Arduino не так проста, как хотелось бы. Я не могу заставить его работать. У вас есть какие-либо идеи, как я могу распечатать адрес моего temp_buffer? Я займусь маллоком, так как у меня нет опыта работы с ним. И кроме того, я никогда не слышал о STL

2. Я обновил свой первоначальный вопрос UPDATE1. Я разместил там какой-то код. Я не знаю, как разместить код в комментарии.

3. Дело в том, что вы копируете строки в temp_buffer, который является локальной переменной, адресующей область в стеке, которая выйдет за рамки в конце каждой итерации цикла. Вы перезаписываете почти одну и ту же область стека на каждой итерации, а затем сохраняете этот адрес в list_strings[]. К тому времени, когда вы посмотрите на list_strings [], этот кусок стека, вероятно, используется для чего-то другого. Даже если бы он еще не был использован повторно, он содержал бы только последнее, что вы написали в нем. Я думаю, вам нужно немного почитать об управлении памятью на C/C

4. Игнорируйте ссылку на malloc(), я должен был сказать new()

5. Хорошо, я понимаю, но как тогда эта проблема решается с помощью strcpy вместо = ? Чем это отличается от других?