Problem with own Substring-Method

Hey,

I implemented a substring-method by myself but I'm encountering strange behaviour.

Here is my substring-method:

char *substring(char const *string, int startIndex, int stopIndex){
  
  if(stopIndex>=strlen(string)){
    stopIndex = strlen(string)-1;
  }
  char substring[stopIndex-startIndex+2];
  
  int index = 0;
  while(startIndex+index <= stopIndex){
    substring[index] = string[startIndex+index];
    index++;
  }
  substring[index] = 0;
  return substring;
}

char *substring(char const *string, int startIndex){
  return substring(string, startIndex, strlen(string)-1);
}

When using it inside my other code it returns the right substring (I checked it inserting Serial.println(substring) before the "return substring;" in my substring-method) but I can't Serial.println() it outside the substring-method.

Here a code snippet with generated Output:

char *command = inputLine;   // inputLine is a charArray[64] which contains "TEMP" with the terminating NULL

command = substring(command, 1);
Serial.println(strlen(command));      // output is: 3
Serial.println(command);                // output is a special c but not the expected "EMP". WHY?

The problem is your substring is allocated inside the function.

The best way of doing it is to pass a target string as a parameter:

char mySubstring[20];
char *myString = "This is my string, so there!";

substring(mySubstring,myString,5,24);

and the function is defined as:

void substring(char *target, char *source, int start, int stop)
{
...
}

And you write the substring data to "target", which modifies the variable passed to the function.

Thank You!

I modified my method to the following and now it works perfectly:

void substring(char const *string, int startIndex, int stopIndex, char *target){
  
  if(stopIndex>=strlen(string)){
    stopIndex = strlen(string)-1;
  }

  char substring[stopIndex-startIndex+2];
  
  int index = 0;
  while(startIndex+index <= stopIndex){
    substring[index] = string[startIndex+index];
    index++;
  }
  substring[index] = 0;
  
  strcpy(target,substring);

}

void substring(char const *string, int startIndex, char *target){
  substring(string, startIndex, strlen(string)-1, target);
}

You don't need the substring variable, nor the strcpy at the end - just use "target" instead of "substring" and modify the target directly.

But I want to be able to call something like

substring(command, 4, command);

so I thought this would be the most memory efficient solution, isn't it?

If you want to modify the string you're passing as the source, so it just contains the target, there's nothing to stop you writing to the same string you're reading from - as long as you are always writing to a different portion to that which you are reading from.

void substring(char const *string, int startIndex, int stopIndex, char *target){
  
  if(stopIndex>=strlen(string)){
    stopIndex = strlen(string)-1;
  }
  
  int index = 0;
  while(startIndex+index <= stopIndex){
    target[index] = string[startIndex+index];
    index++;
  }
  target[index] = 0;
}

char *command = "This is my command, right here.";

substring(command,11,17,command);

"command" would end up with just the word "command" in it.

Or you can use the existing string commands with source and/or dest addresses offset.

char *bigstring = "this is a big string";
char substring[ 12 ];

void setup( void )
{
  byte  len = 11;
  memset( substring, 0, 12 );
  strncpy( substring, ( bigstring + 5 ), len );  // starts copying 5 chars into bigstring
  strcpy( bigstring, bigstring + 8 ); // copies the end of bigstring to the start of bigstring
  Serial.begin( 9600 );
  Serial.println( bigstring );
  Serial.println( substring );
}

void loop( void )
{
}

Or, if you only ever want to modify the source string, it can be even more efficient:

char *string = "This is my command, right here!";

char *sub = string+11;
*(sub+7)=0;