c-将单个字符追加到char数组并返回char数组



我的Arduino程序中的字符和字符数组再次遇到了很多困难。我使用带有SPIFFS的ESP32设备,在那里我保存了一些数据,我想保存到我的ESP 32设备中。在我的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: %sn", 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设备崩溃并返回错误消息:

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: %sn", 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: %sn", 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;

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

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

此函数的调用方必须在使用完返回的字符串后free,否则会造成内存泄漏。

最新更新