将单个字符附加到 char 数组并返回 char 数组

Appending individual characters to char array and returning the char array

我的 Arduino 程序中的字符和字符数组再​​次遇到很多困难。我将 ESP32 设备与 SPIFFS 一起使用,我在其中保存了一些我想保存到我的 ESP32 设备中的数据。在我的 SPIFFS 中,我有一个 wifi.txt 文件,我在其中保存 wifi 名称。然后我调用函数:

char* saved_networks; // create char array to save information from readfile
saved_networks = readFile(SPIFFS, "/wifi.txt");

readFile 函数描述如下:

char* readFile(fs::FS &fs, const char *path)
{
    char* return_message; //create a variable return_message to hold the appended char data
    Serial.printf("Reading file: %s\n", path);

    File file = fs.open(path);
    if (!file || file.isDirectory())
    {
        Serial.println("Failed to open file for reading");
        return "FAIL";
    }

    Serial.print("Read from file: ");
    while (file.available())
    {
        //Serial.write(file.read());
        char c =  file.read(); // save one character at a time and save it to a temporaray variable c
        delayMicroseconds(100);
        Serial.print(c); // this prints the wifi name as expected so everything is working ok up to this point
        strcat(return_message, &c); // append char array (return_message)

    }
    Serial.print("printing final return message before closing file system=");
    Serial.println(return_message); //prints loads of garbage
    file.close();
    return return_message;
}

打印 return_message 后,ESP32 设备崩溃并 returns 一条错误消息:

Reading file: /wifi.txt
Read from file: Telia-33F8A3-Greitas
printing final return message before closing file sysetm=x⸮?⸮⸮?⸮⸮?T⸮    @?e⸮    @?l⸮    @?i⸮    @?a⸮    @?-⸮    @?3⸮    @?3⸮    @?F⸮    @?8⸮    @?A⸮    @?3⸮    @?-⸮    @?G⸮    @?r⸮    @?e⸮    @?i⸮    @?t⸮    @?a⸮


Stack smashing protect failure!

abort() was called at PC 0x401377bf on core 1

ELF file SHA256: 0000000000000000

Backtrace: 0x40088740:0x3ffb1480 0x400889bd:0x3ffb14a0 0x401377bf:0x3ffb14c0 0x400d1685:0x3ffb14e0 0x400d1872:0x3ffb1590 0x400d18b3:0x3ffb1f80 0x400d4cfe:0x3ffb1fb0 0x400899ce:0x3ffb1fd0

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4

非常感谢任何帮助。

更新1

通过引用将 char 数组传递给 void 函数时是否也一样?:

如果我声明我的 readFile 函数如下:

void readFile(fs::FS &fs, const char *path, char* return_data)
{
    Serial.printf("Reading file: %s\n", path);

    File file = fs.open(path);
    if (!file || file.isDirectory())
    {
        Serial.println("Failed to open file for reading");
        return;
    }

    Serial.print("Read from file: ");
    while (file.available())
    {
        //Serial.write(file.read());
        char c =  file.read();
        delayMicroseconds(100);
        Serial.print(c);
// Do I also must have allocated memory in order to append characters to my return_data char array

    }
    Serial.print("printing final return message before closing file sysetm=");
    Serial.println(return_data);
    file.close();

}

然后在我的 main 中,我调用:

    char* saved_networks = NULL; // create char array to save information from readfile
    readFile(SPIFFS, "/wifi.txt",&saved_networks[0]);

更新2

我通过传递一个 char 数组作为参考设法做到了这一点。此方法不需要malloc,也不需要free。

void readFile123(fs::FS &fs, const char *path, char* return_data)
{
   
    int n=0;
    Serial.printf("Reading file: %s\n", path);

    File file = fs.open(path);
    if (!file || file.isDirectory())
    {
        Serial.println("Failed to open file for reading");
        return;
    }
    Serial.print("Read from file: ");
    while (file.available())
    {
        char c =  file.read();
        delayMicroseconds(100);
        Serial.print(c);
        //strcat(return_data, &c); //returns meditation error
        return_data[n]=c; //returns meditation error
        n=n+1;
    }
    file.close();

}

和主要代码:

    char saved_networks[100];
    readFile123(SPIFFS, "/wifi.txt",saved_networks);
    Serial.print("saved networks=");
    Serial.println(saved_networks);

这种实现方式对我来说更有意义。如果我可以通过引用传递数组,为什么还要使用 malloc?这样实现起来更简单。

不过,我还有一个顾虑。从上面的代码中可以看出,我已将 char 数组的最大长度初始化为 100,但是,我不确定我的 SPIFFS 内容的大小是多少。有什么办法可以克服这个问题吗?我知道我可以声明大小,例如 10000,并希望内容永远不会变得那么大,但这似乎不是解决此问题的最有效方法。我希望有人可以对此发表评论。提前致谢。

此处将 c 附加到未初始化的指针:

strcat(return_message, &c); // append char array (return_message)

由于 return_message 未初始化,这将调用未定义的行为,因为 stract 需要一个 0 终止的 C 字符串。所以你必须为消息分配内存,并用 0-byte.

终止它

您必须分配内存才能附加它。

char* return_message = nullptr;
size_t message_len = 0;
...
while (file.available())
{
    //Serial.write(file.read());
    char c =  file.read(); // save one character at a time and save it to a temporaray variable c
    delayMicroseconds(100);
    Serial.print(c); // this prints the wifi name as expected so everything is working ok up to this point

    return_message = realloc(return_message, len+1);
    return_message[len++] = c;
}
return_message = realloc(return_message, len+1);
return_message[len++] = 0;

或者如果您知道预期消息的大小:

size_t max_message = 100;
char* return_message = malloc(max_message);
size_t message_len = 0;
*return_message = 0;
...
while (file.available())
{
    //Serial.write(file.read());
    char c =  file.read(); // save one character at a time and save it to a temporaray variable c
    delayMicroseconds(100);
    Serial.print(c); // this prints the wifi name as expected so everything is working ok up to this point

    return_message[len++] = c;
    if (len == max_message-1)
        break;
}
return_message[len++] = 0;

您也不应该 return 带有非常量指针的字符串文字:

if (!file || file.isDirectory())
{
    Serial.println("Failed to open file for reading");
    free(return_message);
    return strdup("FAIL");
}

此函数的调用者必须 free returned 字符串,当它完成时,否则会造成内存泄漏。