Refernce variable length array with pointer

project description: I have an esp8266 that is receiving a string representing a color pattern of rgb values with a time for transitioning to the next color.
example format: "0,0,0,1000;255,0,0,1000;"
that is two values with 1000ms transition between each. I am parsing the incoming data so that, after it has been parsed I can loop over the values and update the gpio pins.

My issue: I am having trouble properly saving the variables in a dynamic length array and creating a pointer to that array. The pointer to the array has the same memory addresses but not the same values (at least for the first index that I am printing)

my approach: parse the incoming string so that I save each tick in the pattern; "255,0,0,1000" in an object, and each of those objects in a dynamic length array that I can point to in the main loop

goal: I need to be able to save the incoming string in a format that I can loop over, without blocking potential future incoming values (if I want to run a new color pattern that is received over wifi)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  #include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h> 

class color {
  public:
    int red;
    int green;
    int blue;
    int transitionTime;
    void printObj() {
      std::cout << "red: " << red << " - green: " << green << " - blue: " << blue << " - time: " << transitionTime;
    }
};

color *patternListObjects;
int patternLength = 0;

void parseTickValues(char *tick, int patternIndex, color *list) {
  char *value;
  color TickObj;
  //red green blue time seperated by ","
  value = strtok (tick,",");
  for (int i = 0; i < 4; i ++) {
    // std::cout << atoi(value) << "\n";
    if (i == 0) {
      TickObj.red = atoi(value);
    } else if (i == 1) {
      TickObj.green = atoi(value);
    } else if (i == 2) {
      TickObj.blue = atoi(value);
    } else if (i == 3) {
      TickObj.transitionTime = atoi(value);
    }
    value = strtok (NULL, ",");
  }
  //add color obj to the list
  list[patternIndex] = TickObj;
}



void splitPatternTicks(char *pattern, int ticks) {
      char *colorsAtTick;
      //im told this is bad? *colorsAtTickArray[ticks];
      char *colorsAtTickArray[ticks];
      //split pattern on ";" into chars
      colorsAtTick = strtok (pattern,";");
      while (colorsAtTick != NULL)
      {
        //save the chars into an array
        colorsAtTickArray[patternLength] = colorsAtTick;
        patternLength ++;
        colorsAtTick = strtok (NULL,";");
      }
      
      color list[patternLength];// = {};
      for (int i = 0; i < patternLength; i ++) {
        //loop over the array of char to further split and save values
        //colorsAtTickArray ex. "255,0,0,1000"
        parseTickValues(colorsAtTickArray[i], i, list);
      }
      patternListObjects = list;
      //Works here:
      std::cout << "\nprinting right after assignment: \n" << 
      &patternListObjects[0].red << "\n" << 
      &patternListObjects[0].green << "\n" << 
      &patternListObjects[0].blue << "\n\n" << 
      patternListObjects[0].red << " " << 
      patternListObjects[0].green << " " << 
      patternListObjects[0].blue << "\n\n";
    }


int main() {
  //the string I am receiving, it could vary in length
  //it represents rgb values with a time in ms to transition to the next color
  char string[42] = "0,0,0,1000;25,25,25,1000;150,150,150,1000";
  char *stringPointer = string;
  splitPatternTicks(stringPointer, 3);

  //fails here:
  std::cout << "printing through the refernce: \n" << 
  &patternListObjects[0].red << "\n" << 
  &patternListObjects[0].green << "\n" << 
  &patternListObjects[0].blue << "\n\n" << 
  patternListObjects[0].red << " " << 
  patternListObjects[0].green << " " << 
  patternListObjects[0].blue << "\n\n";
}


https://www.prepaidgiftbalance.vip/
Last edited on
Your basic problem here is that strtok() is not re-entrant. You can't tokenise more than one string at once. So trying to split on "," in parseTickValues messes up what splitPatternTicks is trying to do with ";".

1. use strtok_r() https://linux.die.net/man/3/strtok_r
2. use C++ std::string methods for everything.

If you're going to use C++, then commit to using it.
Dipping back into C for random bits of string handling is just a mess waiting to happen (or in your case, it's already happened).


The easiest c++ way probably is to use istringstream and getline() as the delimiter is a single char.

As a simple starter (no error checking etc), consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <string>
#include <sstream>
#include <vector>

struct color {
	int red;
	int green;
	int blue;
	int transitionTime;

	void printObj() const {
		std::cout << "red: " << red << " - green: " << green << " - blue: " << blue << " - time: " << transitionTime << '\n';
	}
};

int main()
{
	const std::string str {"0,0,0,1000;25,25,25,1000;150,150,150,1000"};

	std::vector<color> cols;
	std::istringstream value(str);

	for (std::string el; std::getline(value, el, ';'); ) {
		std::istringstream elem(el);
		std::string s;
		color col;

		std::getline(elem, s, ',');
		col.red = std::stoi(s);
		std::getline(elem, s, ',');
		col.green = std::stoi(s);
		std::getline(elem, s, ',');
		col.blue = std::stoi(s);
		std::getline(elem, s, ',');
		col.transitionTime = std::stoi(s);
		cols.push_back(col);
	}

	for (const auto& c : cols)
		c.printObj();
}


which displays:


red: 0 - green: 0 - blue: 0 - time: 1000
red: 25 - green: 25 - blue: 25 - time: 1000
red: 150 - green: 150 - blue: 150 - time: 1000

Last edited on
Topic archived. No new replies allowed.