Substring of a char array

This is my char array :

char sentence[123] = "AAA,BBB,123,...,ZZZ";
char summary[90] = "";

I want to put AAA,BBB,123,..., inside summary. How can I do so?

In other words, I want to read sentence until the LAST occurence of , (comma), and then grab everything before it (including the comma), in order to put it inside summary

thank you.

I feel creative. :slight_smile:

Copy the entire string with strcpy().
Starting at the end, search backwards for the first comma.
Move forward one character.
Replace it with a 'null'.

The terminating comma seems weird. Why are you doing this?

Why are the buffers different sizes?

This is fun, in place:

void setup() {
Serial.begin(115200);
while(!Serial);
char sentence[123] = "AAA,BBB,123,...,ZZZ";
strtok(sentence,"Z");
Serial.println(sentence);
}

void loop() {}

But not if you are just counting commas. Use strchr() for that.

Ya but, "ZZZ" may be just an example and also a variable, not a constant.

The catch is that the simple search (for commas) requires backtracking or look ahead.

Maybe:

while traversing the entire string from left to right
{
copy a character to the destination buffer
if it is a comma
  {
  store its index
  }
}
increment the index
store a null to terminate the destination string

optionally maybe use strtok() to speed the same algorithm up by searching for commas faster if it's understood to be optimized code.

I am assuming here; the resulting string having a penultimate character "comma" with a terminating null is not desired, rather, the null should replace the "comma" then truncate the remaining characters.

My interpretation of the OP was literal. I did ask the question, why the comma but there was no response to that.

It's easy to make the change, either way.

strrchr() might be useful for this.

"aaa,bbb,..." is just an example, the actual data varies. @anon57585045 is correct.
The relevant information here is that the whole char array contains datas that are comma seperated.
As suggested by @anon57585045 again, my current implementation of this already consists in using strtok(). I don't quite like it because I later need to stitch all the parts together (AAA and , and BBB and , and 123 and , and ... and , and etc) to finally obtain the expected data that is AAA,BBB,123,..., , which is a very laborious way of doing it.

As suggested by @dougp, I came across strrchr() which seems to be relevant to my need, but I was not able to make it work.

What did you try ?

The idea (if you really need to get a copy and don’t want to modify the source cString at all)

  • Have a char pointer be the result of strrchr()
  • You have the char pointer to the start of the cString so The difference between those pointers gives you the number of char to copy
  • Copy that count of bytes using memcpy()
  • Add a trailing null to complete the cString
  • Bonus point: check for size to ensure you don’t overflow when you call memcpy()

If you don’t need the copy and can modify the source then it’s easier

  • Have a char pointer be the result of strrchr()
  • put a null char just after that pointer (if you wan to keep the trailing comma) and you are done
1 Like

@J-M-L

char mysubstring[123];
char * pos = strrchr(fullString, ',');
memcpy(mysubstring, fullString, pos-fullString);

mysubstring equals AAA,BBB,123,...⸮

➜ you are missing the trailing null to terminate the cString

and you need to add 1 to the difference to account for the comma

char fullString[123] = "AAA,BBB,123,...,ZZZ";
char mysubstring[123];


void setup() {
  Serial.begin(115200);
  char * pos = strrchr(fullString, ',');
  size_t count = pos - fullString + 1; // +1 to keep the last comma
  memcpy(mysubstring, fullString, count); // needs modification : check there is enough space before making the copy
  mysubstring[count] = '\0';
  Serial.print(F("result = \""));
  Serial.print(mysubstring);
  Serial.println('\"');
}

void loop() {}

of course you need to modify this to add a test on the count to ensure it's less than the size of mysubstring

or by modifying the original string

char fullString[123] = "AAA,BBB,123,...,ZZZ";

void setup() {
  Serial.begin(115200);
  char * pos = strrchr(fullString, ',');
  if (pos != nullptr ) {
    *(pos+1) = '\0';
    Serial.print(F("result = \""));
    Serial.print(fullString);
    Serial.println('\"');
  } else {
    Serial.println(F("error: could not find a comma"));
  }
}

void loop() {}

1 Like
char mysubstring[123];
char * pos = strrchr(fullString, ',');
uint8_t length = pos - fullString+ 1;
memcpy(mysubstring, fullString, length);
mysubstring[length] = '\0';

You were right I was missing the null terminating char.
I had to add +1 to the char position so that I have the comma included.
This seems to work as expected.
Is it acceptable or should I improve something?

see the comment in previous post

(I possibly edited the post while you were typing)

Just saw your edits.
I do not want to alter the original string indeed.
So I will add a strlen test condition and exit if too long.
Thank you very much for your time @J-M-L

what do you want to call strlen() upon? it needs to be a cString in the first place

you don't need to call strlen() since you know how many bytes you want to copy over (remember you want one extra byte for the trailing null char).

the size of the destination buffer is 127 but you can make that independent of such magic numbers by using sizeof mysubstring (which will be 127)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.