Go Down

Topic: Passing a string to a function/sub (Read 1 time) previous topic - next topic

Lectere

I've made a function to write a line to the log;

Code: [Select]

void wltl(String logmessage) { // write line to log
          if(DEBUG){
           Serial.println(String(hour()) + ":" + String(minute()) + ":" + String(second()) + " " + logmessage);
          }
}


But I get some strange results when I run this.

I call it like this;

Code: [Select]

  wltl("SSID: " + String(WiFi.SSID()));


Thanks for your help guys...!  :)

majenko

Strings are evil.  Don't use them.

Whenever possible, use character arrays (char *).

Lectere

Is that because they can't be of variable lenght?,

And with a char array, how exactly would you write the log routine?

Thanks!

majenko

#3
Dec 04, 2012, 09:37 pm Last Edit: Dec 04, 2012, 09:48 pm by majenko Reason: 1
They can be of variable length, but they stomp all over your memory.  Not nice.

For your function, I would do something like:

Code: [Select]

void wltl(char *facility, char *logmessage)
{ // write line to log
  if (DEBUG) {
    Serial.print(hour());
    Serial.print(":");
    Serial.print(minute());
    Serial.print(":");
    Serial.print(second());
    Serial.print(" ");
    Serial.print(facility);
    Serial.print(": ");
    Serial.println(logmessage);
  }
}

wltl("SSID", WiFi.SSID());

Lectere

#4
Dec 04, 2012, 10:03 pm Last Edit: Dec 04, 2012, 10:06 pm by Lectere Reason: 1
But this forces me to allways pass 2 arguments to the function,

I sometimes just want to '

Code: [Select]
wltl("blaaat");

Without having to:
Code: [Select]
wltl("blaaat" ,"");

To make it all work.

Is there not a way to combine the string before passing it to the function?

Lectere

And why exactly are strings evil?

wildbill

They use C's memory allocation routines behind the scenes. There is a bug in the implementation of free, which will eventually use all your memory and crash. Even if the bug were fixed, there would still be a risk of problems caused by heap fragmentation. C arrays of char are a much better idea.

majenko


But this forces me to allways pass 2 arguments to the function,

I sometimes just want to '

Code: [Select]
wltl("blaaat");

Without having to:
Code: [Select]
wltl("blaaat" ,"");

To make it all work.

Is there not a way to combine the string before passing it to the function?


There is, but it involves more memory, and is pretty pointless anyway.  You could overload:

Code: [Select]

void wltl(char *facility, char *logmessage)
{ // write line to log
  if (DEBUG) {
    Serial.print(hour());
    Serial.print(":");
    Serial.print(minute());
    Serial.print(":");
    Serial.print(second());
    Serial.print(" ");
    if(facility)
    {
      Serial.print(facility);
      Serial.print(": ");
    }
    Serial.println(logmessage);
  }
}

void wltl(char *logmessage)
{
  wltl(NULL,logmessage);
}

Lectere

Okey,

But what if I want to pass 5 arguments;

Code: [Select]

  wltl("IP Address: " + String(ip[0]) + "." + String(ip[1]) + "." + String(ip[2]) + "." + String(ip[3]));
  wltl("Signal strenght (RSSI): " + String(WiFi.RSSI()) + "dBm");


Do I have to write 5 overload routines?


Lectere

It this all because you are passing a pointer to the string, and not the actual string?

majenko

Yep, you are passing the pointer.

You can construct a string using sprintf:

for example:
Code: [Select]

char temp[100];

sprintf(temp,"%d:%d:%d %s: %s",hour(),minutes(),seconds(),facility,logmessage);

drone

You are not passing five arguments, you are passing one argument and using the overloaded + operator of the String class to construct that argument.  Stop putting that operator in the argument, either construct your new string first, or pass multiple strings as multiple arguments.



Lectere

#13
Dec 05, 2012, 12:03 am Last Edit: Dec 05, 2012, 12:06 am by Lectere Reason: 1
I get this error tho;

error: cannot convert 'StringSumHelper' to 'char*' for argument '1' to 'void wltl(char*)'

Code: [Select]
void wltl(char *logmessage) { // write line to log
          if(DEBUG){
            Serial.print(hour());
            Serial.print(":");
            Serial.print(minute());
            Serial.print(":");
            Serial.print(second());
            Serial.print(":");
            Serial.println(logmessage);
          }
}


And I call it with this;

Code: [Select]
  wltl("IP Address: " + String(ip[0]) + "." + String(ip[1]) + "." + String(ip[2]) + "." + String(ip[3]));

The WLTL routine is suppose to make live easier, to centrally controll weather or not to write log items to disc, or add time stamps.

If I first have to construct a string, and then pass it, I might as well just plot it...

I'm a VB guy, I don't understand all this fuzz.

drone


I get this error tho;

error: cannot convert 'StringSumHelper' to 'char*' for argument '1' to 'void wltl(char*)'

Code: [Select]
void wltl(char *logmessage) { // write line to log
          if(DEBUG){
            Serial.print(hour());
            Serial.print(":");
            Serial.print(minute());
            Serial.print(":");
            Serial.print(second());
            Serial.print(":");
            Serial.println(logmessage);
          }
}


And I call it with this;

Code: [Select]
  wltl("IP Address: " + String(ip[0]) + "." + String(ip[1]) + "." + String(ip[2]) + "." + String(ip[3]));

The WLTL routine is suppose to make live easier, to centrally controll weather or not to write log items to disc, or add time stamps.


How can you convert a complex object like String to a char pointer?

You can't.

"ABC"  is a const char[3].  Get the plus operators out of your argument, as I said earlier. 

Consider the following, as has already been indicated to you by majenko (get rid of String):

Code: [Select]

char logmsg[100];
sprintf(logmsg, "IP Address: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);

wltl(logmsg);


Your life will be simpler, and your sketch will be smaller.


Go Up