How to make a function to return part of a char array [SOLVED]

Hi there,

I was working with the String objet on all my projects.

Now, I am told that I am playing with fire using Strings, so I try to understand how char works.

I am trying to extract a subString from a main string in a function. I thought that would be simple, but I just can’t figure it out.

Here is the code :

char items[] =
"ABCDEFG"
"HIJKLMNOP"
"QRS"
"TUV"
"WXYZ";

char abcde(){
  char test[10];
  for (int i = 0 ; i < 5 ; i++) test[i] = items[i];
  test[5] = '\0';
  return test;
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.print(items);
  Serial.print(abcde());
}

void loop() {
  // put your main code here, to run repeatedly:

}

“items” gets printed out, but “abcde()” does not.

If I could get this going, I could easily write a “jklmnop()” function.

Thanks for your help.

Jacques

There are no String objects in the code you posted, just character arrays ("C-strings"). They are totally different.

There are many simple functions to handle C-strings. Read about them here, among many other places.

Your problem is that the test array only exists inside the abcde function. Returning the address of the test string points to an invalid location on the stack. Declare the test string as a global. Pete

You are right, I did not post the equivalent String object code which could go like this:

String items = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

String abcde() {
  return items.substring(0,5);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println(items);
  Serial.println(abcde());
}  

void loop() {
  // put your main code here, to run repeatedly:

}

And that will work… But I was told that it is a no, no.

I have read about <string.h>, strcopy(), strncopy() and the like.

I would just like to see how to implement the simple code that I posted to work before embarking in the <string.h> adventure.

Jacques

Hi Pete,

Changed my code to this:

char items[] =
"ABCDEFG"
"HIJKLMNOP"
"QRS"
"TUV"
"WXYZ";
char test[10];

void abcde(){
  for (int i = 0 ; i < 5 ; i++) test[i] = items[i];
  test[5] = '\0';
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println(items);
  abcde();
  Serial.println(test);
}

void loop() {
  // put your main code here, to run repeatedly:

}

Of course, it works.

The thing is that I would like “abcde()” to return the value.

I have to rewrite a Library that actually uses Strings to comply with the no Strings directive.

That would mean that I will have to make “test” “public”.

Thing is, you don't have to extract it from the main string as long as you're not afraid the main string will not change :) Simply point to the first location you want to use and increment that pointer as many times as you would like characters :)

Hi septillion,

Do you mean that I should return a pointer instead of a char[]?

char[] IS a pointer ;)

I tried this:

String items = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

char abcde() {
  return items+4;
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println(items);
  Serial.println(abcde());
}  

void loop() {
  // put your main code here, to run repeatedly:

}

And I got [cannot convert 'StringSumHelper' to 'char' in return]

I guess I don't understand what a pointer is.

Now you're using String again, not a char array.

char myArray[10];

myArray;
//is the same as
&myArray[0]

//And for declaring
char new[];
//is the same as
char *new;

Realised the error

Changed "String items" to "char items[]". Compiles OK, but did not get "FGHIJKLMNOPQRSTUVWXYZ" as expected

That's because you're returning a char, not a char pointer ;)

char items[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

char* abcde() {
  return items+4;
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println(items);
  Serial.println(abcde());
} 

void loop() {
  // put your main code here, to run repeatedly:

}

I told you I did not understand pointers.

I have to dig into this first before playing with char arrays.

Thanks a lot septillion.

Another little example (Hope I didn’t make an error because untested ::))

char items[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

void setup(){
  Serial.begin(115200);
  
  printFrom(items, 8);
  Serial.println();
  
  printPart(items, 5, 3);
  Serial.println();
}

void loop(){
  
}

//instead of starting at the begin of the string we start with an offset
//but let it print to the nullchar as normal
void printFrom(char* txt, byte start){
  Serial.print(txt[start]);
  //same as
  //Serial.print(*(txt + start));
}

//or just print char for char from a start position
void printPart(char* txt, byte start, byte len){
  for(byte i = 0; i < len; i++){
    Serial.write(txt[start + i]);
    //same as
    //Serial.print(*(txt + start + i));
  } 
}

Note that both functions have NO check whatsoever to check if they go out of bound (or the array/string). (But can be added). So printFrom(items, 30) for example will do weird stuff :slight_smile:

Those are so cool.

Once, when I browsed thru "Serial" in the reference, I thought that "Serial.write" was useless. How wrong was I.

Thanks again. I can see that there is light in the end of my conversion nightmare tunnel.

Jacques

BTW. Tested the code and it works like charm.