使用分隔符拆分字符串数组

Splitting string arrays with delimiter

我正在使用以下代码拆分字符数组:

    char* Split(char* e, int index) {
  index = index -1;
  char* v[index +2];
  char *p;
  int i = 0;
  p = strtok(e, ",");
  while(p && i < index +2)
   {
    v[i] = p;
    p = strtok(NULL, ",");
    i++;
  };
//  Serial.println(v[0]);
  //Serial.println(v[1]);
 // Serial.println(v[2]);
  return v[index];
 };

我是这样调用函数的:

 char array[]="1,3,4,55,6,7,66";
 Serial.println("array:");
Serial.println(array);
 char *out;
 out = Split(array,2);
 Serial.println("out:");
 Serial.println(out);
 Serial.println("array:");
 Serial.println(array);
 out = Split(array,2);
 Serial.println("out:");
 Serial.println(out);

我第一次调用该函数时,一切正常。我得到的结果是 "3" ,这正是我所期望的。

但是第二次调用该函数时,事情变得很疯狂,我只得到了一些象形文字。

当我用 Serial 输出检查变量时,我可以看到“array”第二次只是“1”,这可能是函数输出奇怪的原因。

但我不明白函数的第一次调用如何影响“array”的值,因为函数中没有触及这个变量。 谁能帮我澄清一下这个问题?

串行接口的输出是这样的:

array:
1,3,4,55,6,7,66
out:
3
array:
1
out:
⸮}⸮a⸮⸮-:⸮⸮⸮m⸮⸮⸮⸮⸮⸮⸮]⸮ʻ⸮T⸮;⸮⸮⸮N}⸮⸮⸮⸮{R⸮U)⸮⸮⸮[G⸮⸮`j⸮⸮⸮⸮⸮v⸮⸮wz⸮⸮s⸮⸮⸮⸮⸮⸮}⸮⸮2⸮⸮vz~⸮⸮⸮⸮O}⸮⸮⸮/⸮⸮nv⸮⸮^j⸮yO⸮7{⸮⸮⸮⸮z⸮Z⸮⸮⸮⸮⸮⸮⸮7[⸮⸮⸮j⸮w⸮⸮⸮⸮⸮⸮⸮w)⸮⸮c⸮⸮}⸮⸮⸮⸮⸮⸮⸮⸮⸮v⸮⸮׺⸮m/V⸮ys<⸮⸮ٿ⸮⸮⸮׆⸮+>ֻ⸮z6⸮=⸮D⸮⸮⸮⸮~⸮⸮⸮⸮e⸮⸮?⸮=⸮⸮W⸮⸮⸮⸮}⸮e⸮ߣN绮⸮w⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮w⸮⸮⸮⸮?⸮⸮⸮⸮⸮⸮⸮Y⸮⸮޴f⸮v⸮⸮u⸮p?⸮⸮^h⸮⸮}⸮⸮ݼ⸮^Wo⸮⸮⸮⸮⸮_⸮⸮⸮⸮⸮⸮;s⸮⸮⸮⸮wZ⸮⸮⸮~⸮7⸮⸮⸮r⸮⸮⸮⸮)⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮f⸮⸮O⸮⸮⸮⸮⸮⸮⸮⸮⸮
⸮⸮7⸮⸮a.⸮⸮.kG⸮⸮8⸮⸮⸮⸮⸮⸮⸮⸮U⸮⸮⸮⸮⸮⸮⸮⸮⸮'⸮we⸮⸮⸮M⸮{⸮⸮Lu⸮no⸮⸮⸮>⸮⸮⸮⸮⸮⸮⸮~}⸮⸮⸮⸮⸮⸮⸮⸮y⸮⸮o⸮⸮⸮,'>}⸮⸮⸮+⸮X⸮⸮⸮/⸮⸮ױ⸮⸮⸮⸮̲⸮⸮-_M⸮⸮⸮⸮L~⸮#Φz~⸮⸮⸮⸮?⸮⸮⸮⸮⸮{/⸮_⸮:⸮jmc⸮m]S⸮_3⸮>o⸮׷⸮ݸv⸮⸮⸮|⸮
⸮⸮{_^⸮⸮o⸮?⸮⸮⸮⸮⸮⸮_⸮⸮⸮⸮{⸮⸮⸮^⸮⸮⸮⸮⸮⸮⸮⸮⸮ퟺ⸮⸮߿⸮⸮p⸮⸮⸮w?=⸮⸮⸮X⸮⸮⸮⸮⸮⸮_⸮oy⸮⸮M⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮w⸮⸮⸮[⸮⸮o⸮⸮⸮⸮޿7wE~⸮⸮⸮⸮⸮N⸮⸮o⸮x⸮=v/⸮⸮⸮⸮>⸮9⸮⸮ί⸮Y_Q⸮⸮l⸮⸮}'⸮⸮}⸮?⸮⸮ޭ⸮6⸮7⸮{⸮T⸮⸮⸮ ⸮r⸮⸮⸮⸮⸮⸮⸮
ܽ+'⸮⸮⸮⸮G⸮f⸮z⸮Gn⸮⸮n⸮/⸮⸮⸮⸮/⸮⸮⸮⸮Q⸮⸮⸮⸮⸮o⸮;⸮L⸮⸮r⸮⸮⸮⸮n/߿ſ⸮⸮⸮⸮q⸮⸮⸮ݮ⸮⸮⸮⸮⸮⸮+⸮⸮⸮⸮⸮⸮ﷹln?⸮⸮⸮⸮q⸮⸮⸮{⸮⸮⸮⸮⸮⸮⸮q⸮-⸮⸮{(⸮⸮f⸮⸮{⸮v⸮܀⸮oq⸮⸮⸮⸮⸮⸮߽⸮⸮nj⸮⸮⸮os⸮6۟g⸮⸮⸮⸮"⸮⸮7Z7⸮⸮yo⸮ӟ⸮⸮⸮w⸮⸮⸮⸮⸮⸮{⸮⸮⸮Vr⸮⸮]_⸮׷SS⸮_⸮w⸮⸮⸮wl⸮⸮⸮⸮P⸮⸮z⸮⸮m{⸮⸮⸮ݛs⸮(⸮⸮r⸮⸮˷:⸮%⸮⸮⸮⸮Z⸮⸮⸮m⸮W⸮⸮⸮⸮ם*⸮⸮⸮[>⸮⸮⸮/⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮?⸮⸮⸮⸮|⸮.⸮⸮⸮{⸮⸮⸮ꍥ⸮⸮⸮|⸮⸮⸮⸮⸮⸮⸮⸮⸮7~Ls⸮!⸮⸮⸮⸮⸮{⸮x⸮g⸮⸮|֍om~~⸮⸮⸮{⸮cϠ⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮>;⸮W⸮⸮⸮⸮⸮⸮⸮⸮q⸮⸮[:⸮'⸮#⸮o⸮⸮_⸮uϾ⸮⸮⸮⸮[⸮⸮^⸮⸮⸮n⸮}⸮⸮⸮⸮⸮>/⸮_⸮⸮-⸮⸮⸮⸮s⸮⸮⸮}⸮⸮⸮⸮/⸮[w⸮⸮r⸮⸮_⸮⸮⸮⸮,⸮⸮ݯ⸮⸮⸮7ÿ⸮:⸮⸮⸮⸮Ί⸮⸮⸮⸮⸮t[|⸮⸮w⸮F⸮⸮⸮

好的,我通过使数组独立于 strtok 的更改来获得它:

void setup(){
  Serial.begin(115200);
  char array[]="1,3,4,55,6,7,66";

 char *out;
 char array2[8];
 strcpy(array2,array);
  Serial.println("array2:");
Serial.println(array2);
 out = Split(array2,2);
 Serial.println("out:");
 Serial.println(out);
 Serial.println("array3:");
  char array3[8];
 strcpy(array3,array);
 Serial.println(array3);
 out = Split(array3,2);
 Serial.println("out:");
 Serial.println(out);
}

不是很优雅,但是很管用!!

有没有更好的主意?

Has anybody a better idea?

解决方案取决于你的数据,如果你的数据总是像一个字符串,用 , 分隔的整数列表,那么最好将它拆分成一个 int 数组,你然后可以编写一个通用的 split() 函数。

#define NUMBER_OF_ELEMENT 7

int splitted[NUMBER_OF_ELEMENT];
const char* delimiter = ",";

void split(const char *str, const char *delimiter) {
  char temp[strlen(str)+1] = {0};
  memcpy(temp, str, strlen(str));

  int i=0;
  char *p = strtok(temp, delimiter);
  while(p != NULL) {
    splitted[i++] = atoi(p);
    p = strtok(NULL, delimiter);
  }
}

int setup() {
  char array[]="1,3,4,55,6,7,66";
  
  Serial.begin(115200);

  split(array, delimiter);

  // get every splitted element as an int
  for (int i=0; i<NUMBER_OF_ELEMENT, i++) {
    Serial.print("Out:");
    Serial.println(splitted[i]);
  }

  //if you really want to have string as result
  Serial.println(String(splitted[3]));
}

谢谢,太好了! 是的,我的数据总是整型的。所以你的功能对我来说是完美的。 但是为了结构清晰,我更愿意使用 return 值,而不是更改全局变量“splitted”。 这是一个好习惯吗?还是您更喜欢节省 RAM 的变体?

这是我完成此任务的最终解决方案。该函数只是returns一个单一的值,根据给定的索引:

int splitStrToInt(char *str, int index) {
    //******************
    //This function splits a string that is separated by commas and converts the values ​​to int,
    //according to the given index
    //caution!! The string may only consist of numerical values ​​!!
    //Example: "1,3,4,55,6,7,66"
    //******************
    index--;
    char e[strlen(str) + 1] = { 0 }; 
    memcpy(e, str, strlen(str));
    int v[index + 2];
    char *p;
    int i = 0;
    p = strtok(e, ",");
    while (p && i < index + 2) {
        v[i] = atoi(p);            
        p = strtok(NULL, ",");
        i++;
    }
    ;

    return v[index];
}