[SOLVED] Combining char strings together to make one char string

Hi
I am trying to combine a number of chars together to create a long string that I will then add together to make a checksum.

when I try and compile it keeps coming up with the error “invalid operands of types ‘const char [3]’ and ‘const char [2]’ to binary ‘operator+’”

// Testing Data
const char device_id[3] = "001";
bool state1 = false;
bool state2 = true;
bool state3 = false;
char number_state[13] = "+123456789012";

void setup() {
  Serial.begin(9600);

  char data1[1];
  char data2[1];
  char data3[1];
  char settings_data[100];


  //convert bool to char
  if (state1 == true) {
    data1[0] = '1';
  }
  else {
    data1[0] = '0';
  }

  if (state2 == true) {
    data2[0] = '1';
  }
  else {
    data2[0] = '0';
  }

  if (state3 == true) {
    data3[0] = '1';
  }
  else {
    data3[0] = '0';
  }

  //combining data
  settings_data[0] = device_id + "," + data1 + "," + data2 + "," + data3 + "," + number_state + ","

  Serial.println(settings_data); //desired output "001,0,1,0,+123456789012,"
}

Thanks in advance
Hannah

edit1:
I used the strcat method and it complied but gave an output of “n␞.����������ݣ�.�^���������/�,0,0,0,0,0,0,0,0,0”

#include <arduino.h>

// Testing Data
const char device_id[4] = "001";
bool state1 = false;
bool state2 = true;
bool state3 = false;
char number_state[14] = "+123456789012";

void setup() {
Serial.begin(9600);

  char data1[1];
  char data2[1];
  char data3[1];
  char settings_data[100];


  //convert bool to char
  if (state1 == true) {
    data1[0] = '1';
  }
  else {
    data1[0] = '0';
  }

  if (state2 == true) {
    data2[0] = '1';
  }
  else {
    data2[0] = '0';
  }

  if (state3 == true) {
    data3[0] = '1';
  }
  else {
    data3[0] = '0';
  }

  //combining data
  strcpy(settings_data, device_id);
  strcat(settings_data, ",");
  strcat(settings_data, data1);
  strcat(settings_data, ",");
  strcat(settings_data, data2);
  strcat(settings_data, ",");
  strcat(settings_data, data3);
  strcat(settings_data, ",");
  strcat(settings_data, number_state);
  strcat(settings_data, ",");

  //settings_data[0] = device_id + "," + data1 + "," + data2 + "," + data3 + "," + number_state + ","

 Serial.println(settings_data); //example desired string 001,0,1,0,+123456789012
}

void loop() {

}

Edit2: running the strcat method on the Arduino IDE (rather than PlatformIO on Atom) returned “001,0,10,010,+123456789012,”

C-strings have to be null terminated, so to represent the string "1" requires a 2 element char array, so
there is space for the NUL character at the end.

strcat assumes its arguments are already null terminated and assumes that the result array is large enough
as it has no means to check. You are passing it data1 and data2 which are not null terminated and thus confusing it.

To compute a checksum you don't need to concatenate strings to together, you need to process all
the parts of the string in sequence, which should be straight-forward.

Thank for helping. The data I’m sending is a sort of data packet that I’m going to send over Bluetooth to a pc, then on the pc, it gets processed using a python program. Do you know of an easier way to do this?

I change my code a bit

#include <arduino.h>

// Testing Data
const char device_id[4] = "001";
char state1[1] = "1";
char state2[1] = "1";
char state3[1] = "1";
char number_state[14] = "+123456789012";

void setup() {
    Serial.begin(9600);

    char data1 = state1;
    char data2 = state2;
    char data3 = state3;
    char settings_data[100];


    //convert bool to char
    // if (state1 == true) {
    //   data1[0] = '1';
      // }
      // else {
      //   data1[0] = '0';
      // }
      //
      // if (state2 == true) {
      //   data2[0] = '1';
      // }
      // else {
      //   data2[0] = '0';
      // }
      //
      // if (state3 == true) {
      //   data3[0] = '1';
      // }
      // else {
      //   data3[0] = '0';
      // }

    //combining data
    strcpy(settings_data, device_id);
    strcat(settings_data, ",");
    strcat(settings_data, data1);
    strcat(settings_data, ",");
    strcat(settings_data, data2);
    strcat(settings_data, ",");
    strcat(settings_data, data3);
    strcat(settings_data, ",");
    strcat(settings_data, number_state);
    strcat(settings_data, ",");
    //strcat(settings_data, '\0');

    //settings_data[0] = device_id + "," + data1 + "," + data2 + "," + data3 + "," + number_state + ","

    Serial.println(settings_data); //example desired string 001,0,1,0,+123456789012
}

void loop() {

}

The output of Serial.println is “001,0,10,010,+123456789012,”

I recommend CStringBuilder from my StreamLib library
the library is in Library Manager

example:

 char buff[150];
 CStringBuilder sb(buff, sizeof(buff));

 sb.print(F("Some text: "));
 sb.println(s);
 sb.print(F("Some char: "));
 sb.println(c);
 sb.print(F("HEX of char: "));
 sb.println(c, HEX);
 sb.print(F("Some integer: "));
 sb.println(i);
 sb.print(F("Some float: "));
 sb.println(f, 3);
 sb.print(F("IP address: "));
 sb.println(ipAddress);

  Serial.print("size to print: ");
  Serial.println(sb.length());
  Serial.println();
  Serial.println(buff);

There are a few different methods of doing what you want. You do need to be careful when using c-strings (null-terminated char arrays) that you always allocate enough space for the terminating null character, which you are not doing with the data variables. strcpy() and strcat() require the terminating null, otherwise they will keep copying memory until they encounter a terminating null randomly in memory. The sprintf() command can easily format most data types into a string (will not work with float on an arduino), but if you do not need the combined string in your code, it is common to just print the data separately, the serial output is so slow that the entire sequence of print commands will be executed before the first character is finished sending on the serial line. Note that Serial.println() appends a carriage return and linefeed after the data you are printing, while Serial.print() does not, so the serial monitor sees all the Serial.print() text strung together on the same line.

// Testing Data
const char device_id[4] = "001";
bool state1 = false;
bool state2 = true;
bool state3 = false;
char number_state[14] = "+123456789012";

void setup() {
  Serial.begin(9600);

  char data1[2] = " "; //setting an initial value gets the compiler to store the terminating null character
  char data2[2] = " ";
  char data3[2] = " ";
  char settings_data[100];


  //convert bool to char
  if (state1 == true) {
    data1[0] = '1';
    //strcpy(data1, "1"); //alternate method, sets the terminating null for you
  }
  else {
    data1[0] = '0';
  }

  if (state2 == true) {
    data2[0] = '1';
  }
  else {
    data2[0] = '0';
  }

  if (state3 == true) {
    data3[0] = '1';
  }
  else {
    data3[0] = '0';
  }

  strcpy(settings_data, device_id);
  strcat(settings_data, ",");
  strcat(settings_data, data1);
  strcat(settings_data, ",");
  strcat(settings_data, data2);
  strcat(settings_data, ",");
  strcat(settings_data, data3);
  strcat(settings_data, ",");
  strcat(settings_data, number_state);
  strcat(settings_data, ",");
  Serial.println(settings_data); //example desired string 001,0,1,0,+123456789012

  //second method, using sprintf, and relying on a bool having a value of 0 for false and 1 for true
  sprintf(settings_data, "%s,%i,%i,%i,%s,", device_id, state1, state2, state3, number_state);
  Serial.println(settings_data); //example desired string 001,0,1,0,+123456789012

  //third method that does not require a buffer
  Serial.print(device_id);
  Serial.print(",");
  Serial.print(state1);
  Serial.print(",");
  Serial.print(state2);
  Serial.print(",");
  Serial.print(state3);
  Serial.print(",");
  Serial.print(number_state);
  Serial.println(",");

}

void loop() {

}

One way to get the desired output when you only need to change three characters in the packet is to pre-populate the packet with the unchanging data and indexing into the character array to insert the desired characters:

boolean state1 = false;
boolean state2 = true;
boolean state3 = false;


void setup()
{
  Serial.begin(9600);


  // DeviceID, State1, State2, State3, NumberState
  char settings_data[] = "001, X, X, X, +123456789012";


  // Replace the X's with 0 (false) or 1 (true)
  // Note: the 'trinary operator' ? is used like this: 
  //    (conditionalExpression) ? (valueIfTrue) : (valueIfFalse)
  settings_data[5] = state1 ? '1' : '0';
  settings_data[8] = state2 ? '1' : '0';
  settings_data[11] = state3 ? '1' : '0';


  Serial.println(settings_data);
  Serial.println ("Desired string:");
  Serial.println ("001, 0, 1, 0, +123456789012");


  Serial.flush();  // Wait for all of the characters to be sent out
}


void loop() {}

greshr:
Thank for helping. The data I'm sending is a sort of data packet that I'm going to send over Bluetooth to a pc, then on the pc, it gets processed using a python program. Do you know of an easier way to do this?

You do not need to copy data into a big string just to send.
Serial sends ONE char at a time from the Serial output buffer and reads ONE char at a time.
Even at 115200 baud, it takes over 1300 CPU cycles per char to send or get a single char through Serial.
It does NOT send or read a line at a time, there is NO MAGIC about Serial data.
The receiver, the read end, gets chars until the last and if the last one is a little late, it WAITS but likely never needs to.

The print command puts chars in the output buffer and the send uses interrupt code and the UART/port where the A is for Asynchronous meaning it happens when it happens.

    Serial.print(device_id);
    Serial.write(',');
    Serial.print(data1);
    Serial.write(',');
    Serial.print(data2);
    Serial.write(',');
    Serial.print(data3);
    Serial.write(',');
    Serial.print(number_state);
    Serial.write(',');
    Serial.println();
}

The output of that code is "001,0,10,010,+123456789012," without needing any big buffer.

Wasting RAM on a PC is "so what?" but it is a Bad Habit in Arduinoland.

Just to make it worse, if you try and jam a 100 byte message in the 64 byte Serial output buffer your sketch will block until the output buffer is no longer full.

Building big strings out of small ones is how projects that could run on a Nano end up "needing" a Mega2560.

Thank you to everyone who helped me.

My final solution was

#include <arduino.h>

// Testing Data
const char device_id[4] = "001";
char state1[1] = "1";
char state2[1] = "1";
char state3[1] = "1";
char number_state[14] = "+123456789012";

void setup() {

    Serial1.begin(9600);

    Serial1.print(device_id);
    Serial1.write(',');
    Serial1.print(state1);
    Serial1.write(',');
    Serial1.print(state2);
    Serial1.write(',');
    Serial1.print(state3);
    Serial1.write(',');
    Serial1.print(number_state);
    Serial1.write(',');
    Serial1.println();


}

void loop() {

}

The simplest solution is the best solution.

greshr:
The simplest solution is the best solution.

With a RISC processor it will be the fastest! AVR is simple to the core.

PS for you -- unless you have reason not to, serial baud rate should be 115200 or more.
Reason is that faster Serial empties the 64 char serial output buffer quicker leaving less chance to fill the buffer and until it is less than full every print gets held up until it is.

Baud rate is bits. Each char sent takes 1 start bit, 8 data bits, 1 stop bit.
9600 baud is 960 chars per second, more than a millisecond each!
115200 is 11520 cps and still at 16MHz is more than 1388 cycles... a long time to Arduino.

char state1[1] = "1";
char state2[1] = "1";
char state3[1] = "1";

    Serial1.write(',');
    Serial1.print(state1);
    Serial1.write(',');
    Serial1.print(state2);
    Serial1.write(',');
    Serial1.print(state3);
    Serial1.write(',');

That's risky. You don't have enough room in your character arrays for the null terminator so it is a crapshoot as to whether your strings will be terminated properly or not. Much safer would be:

char state1[] = "1";
char state2[] = "1";
char state3[] = "1";