Pages: [1] 2   Go Down
Author Topic: Passing char arrays to a function - best practice  (Read 2898 times)
0 Members and 1 Guest are viewing this topic.
New Jersey
Offline Offline
God Member
*****
Karma: 2
Posts: 537
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm passing a character array to a function, and I can get it to work two different ways.  I'm wondering if one is preferred over the other.

Method 1
Code:
char msg[] = "Hello World";
SendMsg(msg);
Method 2
Code:
SendMsg("Hello World");
SendMsg function
Code:
void SendMsg(char myMsg[])
{
  char MsgAndTime[strlen(myMsg) + 10]; 
  strcpy(MsgAndTime, myMsg); 
  strcat(MsgAndTime, " 1:00 PM");
  Serial.println(MsgAndTime);
}
Logged

0
Offline Offline
Faraday Member
**
Karma: 24
Posts: 3499
20 LEDs are enough
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

It depends on what else you are doing. But IMHO concatenating two strings for output is a bad idea. Better output the two strings separately thus avoiding unnecessary use of RAM. Also: if you are using string constants you should learn about progmem.
Logged

Check out my experiments http://blog.blinkenlight.net

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 652
Posts: 50869
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I second what Udo says. The data being sent to the serial port by:
Code:
  char MsgAndTime[strlen(myMsg) + 10]; 
  strcpy(MsgAndTime, myMsg); 
  strcat(MsgAndTime, " 1:00 PM");
  Serial.println(MsgAndTime);
and
Code:
  Serial.print(myMsg); 
  Serial.println(" 1:00 PM");
is exactly the same, and the receiving end will have no idea which method was used. The second uses less memory, is faster, and is far less likely to have issues with overwriting array bounds (if you change the size of the string concatenated, without changing the array size).
Logged

New Jersey
Offline Offline
God Member
*****
Karma: 2
Posts: 537
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It depends on what else you are doing. But IMHO concatenating two strings for output is a bad idea. Better output the two strings separately thus avoiding unnecessary use of RAM. Also: if you are using string constants you should learn about progmem.

I need to concatenate the two strings together because the message is going out to Twitter.  In the Tweet I want to have the message and a timestamp.  If twitter sees two identical tweets one after the other it will just drop the 2nd one.  The timestamp prevents this.   I know I could just put millis() or something instead of the time, but that wouldn't change the need to concatenate two strings.
Logged

0
Offline Offline
Faraday Member
**
Karma: 24
Posts: 3499
20 LEDs are enough
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@ScottG: as PaulS confirmed the receiving end will never know that the strings were not concatenated. It does not matter if the receiving end is sending twitter messages or something else. It will never notice the difference.
Logged

Check out my experiments http://blog.blinkenlight.net

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I need to concatenate the two strings together because the message is going out to Twitter.

No you don't. What goes over the serial port is identical in both cases; all that's changing is the code you use to put that sequence of characters into the transmit buffer.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 652
Posts: 50869
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
No you don't. What goes over the serial port is identical in both cases; all that's changing is the code you use to put that sequence of characters into the transmit buffer.
Actually, OP does. The twitting library has one method to post a twit, and that method takes a string.
Logged

New Jersey
Offline Offline
God Member
*****
Karma: 2
Posts: 537
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If I pass a character array to a function, then add to it by using strcat() will my program adjust the memory allocated for this char array, or am I going to run into a memory problem.  For example

Code:
void createMsg() {
  char msgTweet[27];
  strcpy(msgTweet, "This is 26 characters long");
  sendMsg(msgTweet);
}

void sendMsg(char msgToSend[]){
  char addToMsg[] = "stuff";

  // add stuff to the message
  strcat(msgToSend, addToMsg);
  Serial.println(msgToSend);
}
Logged

Ayer, Massachusetts, USA
Offline Offline
Edison Member
*
Karma: 54
Posts: 1857
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If I pass a character array to a function, then add to it by using strcat() will my program adjust the memory allocated for this char array, or am I going to run into a memory problem.
You are going to run into problems and overwrite whatever happens to be adjacent to your array.  Strcat is fairly low level, and it assumes you have already checked that there is enough space allocated in the array to hold the current string plus the new string and the trailing byte.  There is the String class that does what you want, but since it uses dynamic memory allocation, it is subject to running out of memory.  I tend to be of the opinion that in a memory poor environment like the Arduino you should never use dynamic allocation (or if you must, only use it very sparingly).
Logged

New Hampshire
Offline Offline
God Member
*****
Karma: 17
Posts: 781
There are 10 kinds of people, those who know binary, and those who don't.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If I pass a character array to a function, then add to it by using strcat() will my program adjust the memory allocated for this char array, or am I going to run into a memory problem.  For example

strlcat() can be used to prevent writing outside the bounds of the destination buffer.  It will just truncate the second string if necessary.  Here is the reference for all the C string library functions: http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html#ga1fd2a6e188f02599e5eeb17519f67f3e
Logged


Offline Offline
Full Member
***
Karma: 2
Posts: 219
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

please try to adjust your sendmsg function like this, i believe it should work.
Code:
void SendMsg(char * myMsg)    // << points to your array and that should be enough, a basic c++ method
{
  char MsgAndTime[strlen(myMsg) + 10];  
  strcpy(MsgAndTime, myMsg);  
  strcat(MsgAndTime, " 1:00 PM");
  Serial.println(MsgAndTime);
}

notice only the main calling method is changed the way you would if calling for an array function variable.
if it doesnt work then arduino isnt c++ compliant but i dont doubt it wouldnt work like this.
« Last Edit: September 07, 2012, 08:18:41 am by PGTBOOS » Logged

New Jersey
Offline Offline
God Member
*****
Karma: 2
Posts: 537
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

please try to adjust your sendmsg function like this, i believe it should work.
Code:
void SendMsg(char * myMsg)    // << points to your array and that should be enough, a basic c++ method
{
  char MsgAndTime[strlen(myMsg) + 10];  
  strcpy(MsgAndTime, myMsg);  
  strcat(MsgAndTime, " 1:00 PM");
  Serial.println(MsgAndTime);
}

notice only the main calling method is changed the way you would if calling for an array function variable.
if it doesnt work then arduino isnt c++ compliant but i dont doubt it wouldnt work like this.


That was pretty much my plan B. But I was going to use (no pointer like in your example ):
Code:
void SendMsg(char myMsg)

I have a hard time grasping pointers.  I understand how they work, but it's much less intuitive and harder to understand for me.   I thought when you passed an array to a function, C always passes it as  pointer.  Is that right? So what's the difference between these two functions:
Code:
void SendMsg(char   myMsg)
void SendMsg(char * myMsg)

Logged

Germany
Offline Offline
Faraday Member
**
Karma: 59
Posts: 3089
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So what's the difference between these two functions:

Code:
void SendMsg(char [ ]  myMsg)
void SendMsg(char * myMsg)

None.
Inside SendMsg you don't know the size of myMsg, just the strlen.
And you can use both the same way: e.g.
Code:
myMsg[i]
*(myMsg+i)
are identical and valid in both cases
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 99
Posts: 4836
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void SendMsg(char   myMsg)

Passes SendMsg a signed 8-bit value.

Code:
void SendMsg(char * myMsg)

Passes SendMsg an unsigned 16-bit address to a signed 8-bit value.
Using the address (pointer) you can access that char, and others by their relative memory positions.

IMO best practice would be to make the original array big enough to hold the time stamp -- if you have to print just one string -- then strcat to that.

You might check but perhaps the twit thing looks for a newline or carriage return to determine end of message rather than timing out serial chars received or however it's supposed to "know" one bunch of print chars from the next -- you can fill the transmit buffer WAY faster than it sends chars out.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

sendMsg needs to take a const char* argument.
Logged

Pages: [1] 2   Go Up
Jump to: