我在尝试用字符串结构填充数组时遇到了问题。可能,我在Arduino上使用指针或内存分配规则时遗漏了一些基本内容。
请参阅下面的代码。
要填充的数据结构:
Test
字符串解析器例程:
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";
正如您可以根据输出看到的,它会记录整个输入字符串,开始解析它,经历第一次循环迭代(混合来自struct字段的字符串),再次启动第二次迭代填充结构,重复混合字符串然后在中间停止响应。
现在除了内存分配问题外我没有理由看到这样的行为,但是我找不到我做错了什么。
感谢您的任何帮助。
答案 0 :(得分:0)
首先,您的代码是c ++,而不是严格的c,这没关系,但标签应该更改。以下是我在代码中发现的一些问题......
///// Passing nothing, println requires one or two parameters
debugSerial.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);
我们使用C风格指针作为数组的一个技巧是分配一个比我们需要的更大的指针块,并确保它们都被设置为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
这不是最好的代码(可能有错误,我现在无法访问我的编译器)。但它试图坚持你的方法。