0

I have this function (which works fine):

String Esper::rtcTimeString() {
  DateTime now = rtc.now();
  char buf[] = "MM/DD/YY hh:mm:ss";
  return now.toString(buf);
}

I'd like to have a default value of "MM/DD/YY hh:mm:ss" but also pass an argument to a parameter such as "MM/DD/YYYY" if I want to override this default behavior.

Typically, in the definitions .h file I would do something like:

String rtcTimeString(char ts[] = "MM/DD/YY hh:mm:ss");

and subsequently in the .cpp:

String Esper::rtcTimeString(char ts[]) {
  DateTime now = rtc.now();
  return now.toString(ts);
}

However that results in the same returned time string every time.

e.g.

1/6/2020 12:01:12
1/6/2020 12:01:12
1/6/2020 12:01:12

How can I implement a parameter such that the functionality is the same as in the first code block?

1
  • 1
    I would expected char ts[] to be passed as reference (you could change the argument into char* but I doubt it will improve ... What I suggest is to use a PC compiler (e.g. free Visual Studio 2019 C++) and use the internal debugger to see what actually is passed and exactly where it goes wrong. Than move the corrected code back to Arduino. Commented Jan 6, 2020 at 22:03

2 Answers 2

1

You cannot pass an array of characters as an argument (implicit or not) to a function. When you write

String rtcTimeString(char ts[] = "MM/DD/YY hh:mm:ss");

The array notation is implicitly converted to a pointer. The line above is then equivalent to:

String rtcTimeString(char *ts = "MM/DD/YY hh:mm:ss");

And this is incorrect: you are initializing a pointer to modifiable characters using the address of an array of constant characters. The compiler should have warned you about this... if you enabled compiler warnings. The correct prototype should be

string rtcTimeString(const char* ts = "MM/DD/YY hh:mm:ss");

But then you cannot pass this pointer to DateTime::toString(), as this method expects the template string to live in a buffer it can overwrite: that's where it will write the formatted string.

I suggest this solution:

string rtcTimeString(const char* ts = "MM/DD/YY hh:mm:ss") {
    DateTime now = rtc.now();
    char buf[strlen(ts)+1];  // allocate a fresh buffer
    strcpy(buf, ts);         // copy the template there
    return now.toString(buf);
}
1
  • Well explained. Thank you!
    – Alex
    Commented Jan 8, 2020 at 8:15
1

This basic C++ (and GIYF).

What about

String Esper::rtcTimeString(std::string dateTimeForamt = "MM/DD/YY hh:mm:ss")
{
  DateTime now = rtc.now();

  return now.toString(dateTimeForamt );
}

See, for instance, this question. Hope this helps :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.