Arrays 将单个字符追加到字符数组并返回字符数组

Arrays 将单个字符追加到字符数组并返回字符数组,arrays,c,character-encoding,character,esp32,Arrays,C,Character Encoding,Character,Esp32,在我的Arduino程序中,我再一次在字符和字符数组方面遇到了很多困难。我使用带有SPIFFS的ESP32设备,在这里我保存了一些我想保存到ESP32设备中的数据。在我的SPIFFS中,我有一个wifi.txt文件,其中保存了wifi名称。然后调用函数: char* saved_networks; // create char array to save information from readfile saved_networks = readFile(SPIFFS, "/wifi

在我的Arduino程序中,我再一次在字符和字符数组方面遇到了很多困难。我使用带有SPIFFS的ESP32设备,在这里我保存了一些我想保存到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;
}
打印返回消息后,ESP32设备崩溃并返回错误消息:

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();

}
然后在我的主要发言中,我呼吁:

    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\u message
未初始化,这将调用未定义的行为,因为
stract
需要以0结尾的C字符串。因此,您必须为消息分配内存,并使用
0字节的
终止消息

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

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;
还不应返回带有非常量指针的字符串文字:

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

此函数的调用方必须
释放返回的字符串,否则会造成内存泄漏。

谢谢。你能解释一下这个代码的用途吗:
return\u message=realloc(return\u message,len+1)
还有,如果不是创建一个char指针返回消息,而是创建一个char返回消息[100],那情况还会一样吗。然后我会创建一个最大大小为100的字符数组,也许我可以避免使用分配?如果您知道消息的大小或将其限制为已知值,那么它比像我一样使用
realloc
更有效,这是一种幼稚的方法,但没有那么有效。是的,这确实有效。。请你解释一下我最初尝试的方式到底有什么问题,以及为什么我们需要手动分配内存。我是否也必须在函数结束时释放内存?如果我释放内存,我将无法返回字符串,是吗?我用其他信息更新了答案。