存储的结构体成员数据通过字符数组指针返回垃圾值



我正在尝试使用MySQL_Connection.h在OLED LCD上显示我的数据库数据,并通过ChuckBellMySQL_Cursor.h

此库的链接 https://github.com/ChuckBell/MySQL_Connector_Arduino>

我能够成功地从mysql database获取数据。但是,我希望将数据存储在字符数组中,以便以后可以在OLED LCD上显示它们。问题是存储的值始终返回垃圾值。我知道它与字符数组指针有关,但是搜索了这么长时间后,我仍然找不到正确的语法。下面是我的代码片段。

首先设置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 resultsn");
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);
}

输出如下所示 单击此处或查看下方。如您所见,这些值在do while循环中正确显示(除了布尔类型的第 8 个,我稍后会更改它(。但是,当我退出循环并再次打印值时,它会返回垃圾值sqldata[0]假设返回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平底锅给出的建议,我能够自己找到解决方案。他们为我提供了寻找解决方案的方向。 通过编辑如下所示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中的类型传递长度:intchar不同......

最新更新