【问题标题】:Stored struct member data via char array pointer return garbage value通过 char 数组指针存储的结构成员数据返回垃圾值
【发布时间】:2018-08-23 09:21:31
【问题描述】:

我正在尝试使用MySQL_Connection.hMySQL_Cursor.h 通过ChuckBell 在OLED LCD 上显示我的database data

这个库的链接是https://github.com/ChuckBell/MySQL_Connector_Arduino>

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

首先设置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,我稍后会更改它)。但是,当我退出循环并再次打印该值时,它会返回垃圾值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

⸮

下面的代码sn-p显示了MySQL_Cursor.h中的struct声明

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-&gt;values[f]; 导致垃圾值。由于指针仅指向该地址,该值将发生变化。如何静态存储变量,以便在do while 之后,该值将保持不变? 请好心的先生和女士们解释这个谜团。

PS:我对数组和指针感到困惑,当它们涉及结构时更是如此。

【问题讨论】:

  • 试试把“char* sqldata[11]”改成“static char* sqldata[11]”看看。
  • 可能row = cur_mem-&gt;get_next_row(); 使之前的row = cur_mem-&gt;get_next_row(); 填充的内存无效。不要复制指针,而是复制字符串。
  • @user846834 不起作用 =( 仍然返回垃圾值。
  • @Jabberwocky 感谢您的建议。经过长时间的搜索,我终于能够存储字符串而不是指针。稍后将更新解决方案。感谢您的帮助!
  • 不要在问题中加入答案,也不要在标题中加入“[SOLVE]”。此网站不是论坛。

标签: mysql c pointers struct arduino-esp8266


【解决方案1】:

解释是内存在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

【讨论】:

  • 感谢您指出 free_row_buffer。猜猜我必须在调用 free_row_buffer() 之前弄清楚如何存储这些值。无论如何感谢您的帮助!
【解决方案2】:

感谢@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-&gt;values[f];替换为strcpy(sqldata[f], (*row).values[f]);

现在一切正常。是时候在 OLED LCD 上打印这些废话了。 再次感谢各位!

【讨论】:

    【解决方案3】:

    @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 不同...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-07
      • 1970-01-01
      • 2022-12-12
      • 1970-01-01
      相关资源
      最近更新 更多