Arduino How can I use char instead of String (for better memory usage)

偶尔善良 提交于 2021-02-11 12:29:21

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!