Go Down

Topic: Having issue wrapping my head around concatenation in c++ (Read 296 times) previous topic - next topic

kilgorq

 I am setting up a clock on my tft display and I want to control exactly how the date is displayed. I Figured out how to get the correct portion of the date and time but I want them to be combined into one string that I send to the display. I can send each portion individually but have to specify the location on the display.

I want it to display

Thu, Oct, 12, 2017 

not

Thu  ,  Oct ,    12   ,   2017

The spacing is a little exaggerated to show what I an talking about.

I thought this would work

Code: [Select]
 
String sDate;
 
  sDate= (rtc.getDOWStr(FORMAT_SHORT) + ", " + (rtc.getMonthStr(FORMAT_SHORT)) + ", " + (t.date) + ", " + (t.year));


But is gives me this error.

invalid operands of types 'char*' and 'const char [3]' to binary 'operator+'


I am using Arduino DUE with CTE TFT Sheild and a 7" TFT CPLD Display.

Here is the section of code

Code: [Select]


void UpdateClock(){

    // Get data from the DS3231
  t = rtc.getTime();
  String sDate;
 
  sDate= (rtc.getDOWStr(FORMAT_SHORT) + ", " + (rtc.getMonthStr(FORMAT_SHORT)) + ", " + (t.date) + ", " + (t.year));

//  rtc.getDOWStr(FORMAT_SHORT)
//  rtc.getMonthStr(FORMAT_SHORT)
// (t.date)
// (t.year))
 
  myGLCD.setFont(DotMatrix_M_Slash);
  myGLCD.print(rtc.getDOWStr((FORMAT_SHORT)),400, 10);// Day of Week
  myGLCD.print("," ,450, 10); //Day of Month
  myGLCD.print(rtc.getMonthStr((FORMAT_SHORT)) ,465, 10); // Month Name Abbreviated
  myGLCD.printNumI((t.date) ,400 ,50); // Day of Month
  myGLCD.printNumI((t.year) ,400, 100); // Year
  myGLCD.print(rtc.getTimeStr((FORMAT_SHORT)) ,400, 150); // Time of Day 24 Hour

}


Delta_G

Stay away from the String class, and especially stay away from using the + to put Strings together.  It can shoot your heap memory full of holes and Arduino doesn't have any way to clean that up.  Plus, lots of libraries are going to use the much safer char arrays and suddenly that String crutch gets hard to use. 

You could use sprintf:

Code: [Select]


char buf[22];  // check this is big enough, I didn't count.

sprintf(buf, "%s, %s, %02d, %04d", rtc.getDOWStr(FORMAT_SHORT), rtc.getMonthStr(FORMAT_SHORT), t.date, t.year);



But the easier method may be just to print the different pieces to the screen separately instead of trying to get it all done in one line. 
If at first you don't succeed, up - home - sudo - enter.

johnwasser

The '+' operator only works for concatenation on String objects.  For character arrays, character pointers, and string constants you would typically use a C library function like strcat().  BE WARNED: It is YOUR responsibility to make sure that your buffer is large enough to hold the combined strings.
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

kilgorq

Stay away from the String class, and especially stay away from using the + to put Strings together.  It can shoot your heap memory full of holes and Arduino doesn't have any way to clean that up.  Plus, lots of libraries are going to use the much safer char arrays and suddenly that String crutch gets hard to use. 

You could use sprintf:

Code: [Select]


char buf[22];  // check this is big enough, I didn't count.

sprintf(buf, "%s, %s, %02d, %04d", rtc.getDOWStr(FORMAT_SHORT), rtc.getMonthStr(FORMAT_SHORT), t.date, t.year);



But the easier method may be just to print the different pieces to the screen separately instead of trying to get it all done in one line. 
Thank you... This work perfectly.

I am not a c or c++ coder.  I have always worked with TCL, and VBA,

This is all very new to me. I am really having difficulty getting the concepts down for some reason. Not sure why. I guess it will click eventually. I am sure part of it is time. I use it as a hobby so I don't get to use it very often.


What are the %s, %s, %02d, %04d for? I read the sprintf and the rest makes sense.

kilgorq

Am I reading it right?

%s means string
%02d means 2 digits
%04d means 4 digits


I this how sprintf sets up the formatting?

Delta_G

Am I reading it right?

%s means string
%02d means 2 digits
%04d means 4 digits


I this how sprintf sets up the formatting?
Google printf, you're more likely to find a good list of formatters that way. 



%s means string           Yes, lower case s string, not String class.  This is a null terminated char array
%02d means 2 digits     Not just 2 digits, the 0 there means to pad with 0's if not long enough
%04d means 4 digits     Same here, 4 digits 0 padded. 
If at first you don't succeed, up - home - sudo - enter.

jremington

With a little study, you will find sprintf() a much easier and much more flexible method to get exactly the output format you want, than mucking around with String operators.

In any case, Strings will eventually cause your Arduino to malfunction.

groundFungus


econjack

sprintf() is an extremely flexible and powerful function. However, rarely does one program use anything but a small fraction of that power. In the program below:

Code: [Select]

void setup() {
  char dow[] = "Thu";
  char month[] = "Oct";
  char result[20];
  char temp[5];
  int day = 12;
  int year = 2017;

  Serial.begin(9600);

 // sprintf(result, "%s, %s, %02d, %04d", dow, month, day, year);

  strcpy(result, dow);
  strcat(result, ", ");
  strcat(result, month);
  strcat(result, ", ");
  itoa(day, temp, DEC);
  strcat(result, temp);
  strcat(result, ", ");
  itoa(year, temp, DEC);
  strcat(result, temp);
   
  Serial.println(result);
}

void loop() {
}


the versions that uses sprintf() consumes 3348 bytes of flash and 206 bytes of SRAM. The alternative using the simple str*() functions uses 2084 bytes of flash and 190 bytes of SRAM. If you ever find yourself operating at the margins of memory, dropping back to less powerful functions might save the day.

Delta_G

You could recover the RAM (but not the program space) by using sprintf_P.

Code: [Select]
sprintf_P(result, PSTR("%s, %s, %02d, %04d"), dow, month, day, year);

If at first you don't succeed, up - home - sudo - enter.

econjack

You could recover the RAM (but not the program space) by using sprintf_P.

Code: [Select]
sprintf_P(result, PSTR("%s, %s, %02d, %04d"), dow, month, day, year);


True. The SRAM requirement drops from 206 to 188 for this version and flash increase a few bytes to 3350.

Delta_G

Where'd I get the extra 2 bytes of SRAM from?  I expected 190 like the str*() functions version you posted.  I figured all I was getting back was the format string.  Am I miscounting something?  I would say it is temp getting optimized out, but that should be 5 bytes.

If at first you don't succeed, up - home - sudo - enter.

econjack

I don't know. I'm using 1.8.4 of the compiler. Try compiling it and see if your numbers are different.

Delta_G

I don't know. I'm using 1.8.4 of the compiler. Try compiling it and see if your numbers are different.
Don't have one I can use right now (work computer, can't install).  I'll take your word for it, I know you know what you're doing.  I'm assuming your number is right and my thinking is wrong.  I just want to know where I'm counting wrong.  Nothing makes me crazier than knowing I got the answer wrong but not knowing why. 
If at first you don't succeed, up - home - sudo - enter.

PaulS

Quote
Where'd I get the extra 2 bytes of SRAM from?  I expected 190 like the str*() functions version you posted.
206 - 188 is 18, if I calculated that correctly. I'm tired, and I've been drinking, so maybe I didn't.

Quote
"%s, %s, %02d, %04d"
This string literal is 18 characters, if I counted that correctly. I'm tired, and I've been drinking, so maybe I didn't.

18 == 18 most of the time.
The art of getting good answers lies in asking good questions.

Go Up