C++ Arduino-What';存储字符串数组的正确方法是什么?

C++ Arduino-What';存储字符串数组的正确方法是什么?,c++,string,arduino,C++,String,Arduino,在尝试填充字符串对象的动态数组时,我得到了一个程序的不可预测的行为。我试图简化程序,但找不出原因 仅供参考:debug()和debugLn()将数据打印到Serial,debugMem()打印可用内存量 因此,最简单的版本按预期工作(场景-分配一个包含3个字符串的全局数组,定义3个局部变量并将其值分配给数组元素): 其产出: >>>>>>>>>>1787<<<<<<<<<<1

在尝试填充字符串对象的动态数组时,我得到了一个程序的不可预测的行为。我试图简化程序,但找不出原因

仅供参考:
debug()
debugLn()
将数据打印到
Serial
debugMem()
打印可用内存量

因此,最简单的版本按预期工作(场景-分配一个包含3个字符串的全局数组,定义3个局部变量并将其值分配给数组元素):

其产出:

>>>>>>>>>>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
>>>>>>>>>>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
PS2:第二个示例的简短版本(具有最小调试输出):

String*手机;
int-phonescont;
无效设置(){
Serial.begin(9600);
字符串reply=“123456789023456789013456789012”;
电话(答复);;
}
void循环(){
debugln(F(“循环”);
for(int i=0;i=0){
toIndex=reply.indexOf(F(“,”),fromIndex);
String entryPhone=reply.substring(从索引到索引);
String*tmpArray=realloc(phonesArray,(count+1)*sizeof(String));
如果(tmpArray==NULL){
打破
}
phonesArray=tmpArray;
phonesArray[计数]=入口电话;
计数++;
从索引=到索引+1;
}
返回计数;
}

我相信你可以这样做

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

总结自己的调查结果和其他人的评论-
malloc()
/
realloc()
应避免在Arduino程序中使用(至少是内置于Arduino IDE中的程序),始终使用
new
运算符分配动态数组(尽管您需要为
realloc()
函数定义一个自定义的替代方案)

1)在C++程序中不要使用<代码> MalOC < /COD>。2) 了解
std::vector
。3) 了解智能指针。4) 如果你坚持使用(可怕的)原始指针;至少要正确地执行,并在您自己之后清理—您的程序泄漏。@JesperJuhl我同意#1,但对于#2和#3,Arduino的资源非常有限,所以通常使用原始指针和数组。@Johnny Mopp在这种情况下,4肯定会起作用。。还有,
std::unique_ptr
完全优化了—这是一个0开销的抽象。此外如果这就是OPs代码的全部错误,我们将是金黄色的。但事实并非如此。基本上是用C++编译器编译的坏C。什么是<代码>字符串< /代码>?您还没有向我们展示它的定义/代码。@JesperJuhl在Arduino上没有
std
。是一个特定于Arduino的类。或者你可以使用
std::string
而不是
char
的原始数组来获得更快乐的生活。@user1754322我问的是MCU程序,没有内置的向量实现等等。对不起,我不知道。我更新了答案。这行得通吗?@user1754322似乎我有一个想法,但它似乎不适合我(主要是因为内存大小非常有限)。我希望使用realloc()来简化数组的扩展。此外,一个保留字符串*和(分隔)字符串实例数组的选项本身也可以工作,但需要更多内存,而且会导致其碎片化。如果这是唯一正确的方法-好的,但是我不明白为什么我的第一个代码示例可以工作。
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');
}
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;
}
String arr[3];
arr[0] = "one";
arr[1] = "two";
arr[2] = "three";
#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
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;