Can some explain this code - it works

Is there someone that could explain this code to me? It does what I want, I just want to understand what exactly is happening.

      int counter = 0; 
      std::string str = "10:00,Adcom,11:00,Fitness";
      std::vector<std::string> v; // I don't understand this.
     
      char * token = strtok (&str[0],","); // I don't understand everything, I know it splits the comma limited list, but why &str[0]? Why not just &str?
      while (token != NULL)
      {
        v.push_back(token); // seems to push to the next in the array? But what does v contain?
        token = strtok (NULL, ","); // don't understand what this does. 
      }
      for ( std::string s : v ) // fills s with value from v, as long as v has a value?  
      {
        counter = counter + 30;
        it.printf(240, 425 + counter, id(tm30), TextAlign::CENTER, "%s", s.c_str());
      }

If someone could help me figure out, then I would be greatly helped.

As best I can figure:

std::vector<std::string> v; 

Creates an empty vector of type string. A vector can be thought of as a way to reference an element of an array for this example. They are actually more complex, the reason for using them is unlike arrays you don’t have to define a size.

char * token = strtok (&str[0],",");

As you said, strtok takes a string and breaks it into a series of tokens using a delimiter - in this case “,” (comma). Why &str[0]? Because we used a string not a char array. Possibly because ESPHome makes extensive use of strings.

while (token != NULL)

token = NULL would mean we have run out of tokens.

      {
        v.push_back(token); 

This takes the current token and loads it into vector v (we will use it later)

        token = strtok (NULL, ","); 

In order to get next token and to continue with the same string NULL is passed as first argument since strtok maintains a static pointer to your previous passed string.

      }

      for ( std::string s : v ) 
      {
        counter = counter + 30;
        it.printf(240, 425 + counter, id(tm30), TextAlign::CENTER, "%s", s.c_str());
      }

This will iterate through vector v, that you just loaded above.

So in summary what it does is, takes a comma delimited string, which can have as many elements as you like, load the values from that string into a vector, then iterates that vector to print them out.

The emphasis above is why you would use vectors. Mind you the could have just used the tokens and done the same thing, the vector is only really useful if you want to do something else with the values after printing them.

      int counter = 0; 
      std::string str = "10:00,Adcom,11:00,Fitness";
     
      char * token = strtok (&str[0], ","); 
      while (token != NULL)
      {
        counter = counter + 30;
        it.printf(240, 425 + counter, id(tm30), TextAlign::CENTER, "%s", token);        
        token = strtok (NULL, ","); 
      }

That should work the same :slight_smile: Maybe…

@zoogara Thanks for your explanation. It makes sense to me now. Still difficult to get my head around, but much clearer. This looping and arrays (of any kind) have been difficult to grasp for me in any language (php or basic).
I did find out that the code could be shorter by using the token as you said. This is the code that I use:

int counter = 180;
      if (id(agendanum1).state >= 1) {
        int loopcounter = 0;
        std::string str = id(agendaitems1).state;
        std::vector<std::string> v;
        char * token = strtok (&str[0],",");
        while (token != NULL)
        {
          v.push_back(token);
          loopcounter += 1; 
          it.printf(75, counter, id(tm20), token);
          if (loopcounter < 2) {
            counter += 20;
          } else {
            counter += 30;
            loopcounter = 0;
          } 
          token = strtok (NULL, ",");
        } 
      } else {
        it.print(75, counter, id(tm20), "No appointments today!");
        counter += 30;
      }

It creates the entries of an agenda (which is a comma delimited list) writes them over several lines on an e-paper. Basically I will be going through the week, starting with the current day and showing all appointments I have for the rest of the week per day. Seems to be working so far. Just hoping the ESP32 holds it and doesn’t brownout on me.