问题
I have read thousand times that String library is not the best solution for code and memory optimization. So I need to use char instead of String. I have several functions that return String where I use it for store in file (sd card) or post it to web as param. So in the following sketch, how can i change it to work with char. I know how to save to sd file or post to webserver. I need only help for change the String to char.
#include <ThreeWire.h>
#include <RtcDS1302.h>
ThreeWire myWire(7,8,6); // IO, SCLK, CE
RtcDS1302<ThreeWire> Rtc(myWire);
#define countof(a) (sizeof(a) / sizeof(a[0]))
String NowDateTime="";
void setup() {
Serial.begin(9600); // for debugging
Rtc.Begin();
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
if (!Rtc.IsDateTimeValid()) {
Rtc.SetDateTime(compiled);
}
if (Rtc.GetIsWriteProtected()) {
Rtc.SetIsWriteProtected(false);
}
if (!Rtc.GetIsRunning()) {
Rtc.SetIsRunning(true);
}
RtcDateTime tempnow = Rtc.GetDateTime();
if (tempnow < compiled) {
Rtc.SetDateTime(compiled);
}
RtcDateTime now = Rtc.GetDateTime();
NowDateTime = strDT(now);
Serial.println((String)"RTC: "+NowDateTime);
}
void loop() {
delay(1000);
RtcDateTime now = Rtc.GetDateTime();
NowDateTime = strDT(now);
Serial.println(NowDateTime);
}
//RETURN Datetime id Readeable format as stting
String strDT(const RtcDateTime& dt)
{
char ret[30];
snprintf_P(ret,
countof(ret),
PSTR("%04u/%02u/%02u %02u:%02u:%02u"),
dt.Year(),
dt.Month(),
dt.Day(),
dt.Hour(),
dt.Minute(),
dt.Second() );
return ret;
}
Thanks in advance for your help!!!
回答1:
I know your intention is to understand on how to use c array instead of String class, but in your code, it is easy to avoid the use of String and keep the array local within the function to make the code simple and more robust.
You don't need to return a String, just add the Serial.print to the end of your function.
void loop() {
RtcDateTime now = Rtc.GetDateTime();
printDateTime(now);
}
void printDateTime(const RtcDateTime& dt)
{
char ret[20];
snprintf_P(ret,
countof(ret),
PSTR("%04u/%02u/%02u %02u:%02u:%02u"),
dt.Year(),
dt.Month(),
dt.Day(),
dt.Hour(),
dt.Minute(),
dt.Second()
);
Serial.println(ret);
}
If you really prefer to have the function to return the array that contained the formatted string, you can declare ret[20]
as a static
array within the function so that the value of the array won't be free up after returning from the function call.
void loop() {
RtcDateTime now = Rtc.GetDateTime();
Serial.println(strDT(now));
}
char* strDT(const RtcDateTime& dt)
{
static char ret[20]; //local static variable
snprintf_P(ret,
countof(ret),
PSTR("%04u/%02u/%02u %02u:%02u:%02u"),
dt.Year(),
dt.Month(),
dt.Day(),
dt.Hour(),
dt.Minute(),
dt.Second()
);
return ret;
}
Noticed that the return type from the function should be a point to the ret
(i.e. char*
).
Updated
Arduino String class versus cstring.h
String library you see in Arduino is not part of C++, it gives Arduino some features such as python-like or Java-like concatenation like String myString = "This string " + this_var + " another string";
, which use dynamic memory allocation malloc at heap memory. it looks easier for the people who is new to Arduino, it is however could caused heap fragmentation or memory leak especially if one is new to programming and don't really understand how heap works. To complete replace of using Sting class, it is best to learn how to use C++ cstring.h functions to handle string.
回答2:
Your function strDT(const RtcDateTime& dt)
returns a char*, not a String, if you don't force it to do so.
(You should define a static char ret[30];
however)
来源:https://stackoverflow.com/questions/61208131/arduino-how-can-i-use-char-instead-of-string-for-better-memory-usage