通过 char 数组指针 return 垃圾值存储结构成员数据
Stored struct member data via char array pointer return garbage value
我正在尝试通过 ChuckBell
使用 MySQL_Connection.h
和 MySQL_Cursor.h
在 OLED LCD 上显示我的 database data。
这个库的 link 是 https://github.com/ChuckBell/MySQL_Connector_Arduino>
我能够从 mysql database
成功获取数据。但是,我希望将数据存储在一个字符数组中,以便稍后可以在 OLED LCD 上显示它们。问题是存储的值总是 returns 垃圾值。我知道它与 char 数组指针有关,但在搜索了这么久之后,我仍然找不到正确的语法。下面是我的代码片段。
首先设置 Wifi 连接和 mysql 连接。
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>
char query[] = "SELECT * FROM test.assetdemo WHERE RFID = \"048EB25A\""; //sql query
char* sqldata[11]; //array of char pointer to store the 11 data in the database
void setup(){
Serial.begin(115200);
internetConnect(ssid,pw); //connect to Wifi
conn.connect(server_addr, 3306, user, password); //connect to mysqldatabase
}
然后开始循环函数存储和显示数据库数据。
void loop(){
Serial.println("\nRunning SELECT and printing results\n");
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn); // Initiate the query class instance
cur_mem->execute(query); // Execute the query
row_values *row = NULL; // Read the rows and print them
do {
row = cur_mem->get_next_row();
if (row != NULL) {
for (int f = 0; f < cols->num_fields; f++) {
sqldata[f] = row->values[f];
Serial.print(f);
Serial.print(" ");
Serial.println(sqldata[f]); /*This works*/
}
Serial.println();
}
} while (row != NULL);
Serial.println(sqldata[0]); /*This return garbage value*/
delete cur_mem; // frees up memory used
delay(5000);
}
输出结果如下Click here or view below。如您所见,值在 do while
循环中正确显示(除了 8th 是布尔类型,我稍后会更改它)。但是,当我退出循环并再次打印该值时,它 return 是垃圾值 ⸮
。 sqldata[0]
假设为 return 048EB25A
.
Running SELECT and printing results
0 048EB25A
1 Blood Pressure Monitor
2 NA
3 WelchAllyn 503-0054-03
4 010720
5 NA
6 NA
7 Blood Pressure Cuff
8
9 Yes
10 1
⸮
下面的代码片段显示了 MySQL_Cursor.h
中的结构声明
typedef struct {
char *db;
char *table;
char *name;
} field_struct;
// Structure for storing result set metadata.
typedef struct {
int num_fields; // actual number of fields
field_struct *fields[MAX_FIELDS];
} column_names;
// Structure for storing row data.
typedef struct {
char *values[MAX_FIELDS];
} row_values;
我的一部分知道 sqldata[f] = row->values[f];
导致了垃圾值。由于指针仅指向地址,因此该值将发生变化。如何静态存储变量,以便在 do while
之后,该值将持续存在?
好心的先生女士们请解开这个谜团。
PS: 我对数组和指针感到困惑,当它们涉及结构时更是如此。
解释是get_next_row函数https://github.com/ChuckBell/MySQL_Connector_Arduino/blob/master/src/MySQL_Cursor.cpp
里面释放了内存
/*
get_next_row - Iterator for reading rows from a result set
This method returns an instance of a structure (row_values)
that contains an array of strings representing the row
values returned from the server.
The caller can use the values however needed - by first
converting them to a specific type or as a string.
*/
row_values *MySQL_Cursor::get_next_row() {
int res = 0;
free_row_buffer();
// Read the rows
res = get_row_values();
if (res != MYSQL_EOF_PACKET) {
return &row;
}
return NULL;
}
第二次尝试获取行 free_row_buffer 被调用。
感谢@Jabberwocky 和@rantan pan 的建议,我自己找到了解决方案。他们为我提供了在哪里寻找解决方案的方向。
通过如下所示编辑 sqldata
,我能够将字符串而不是指针存储到 sqldata 中。
如下所示重新声明 sqldata。
char **sqldata = new char*[11]; //to store 11 data for each query executed
for ( int i = 0; i < 11; i++ )
{
sqldata[i] = new char[11];
}
然后将sqldata[f] = row->values[f];
替换为strcpy(sqldata[f], (*row).values[f]);
现在一切正常。是时候在 OLED LCD 上打印这些废话了。
再次感谢大家!
@TK Ooi 的解决方案还可以,但作为对其的改进,我会更安全地使用我们要存储数据的数组的大小,因此可以代替使用
int numberRows = 11;
char **sqldata = new char*[numberRows];
for(int i = 0; i < numberRows; i++ ) {
sqldata[i] = new char[numberChars];
}
strcpy(sqldata[f], (*row).values[f]);`
最好将 char* 数组声明为全局数组,但在查询函数中执行以下操作:
int numberChars = strlen((*row).values[f]);
sqldata[f] = new char[numberChars]; // implies already extra place for null terminator
snprintf(sqldata[f], strlen(sqldata[f]), "%s", (*row).values[f]);`
这样,我们总是为我们的数组分配准确的长度来存储恢复的数据。请注意,使用 numberChars
而不是 strlen(sqldata[f])
将失败,因为您需要根据存储在 sqldata
中的类型传递长度:int
与 char
...
我正在尝试通过 ChuckBell
使用 MySQL_Connection.h
和 MySQL_Cursor.h
在 OLED LCD 上显示我的 database data。
这个库的 link 是 https://github.com/ChuckBell/MySQL_Connector_Arduino>
我能够从 mysql database
成功获取数据。但是,我希望将数据存储在一个字符数组中,以便稍后可以在 OLED LCD 上显示它们。问题是存储的值总是 returns 垃圾值。我知道它与 char 数组指针有关,但在搜索了这么久之后,我仍然找不到正确的语法。下面是我的代码片段。
首先设置 Wifi 连接和 mysql 连接。
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>
char query[] = "SELECT * FROM test.assetdemo WHERE RFID = \"048EB25A\""; //sql query
char* sqldata[11]; //array of char pointer to store the 11 data in the database
void setup(){
Serial.begin(115200);
internetConnect(ssid,pw); //connect to Wifi
conn.connect(server_addr, 3306, user, password); //connect to mysqldatabase
}
然后开始循环函数存储和显示数据库数据。
void loop(){
Serial.println("\nRunning SELECT and printing results\n");
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn); // Initiate the query class instance
cur_mem->execute(query); // Execute the query
row_values *row = NULL; // Read the rows and print them
do {
row = cur_mem->get_next_row();
if (row != NULL) {
for (int f = 0; f < cols->num_fields; f++) {
sqldata[f] = row->values[f];
Serial.print(f);
Serial.print(" ");
Serial.println(sqldata[f]); /*This works*/
}
Serial.println();
}
} while (row != NULL);
Serial.println(sqldata[0]); /*This return garbage value*/
delete cur_mem; // frees up memory used
delay(5000);
}
输出结果如下Click here or view below。如您所见,值在 do while
循环中正确显示(除了 8th 是布尔类型,我稍后会更改它)。但是,当我退出循环并再次打印该值时,它 return 是垃圾值 ⸮
。 sqldata[0]
假设为 return 048EB25A
.
Running SELECT and printing results
0 048EB25A
1 Blood Pressure Monitor
2 NA
3 WelchAllyn 503-0054-03
4 010720
5 NA
6 NA
7 Blood Pressure Cuff
8
9 Yes
10 1
⸮
下面的代码片段显示了 MySQL_Cursor.h
typedef struct {
char *db;
char *table;
char *name;
} field_struct;
// Structure for storing result set metadata.
typedef struct {
int num_fields; // actual number of fields
field_struct *fields[MAX_FIELDS];
} column_names;
// Structure for storing row data.
typedef struct {
char *values[MAX_FIELDS];
} row_values;
我的一部分知道 sqldata[f] = row->values[f];
导致了垃圾值。由于指针仅指向地址,因此该值将发生变化。如何静态存储变量,以便在 do while
之后,该值将持续存在?
好心的先生女士们请解开这个谜团。
PS: 我对数组和指针感到困惑,当它们涉及结构时更是如此。
解释是get_next_row函数https://github.com/ChuckBell/MySQL_Connector_Arduino/blob/master/src/MySQL_Cursor.cpp
里面释放了内存/*
get_next_row - Iterator for reading rows from a result set
This method returns an instance of a structure (row_values)
that contains an array of strings representing the row
values returned from the server.
The caller can use the values however needed - by first
converting them to a specific type or as a string.
*/
row_values *MySQL_Cursor::get_next_row() {
int res = 0;
free_row_buffer();
// Read the rows
res = get_row_values();
if (res != MYSQL_EOF_PACKET) {
return &row;
}
return NULL;
}
第二次尝试获取行 free_row_buffer 被调用。
感谢@Jabberwocky 和@rantan pan 的建议,我自己找到了解决方案。他们为我提供了在哪里寻找解决方案的方向。
通过如下所示编辑 sqldata
,我能够将字符串而不是指针存储到 sqldata 中。
如下所示重新声明 sqldata。
char **sqldata = new char*[11]; //to store 11 data for each query executed
for ( int i = 0; i < 11; i++ )
{
sqldata[i] = new char[11];
}
然后将sqldata[f] = row->values[f];
替换为strcpy(sqldata[f], (*row).values[f]);
现在一切正常。是时候在 OLED LCD 上打印这些废话了。 再次感谢大家!
@TK Ooi 的解决方案还可以,但作为对其的改进,我会更安全地使用我们要存储数据的数组的大小,因此可以代替使用
int numberRows = 11;
char **sqldata = new char*[numberRows];
for(int i = 0; i < numberRows; i++ ) {
sqldata[i] = new char[numberChars];
}
strcpy(sqldata[f], (*row).values[f]);`
最好将 char* 数组声明为全局数组,但在查询函数中执行以下操作:
int numberChars = strlen((*row).values[f]);
sqldata[f] = new char[numberChars]; // implies already extra place for null terminator
snprintf(sqldata[f], strlen(sqldata[f]), "%s", (*row).values[f]);`
这样,我们总是为我们的数组分配准确的长度来存储恢复的数据。请注意,使用 numberChars
而不是 strlen(sqldata[f])
将失败,因为您需要根据存储在 sqldata
中的类型传递长度:int
与 char
...