2017-09-28 134 views
0

我试图用字符串结构填充数组时遇到了问题。可能,我在Arduino上使用指针或内存分配规则时缺少一些基本的东西。Arduino - 处理一系列结构的正确方法是什么?

看到我的代码如下。

数据结构将被填充:

struct SMSData { 
    String id; 
    String status; 
    String from; 
    String date; 
    String text; 
}; 

串分析器例程:

SMSData* readSMS(String reply) { 
    debugSerial.println(reply); 

    // declare a pointer to result array 
    SMSData* smsArray = NULL; 

    const String startPattern = F("+CMGL: "); 

    int index = -1; 

    // calculate result array length 
    byte count = 0; 
    do { 
    index = reply.indexOf(startPattern, (index + 1)); 

    if(index < 0) { 
     break; 
    } 

    count++; 
    } while(true); 

    if(count == 0) { 
    return NULL; 
    } 

    debugSerial.println(count); 

    // allocate memory to store result array 
    smsArray = malloc(count * sizeof(SMSData*)); 

    if(smsArray == NULL) { 
    return NULL; 
    } 

    // start parsing input String 
    index = reply.indexOf(startPattern); 

    int fromIndex = 0; 
    while(true) { 
    debugSerial.println(); 

    if(index < 0) { 
     break; 
    } 

    // init data for the next element of result array 
    SMSData smsData = {"", "", "", "", ""}; 

    // start filling result array element 
    // get id 
    fromIndex = index + startPattern.length(); 
    index = reply.indexOf(F(","), fromIndex); 
    smsData.id = reply.substring(fromIndex, index); 

    debugSerial.println(smsData.id); 

    // get status 
    fromIndex = reply.indexOf(F("\""), index) + 1; 
    index = reply.indexOf(F("\""), fromIndex); 
    smsData.status = reply.substring(fromIndex, index); 

    debugSerial.println(smsData.status); 

    // get phone 
    fromIndex = reply.indexOf(F("\""), index + 1) + 1; 
    index = reply.indexOf(F("\""), fromIndex); 
    smsData.from = reply.substring(fromIndex, index);  

    debugSerial.println(smsData.from); 

    // get date 
    fromIndex = reply.indexOf(F("\""), index + 1) + 1; 
    index = reply.indexOf(F("\""), fromIndex); 
    smsData.date = reply.substring(fromIndex, index); 

    debugSerial.println(smsData.date); 

    // get text 
    fromIndex = index + 1; 
    index = reply.indexOf(startPattern, fromIndex); 

    if(index < 0) { 
     smsData.text = reply.substring(fromIndex); 
    } else { 
     smsData.text = reply.substring(fromIndex, index); 
    } 

    smsData.text.trim(); 
    debugSerial.println(smsData.text); 

    // add filled element to result array 
    smsArray[count - 1] = smsData; 
    } 

    return smsArray; 
} 

输出解析的数据:

SMSData* smsArray = readSMS(reply); 

int count = sizeof(smsArray); 

debugSerial.print(F("SMS count:")); 
debugSerial.println(count); 

for(int i = 0; i < count; i++) { 
    SMSData smsData = smsArray[i]; 

    debugSerial.print(F("id: ")); 
    debugSerial.println(smsData.id); 
    debugSerial.print(F("status: ")); 
    debugSerial.println(smsData.status); 
    debugSerial.print(F("from: ")); 
    debugSerial.println(smsData.from); 
    debugSerial.print(F("date: ")); 
    debugSerial.println(smsData.date); 
    debugSerial.print(F("text: ")); 
    debugSerial.println(smsData.text); 
} 

free(smsArray); 

假人字符串解析:

String reply = "+CMGL: 1,\"REC READ\",\"+123456789012\",,\"2017/09/26,18:31:25+03\"\r\nHi\r\n+CMGL: 2,\"REC READ\",\"+123456789012\",,\"2017/09/26,18:34:25+03\"\r\nHello\r\n"; 

当我运行草图时,它的输出通常会有所不同,但始终是不完整的,例如

+CMGL: 1,"REC READ","+123456789012",,"2017/09/26,18:31:25+03" 
Hi 
+CMGL: 2,"REC READ","+123456789012",,"2017/09/26,18:34:25+03" 
Hello 

2 

1 
REC READ 
+12345678905+03 017/09/26,18:31:25+03 
Hi 

2 
REC REA 

正如你可以根据输出看,它记录了整个输入串,开始分析它,穿过第一循环迭代(混合从结构字段的字符串),开始第二次迭代填充结构与重混合字符串再次,然后在中间停止响应。

现在我没有看到这种行为的原因,除了内存分配的问题,但我找不到我做错了什么。

任何您的帮助表示赞赏。

+0

什么是(定义)'String'和'F(...)'? – Yunnosch

+0

@Yunnosch String是标准的Arduino数据类型(描述 - https://www.arduino.cc/en/Reference/StringObject,source - https:// github。com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/WString.h),F是用于在闪存中存储字符串值的宏(请参阅define的相同头文件)。 –

+0

'reply'是一个String变量,请参阅我的帖子中的声明和初始化。 –

回答

0

首先,你的代码是C++,不是严格的c,没关系,但标签应该改变。这里有一些问题,我在你的代码中发现...

///// Passing nothing, println requires one or two parameters 
    debugSerial.println(); 

看看我们使用以C风格的指针作为数组使用documentation on println

// init data for the next element of result array 
    ////// You are creating a local buffer, it will go out of scope 
    ////// when you leave the function. And you are trying to store 
    ////// it in an array that you return from your function. 
    ////// And you are changing the data with pass through your loop 
    ////// (2 passes). 
    SMSData smsData = {"", "", "", "", ""}; 

    //... 
    ////// You should be assigning an allocated struct pointer 
    ////// count is not changing, you are only assigning the last 
    ////// element of the array. 
    smsArray[count - 1] = smsData; 


///// This will not work. smsArray is a pointer and you have lost 
///// the information about how much memory was allocated and assigned to 
///// the pointer. 
SMSData* smsArray = readSMS(reply); 
int count = sizeof(smsArray); 

一个窍门,就是分配指针一个更大的块比我们需要的,并确保他们都设置为NULL(使用calloc()而不是malloc())。然后,我们将在数组中设置eacch指针,除了最后一个。最后,我们遍历数组,直到指针为NULL,表示数据结束。

你应该在你的smsArray中存储指向已分配数据的指针,并且你应该释放(销毁)该数据以及数组。

所以,你的代码可能看起来像......

SMSData** smsArray = NULL; 
smsArray = (SMSData **)calloc(count+1, sizeof(SMSData *)); 
int idx = 0; 
//... 

    SMSData* smsData = new smsData(); 
    smsData->id = ""; //etc. for the rest of the fields 
    //... 

    smsArray[idx++] = smsData; 
    //.. 

回来后...

SMSData ** smsArray = readSMS(reply); 
SMSData ** ptr = smsArray; 
while (ptr != NULL) { 
    //do stuff with ptr->whatever 
    destroy(ptr); //destroy since allocated with new 
    ptr++; 
} 
free(smsArray); //free since allocated with malloc 

这是不是最好的代码(可能有错误,我不知道现在可以访问我的编译器)。但它试图坚持你的方法。

+0

我明白了 - 应该1)使用指针数组,2)在每个循环中分配一个新的结构体。并谈论'Serial.println' - 我现在找不到它的源代码,但是......即使没有任何参数传递,它也可以工作。 –

+0

println可能没问题,但我在我的答案中包含了文档链接,它显示了一个或两个参数。编译可能会用NULL结束参数,所以它“恰好如此”工作 – Les

+0

Arduino文档是非常基本的,你可能会同意。我刚刚在https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/Print.h找到了声明 - 'size_t println(void)'也在那里。 –

相关问题