Buffer cleaning problem

Hi everyone,
i have a problem with a buffer.
After i cleaned the buffer, the first time i use it, it show me the old text.
Why?

    const char ready[] = {"READY_200"};  // no array size, it will be auto terminated with \0
    const char end[] = {",END"};             // no array size, it will be auto teminated with \0
    const char changeLength[4] = {"C01,"}; // no array size, it will be auto teminated with \0

    char buffer[20];
    memset(buffer, 0, sizeof(buffer)); // clean buffer https://is.gd/E1eUgo
    byte i = 0;

    while (Serial.available() > 0) {  // have i received something?
      buffer[i] = Serial.read();
      i++;
    }
    Serial.print("buffer: ");
    Serial.println(buffer);

    char msg[i];
    memset(msg, 0, sizeof(msg)); // clean buffer https://is.gd/E1eUgo
    strcpy(msg, buffer);
    memset(buffer, 0, sizeof(buffer)); // clean buffer https://is.gd/E1eUgo

    Serial.print("msg: ");
    Serial.println(msg);
    Serial.print("buffer: ");
    Serial.println(buffer);
    Serial.println("--------");
    delay(500);

    if (strcmp(msg, ready) == 0) {  // have i received "READY_200"?
      Serial.println("ok");
      char buffer[30];
      char a[4];
      strcpy(buffer, changeLength);
      strcat(buffer, itoa(x, a, 10));  // int to string
      strcat(buffer, ",");
      strcat(buffer, itoa(y, a, 10));  // int to string
      strcat(buffer, end); 
      Serial.write(buffer);  // send to the machine
      Serial.println("");

I added a pic to show the problem.

UPDATE:
I found the problem:
const char changeLength[4] must be const char changeLength without dimension.

Now i can remove some clean buffer:

    const char ready[] = {"READY_200"};  // no array size, it will be auto terminated with \0
    const char end[] = {",END"};             // no array size, it will be auto teminated with \0
    const char changeLength[] = {"C01,"}; // no array size, it will be auto teminated with \0

    char buffer[20];
    byte i = 0;

    while (Serial.available() > 0) {  // have i received something?
      buffer[i] = Serial.read();
      i++;
    }
    Serial.print("buffer: ");
    Serial.println(buffer);

    char msg[i];
    strcpy(msg, buffer);
    memset(buffer, 0, sizeof(buffer)); // clean buffer https://is.gd/E1eUgo

    Serial.print("msg: ");
    Serial.println(msg);
    Serial.print("buffer: ");
    Serial.println(buffer);
    Serial.println("--------");
    delay(500);

    if (strcmp(msg, ready) == 0) {  // have i received "READY_200"?
      Serial.println("ok");
      char buffer[30];
      char a[4];
      strcpy(buffer, changeLength);
      strcat(buffer, itoa(x, a, 10));  // int to string
      strcat(buffer, ",");
      strcat(buffer, itoa(y, a, 10));  // int to string
      strcat(buffer, end); 
      Serial.write(buffer);  // send to the machine
      Serial.println("");

I noted that the “buffer[0] = (char)0;” instead of “memset(buffer, 0, sizeof(buffer));” doesn’t works good.

Would help if you could post code that would actually compile, but I think part of your problem is caused by declaring changeLength too short to hold the text you are storing in it, so that when you copy changeLength it runs past the end of the text into whatever is stored after it in memory, until the strcpy() finds a terminating null.

const char changeLength[4] must be const char changeLength[] without dimension.

Do you understand what was wrong with the original declaration ?

I noted that the "buffer[0] = (char)0;" instead of "memset(buffer, 0, sizeof(buffer));" doesn't works good.

If this doesn't work then there may be something else wrong.

    char buffer[20];
    byte i = 0;

    while (Serial.available() > 0) {  // have i received something?
      buffer[i] = Serial.read();
      i++;
    }
    Serial.print("buffer: ");
    Serial.println(buffer);

    char msg[i];
    strcpy(msg, buffer);

You forgot to terminate this buffer before copying it! This buffer is a new local buffer that contains whatever garbage was in memory. You have to add a terminator before using it as a string. Also, 'i' is the count of characters in the string WITHOUT the terminator. You have to make 'msg' a byte longer to have room for the terminator.

    while (Serial.available() > 0) {  // have i received something?
      buffer[i++] = Serial.read();
      buffer[i] = '\0';  // ADD NULL TERMINATOR
    }
    Serial.print("buffer: ");
    Serial.println(buffer);

    char msg[i+1];
    strcpy(msg, buffer);

If you have a char array that is being used to hold a cstring you can "clear" the cstring by writing a NULL i.e. '\0' to the first position in the array. For example

myBuffer[0] = '\0';

...R

UKHeliBob: Do you understand what was wrong with the original declaration ?

If i declare the string without the dimension between [] it adds the "\0" at the end of the string. Without the "\0" strcpy() doesn't works correctly, thx @david_2018.

vaj4088: If this doesn't work then there may be something else wrong.

I founded this solution here: https://is.gd/Eneocx Looks similar to the @Robin2 solution.

myBuffer[0] = '\0'; // Robin
data[0] = (char)0; // stackexchange

johnwasser: You forgot to terminate this buffer before copying it! This buffer is a new local buffer that contains whatever garbage was in memory.

Yes, this is my bigger mistake. Serial.available stops the read at "\0". Your code is very smart, but probably i prefer this way:

    while (Serial.available() > 0) {  // have i received something?
      buffer[i] = Serial.read();
      i++;
    }
    buffer[i] = '\0';  // ADD NULL TERMINATOR

    Serial.print("buffer: ");
    Serial.println(buffer);

    char msg[i];
    strcpy(msg, buffer);

With that fix i can eliminate the clean buffer.

Serial.available stops the read at “\0”.

Serial.available doesn’t “read”

markcalaway:
Serial.available stops the read at “\0”.

No, it doesn’t. If you receive a bunch of null characters, Serial.available() will show them as available in the input buffer and Serial.read() will return a zero value for each one.

markcalaway:
Your code is very smart, but probably i prefer this way:

    buffer[i] = '\0';  // ADD NULL TERMINATOR

Serial.print("buffer: ");
   Serial.println(buffer);

char msg[i];
   strcpy(msg, buffer);

You left in the mistake where ‘msg’ is one byte too small for the string you are copying into it.

Serial.available doesn't "read"

Assuming that the FIFO buffer has already contained 2 characters, then the execution of this code: byte n = Serial.available(); will return 2. From this fact, the poster might have the notion that Serial.available() does do the read (Serial.read()) operation, which is not true as is said in the above quote.

johnwasser: No, it doesn't. If you receive a bunch of null characters, Serial.available() will show them as available in the input buffer and Serial.read() will return a zero value for each one.

I tried, if i send "READY_200\0" it shows:

R E A D Y _ 2 0 0 \ 0

So the buffer array has a dimension of 11. In this case, when i add the "\0" at the end, i will have 12 chars. When i do strcmp, is it stops at the first \0 or at the second?

johnwasser: You left in the mistake where 'msg' is one byte too small for the string you are copying into it.

Yes right.

TheMemberFormerlyKnownAsAWOL: Serial.available doesn't "read"

My mistake, i meant what @GolamMostafa said.

The “\0” escape is part of the C++ programming language. Serial Monitor does not turn “\0” into a null character. It sends a ‘’ and a ‘0’ just like any other characters. If you want to send binary you could use another Arduino:

Serial.write("READY_200\0\0\0\0<-SEE?", 19);

All of the ‘str’ functions (strcmp(), strcpy(), strcat()…) will stop at the first NULL character because that is the definition of a C string. Serial.print(string) and Serial.write(string) will stop at the first NULL. To send a binary buffer you have to include the number of bytes to send. That’s why the ‘19’ in the code above is important. Without it you would only send “READY_200”.

johnwasser:
The “\0” escape is part of the C++ programming language. Serial Monitor does not turn “\0” into a null character. It sends a ‘’ and a ‘0’ just like any other characters. If you want to send binary you could use another Arduino:

Serial.write("READY_200\0\0\0\0<-SEE?", 19);

All of the ‘str’ functions (strcmp(), strcpy(), strcat()…) will stop at the first NULL character because that is the definition of a C string. Serial.print(string) and Serial.write(string) will stop at the first NULL. To send a binary buffer you have to include the number of bytes to send. That’s why the ‘19’ in the code above is important. Without it you would only send “READY_200”.

Very clear, thank you.
I hope that this discussion will be useful for other people.