在尝试填充String对象的动态数组时,我得到了程序的不可预知的行为。我试图简化程序,但无法弄清楚原因。
仅供参考:debug()
和debugLn()
将数据打印到Serial
,debugMem()
打印可用内存金额。
因此,最简单的版本按预期工作(场景 - 分配3个字符串的全局数组,定义3个局部变量并将它们的值赋给数组元素):
String* arr;
void setup() {
Serial.begin(9600);
debugMem("1");
String src = "abcdefghijk";
arr = malloc(3 * sizeof(String));
debugMem("2");
String dest1 = src;
String dest2 = src;
arr[0] = src.substring(0);
arr[1] = dest1.substring(0);
arr[2] = dest2.substring(0);
debugMem("3");
dest1.setCharAt(1, 'z');
dest2.setCharAt(1, 'x');
debug(F("src: "));
debugln(src);
debug(F("src located at "));
debugln((long)&src);
debug(F("dest1: "));
debugln(dest1);
debug(F("dest1 located at "));
debugln((long)&dest1);
debug(F("dest2: "));
debugln(dest2);
debug(F("dest2 located at "));
debugln((long)&dest2);
debug(F("arr[0]: "));
debugln(arr[0]);
debug(F("arr[0] located at "));
debugln((long)(arr + 0));
debug(F("arr[1]: "));
debugln(arr[1]);
debug(F("arr[1] located at "));
debugln((long)(arr + 1));
debug(F("arr[2]: "));
debugln(arr[2]);
debug(F("arr[2] located at "));
debugln((long)(arr + 2));
debugMem("4");
}
其输出:
>>>>>>>>>>1787<<<<<<<<<<1
>>>>>>>>>>1753<<<<<<<<<<2
>>>>>>>>>>1683<<<<<<<<<<3
src: abcdefghijk
src located at 2294
dest1: azcdefghijk
dest1 located at 2288
dest2: axcdefghijk
dest2 located at 2282
arr[0]: abcdefghijk
arr[0] located at 493
arr[1]: abcdefghijk
arr[1] located at 499
arr[2]: abcdefghijk
arr[2] located at 505
>>>>>>>>>>1683<<<<<<<<<<4
(尽管我对src,dest1,dest2的地址有点困惑,它们的总量大于2048字节的RAM)。
第二个版本实际上是相同的(将值从局部var推送到全局数组),但它的行为是完全不同的&#34; (方案 - 初始化一个虚拟源字符串,在函数中解析它,重新分配全局数组以存储已解析的字符串,从本地变量为每个数组元素分配一个值):
String* phones;
int phonesCount;
void setup() {
Serial.begin(9600);
String reply = "1234567890,2345678901,3456789012";
fillPhones(reply);
}
void loop() {
debugln(F("loop"));
for(int i = 0; i < phonesCount; i++) {
debug(F("Phone"));
debugln(i);
debug(F("Phone located at "));
debugln((long)(phones + i));
debug(F("Phone: "));
debugln(*(phones + i));
}
}
void fillPhones(String reply) {
phonesCount = parsePhones(reply, phones);
}
int parsePhones(String reply, String* &phonesArray) {
debugMem("1");
phonesArray = NULL;
int count = 0;
int fromIndex = 0;
int toIndex = 0;
while(toIndex >= 0) {
debug(F("Phone index: "));
debugln(count);
toIndex = reply.indexOf(F(","), fromIndex);
debug(F("Substring: "));
debug(fromIndex);
debug(F(".."));
debugln(toIndex);
debugMem("2");
String entryPhone = reply.substring(fromIndex, toIndex);
debugMem("3");
debug(F("Phone to add: "));
debugln(entryPhone);
debug(F("Phone located at "));
debugln((long)&entryPhone);
String* tmpArray = realloc(phonesArray, (count + 1) * sizeof(String));
if(tmpArray == NULL) {
break;
}
debug(F("Array allocated bytes: "));
debugln((count + 1) * sizeof(String));
debug(F("Array located at "));
debugln((long)tmpArray);
debugMem("4");
phonesArray = tmpArray;
debugMem("5");
phonesArray[count] = entryPhone;
debug(F("Added phone: "));
debugln(phonesArray[count]);
debug(F("Added phone located at "));
debugln((long)(phonesArray + count));
debugMem("6");
count++;
fromIndex = toIndex + 1;
}
debug(F("Total phones count:"));
debugln(count);
debugMem("7");
return count;
}
其输出:
>>>>>>>>>>1647<<<<<<<<<<1
Phone index: 0
Substring: 0..10
>>>>>>>>>>1647<<<<<<<<<<2
>>>>>>>>>>1634<<<<<<<<<<3
Phone to add: 1234567890
Phone located at 2273
Array allocated bytes: 6
Array located at 623
>>>>>>>>>>1626<<<<<<<<<<4
>>>>>>>>>>1626<<<<<<<<<<5
Added phone: 1234567890
Added phone located at 623
>>>>>>>>>>1613<<<<<<<<<<6
Phone index: 1
Substring: 11..21
>>>>>>>>>>1626<<<<<<<<<<2
>>>>>>>>>>1613<<<<<<<<<<3
Phone to add: 2345678901
Phone located at 2273
Array allocated bytes: 12
Array located at 657
>>>>>>>>>>1607<<<<<<<<<<4
>>>>>>>>>>1607<<<<<<<<<<5
Added phone: 2345678901
Added phone located at 663
>>>>>>>>>>1607<<<<<<<<<<6
Phone index: 2
Substring: 22..-1
>>>>>>>>>>1620<<<<<<<<<<2
>>>>>>>>>>1607<<<<<<<<<<3
Phone to add: 3456789012
Phone located at 2273
Array allocated bytes: 18
Array located at 657
>>>>>>>>>>1601<<<<<<<<<<4
>>>>>>>>>>1601<<<<<<<<<<5
Added phone: 3456789012
Added phone located at 669
>>>>>>>>>>1601<<<<<<<<<<6
Total phones count:3
>>>>>>>>>>1614<<<<<<<<<<7
loop
Phone0
Phone located at 657
Phone: 1234567890
Phone1
Phone located at 663
Phone: ‚56789012
Phone2
Phone located at 669
Phone: 3456789012
正如你所看到的,虽然没有可观察到的填充失败,但它会循环输出。
我想知道将字符串添加到(动态)字符串数组的正确方法是什么。为什么第一个版本工作正常?是因为它如此小/简单吗?
PS1:第一个例子的简短版本(没有调试输出):
String* arr;
void setup() {
Serial.begin(9600);
String src = "abcdefghijk";
arr = malloc(3 * sizeof(String));
String dest1 = src;
String dest2 = src;
arr[0] = src.substring(0);
arr[1] = dest1.substring(0);
arr[2] = dest2.substring(0);
dest1.setCharAt(1, 'z');
dest2.setCharAt(1, 'x');
}
PS2:第二个示例的简短版本(带有min debug输出):
String* phones;
int phonesCount;
void setup() {
Serial.begin(9600);
String reply = "1234567890,2345678901,3456789012";
fillPhones(reply);
}
void loop() {
debugln(F("loop"));
for(int i = 0; i < phonesCount; i++) {
debug(F("Phone"));
debugln(i);
debug(F("Phone located at "));
debugln((long)(phones + i));
debug(F("Phone: "));
debugln(*(phones + i));
}
}
void fillPhones(String reply) {
phonesCount = parsePhones(reply, phones);
}
int parsePhones(String reply, String* &phonesArray) {
phonesArray = NULL;
int count = 0;
int fromIndex = 0;
int toIndex = 0;
while(toIndex >= 0) {
toIndex = reply.indexOf(F(","), fromIndex);
String entryPhone = reply.substring(fromIndex, toIndex);
String* tmpArray = realloc(phonesArray, (count + 1) * sizeof(String));
if(tmpArray == NULL) {
break;
}
phonesArray = tmpArray;
phonesArray[count] = entryPhone;
count++;
fromIndex = toIndex + 1;
}
return count;
}
答案 0 :(得分:0)
我相信你可以这样做。
String arr[3];
arr[0] = "one";
arr[1] = "two";
arr[2] = "three";
如果数组需要增加元素数量,请使用std :: vector。
#include <vector> // include this header
// ...
std::vector<String> arr; // declare the array
arr.push_back("one"); // add as many elements as you want
arr.push_back("two");
arr.push_back("three");
arr[0]; // you can access the elements just like if it was a regular array
编辑:
由于没有可用的载体。
我认为最好的选择是为String
分配足够大的指针数组。然后保留索引到下一个要分配的String。
const unsigned MAX_PHONES = 1024;
String* arr = new String*[MAX_PHONES];
unsinged arrSize = 0;
// ...
// add new string
if(arrSize < MAX_PHONES)
arr[arrSize++] = new String;
else
assert(false && "MAX_PHONES exceeded");
// releasing memory
for(int i=0; i<arrSize; i++) delete arr[i];
delete[] arr;
答案 1 :(得分:0)
总结自己调查的结果和其他的评论 - 在Arduino程序中至少应该避免使用malloc()
/ realloc()
(至少 - 在Arduino IDE中构建的程序),总是使用new
运算符来分配动态数组(尽管您需要为realloc()
函数定义一个自定义替代)。