将单个字符附加到 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 字符串,当它完成时,否则会造成内存泄漏。
我的 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 字符串,当它完成时,否则会造成内存泄漏。