2017-09-28 182 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)'也在那裏。 –

相關問題