Parsing and comparing strings on Teensy 3.2: different behaviour from gcc?

Status
Not open for further replies.

frodojedi

Member
I am trying to parse a simple string, print the result of the parsing via serial.println, and trigger a function on the basis of the received command. I wrote the code below, which perfectly works in c. However, the behaviour of the same code on the arduino IDE is completely different and I really can't figure out why.

Code:
#include <string.h>

void rcv_msg(char *rcv_msg) {
  
  char *all_tokens[2]; 
  int i = 0;

  all_tokens[i] = strtok(rcv_msg, "{,}");
  while (all_tokens[i] != NULL) {
    all_tokens[++i] = strtok(NULL, "{,}");
  }

  char *command = all_tokens[0]; 
  char *value = all_tokens[1];

  
  /*
  //These printls do not work, they are ignored, why?
  Serial.println("all_tokens[0]: ");
  Serial.println(all_tokens[0]);
  Serial.println("all_tokens[1]: ");
  Serial.println(all_tokens[1]);
  */

  if (strcmp(command,"message_1") == 0 && strcmp(value,"1") == 0) {

    Serial.println("message 1: ");
    Serial.println(command);
    Serial.println(value);
    Serial.println(" ");
    
  }
  
  if (strcmp(command,"message_2") == 0 && strcmp(value,"0") == 0) {

    Serial.println("message 2: ");
    Serial.println(command);
    Serial.println(value);
    Serial.println(" ");
    
  }
}



void setup() {
  
    Serial.begin(115200);
}

void loop() {
   
    char msg1[] = "{message_1,1}";
    char msg2[] = "{message_2,0}";

    Serial.println("Send msg1: ");
    rcv_msg(msg1); 
    delay(5000);
 
    Serial.println("Send msg2: ");
    rcv_msg(msg2); 
    delay(5000);    
}

This code gives the following output on the serial monitor, which is wrong:

Send msg2:
message 2:
message_2
{message_2,0}

Send msg1:
message 2:
message_1
{message_2,0}

Send msg2:
message 2:
message_2
{message_2,0}

Send msg1:
message 2:
message_1
{message_2,0}


Firstly, I don't understand why at the beginning, message 2 is printed before message 1, although message 1 was sent first. Second it is not clear to me the comparison done with strcmp is always returning the message 2.


More importantly, why running the same code in c has instead the correct output?


The c code (which is perfectly working is this:
Code:
#include <string.h>
#include <stdio.h>


void rcv_msg(char *rcv_msg) {
    
    char *all_tokens[2]; //NOTE: the message is composed by 2 tokens: command and value
    int i = 0;
    

    all_tokens[i] = strtok(rcv_msg, "{, }");
    while (all_tokens[i] != NULL) {
        all_tokens[++i] = strtok(NULL, "{, }");
    }
    
    printf("all_tokens[0] : %s \n", all_tokens[0]);
    printf("all_tokens[1] : %s \n", all_tokens[1]);
    
    char *command = all_tokens[0];
    char *value = all_tokens[1];
    
    printf("command : %s \n", command);
    printf("value : %s \n", value);
    
    

    if (strcmp(command,"motor1_pattern1") == 0 && strcmp(value,"1") == 0) {
        printf("activating command : %s %s \n\n\n", command, value);
    }
    
    if (strcmp(command,"motor1_pattern2") == 0 && strcmp(value,"0") == 0) {
        printf("activating command : %s %s \n\n\n", command, value);
    }
}



int main() {
    
    char msg1[] = "{message_1, 1}";
    char msg2[] = "{message_2, 0}";
    
    rcv_msg(msg1);
    rcv_msg(msg2);

}
 
Emm I spot the error... I was accessing all_tokens[2], which is wring given the fact that that array is only long 2.
 
I modified you sketch just a bit. It works for optimization Smallest or Fast but misbehaves for Faster and Fastest ???
Code:
#include <string.h>

void rcv_msg(char *rcv_msg) {

  char *all_tokens[2];
  int i = 0;

  all_tokens[i] = strtok(rcv_msg, "{,}");
  while (all_tokens[i] != NULL) {
    all_tokens[++i] = strtok(NULL, "{,}");
  }
  //  Serial.println(i);

  char *command = all_tokens[0];
  char *value = all_tokens[1];

  //These printls do not work, they are ignored, why?
  Serial.print("all_tokens[0]: ");
  Serial.println(all_tokens[0]);
  Serial.print("all_tokens[1]: ");
  Serial.println(all_tokens[1]);

  if (strcmp(command, "message_1") == 0 && strcmp(value, "1") == 0) {
    Serial.print("message 1: ");
    Serial.print(command);
    Serial.print(" ");
    Serial.println(value);
  }

  if (strcmp(command, "message_2") == 0 && strcmp(value, "0") == 0) {
    Serial.print("message 2: ");
    Serial.print(command);
    Serial.print(" ");
    Serial.println(value);
  }
  Serial.println();
}



void setup() {

  Serial.begin(115200);
  while (!Serial);
}

void loop() {

  char msg1[] = "{message_1,1}";
  char msg2[] = "{message_2,0}";

  Serial.print("Send : ");
  Serial.println(msg1);
  rcv_msg(msg1);
  delay(5000);

  Serial.print("Send : ");
  Serial.println(msg2);
  rcv_msg(msg2);
  delay(5000);
}

However, if you uncomment the Serial.println(i), sketch works for Faster and Fastest too ????

strange.
 
@manitou - that is strange - I had to try it - and without sending '\n' the parse printing is messed up - active Teensy was the beta - but same result with FASTER is BAD and FAST is GOOD.

Instead of println() I did ' Serial.print("---"); ' - and the "---" did not appear either without the println.

It seems the 2nd string is losing the NULL terminate - this fails the same too:
Code:
  Serial.printf( "all_tokens[0]: %s\n", all_tokens[0]); 
  Serial.printf( "all_tokens[1]: %s\n", all_tokens[1]);

EDIT: It isn't just printing the '\n' - it takes the reference to (i) !

This to Serial2 works as well :: Serial2.println(i);

BUT THAT is just a HACK - the problem as @frodojedi indicated this array is too small to exit properly! This needs [3] elements!

char *all_tokens[3];
 
Last edited:
Code works nicely like this:
Code:
#include <string.h>

void rcv_msg(char *rcv_msg) {
	[COLOR="#FF0000"]char *all_tokens[3];[/COLOR]
	int i = 0;

	all_tokens[i] = strtok(rcv_msg, "{,}");
	while (all_tokens[i] != NULL) {
		all_tokens[++i] = strtok(NULL, "{,}");
	}

	char *command = all_tokens[0];
	char *value = all_tokens[1];

	Serial.print("all_tokens[0]: ");
	Serial.println(all_tokens[0]);
	Serial.print("all_tokens[1]: ");
	Serial.println(all_tokens[1]);

	if (strcmp(command, "message_1") == 0 && strcmp(value, "1") == 0) {
		Serial.print("message 1: ");
		Serial.print(command);
		Serial.print(" ");
		Serial.println(value);
	}

	if (strcmp(command, "message_2") == 0 && strcmp(value, "0") == 0) {
		Serial.print("message 2: ");
		Serial.print(command);
		Serial.print(" ");
		Serial.println(value);
	}
	Serial.println();
}



void setup() {

	Serial.begin(115200);
	while (!Serial);
	Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
}

void loop() {

	char msg1[] = "{message_1,1}";
	char msg2[] = "{message_2,0}";

	Serial.print("Send : ");
	Serial.println(msg1);
	rcv_msg(msg1);
	delay(5000);

	Serial.print("Send : ");
	Serial.println(msg2);
	rcv_msg(msg2);
	delay(5000);
}

T:\tCode\FORUM\TokenParse\TokenParse.ino May 25 2019 12:13:07
Send : {message_1,1}
all_tokens[0]: message_1
all_tokens[1]: 1
message 1: message_1 1

Send : {message_2,0}
all_tokens[0]: message_2
all_tokens[1]: 0
message 2: message_2 0
 
Code:
  while (all_tokens[i] != NULL) {
    all_tokens[++i] = strtok(NULL, "{,}");   //  char msg1[] = "{message_1,1}";
  }

There are 3 tokens in the test string( msg1[] ), open bracket, comma, close bracket. The while loop does not terminate after two iterations. And the array also stores the NULL case. I count a total of 4 array elements.
 
Status
Not open for further replies.
Back
Top