In C how can I separate a char array by a delimiter? Or is it better to manipulate a string? What are some good C char manipulation functions?
8 Answers
#include<string.h>
#include<stdio.h>
int main()
{
char input[16] = "abc,d";
char *p;
p = strtok(input, ",");
if(p)
{
printf("%s\n", p);
}
p = strtok(NULL, ",");
if(p)
printf("%s\n", p);
return 0;
}
you can look this program .First you should use the strtok(input, ",").input is the string you want to spilt.Then you use the strtok(NULL, ","). If the return value is true ,you can print the other group.

- 416
- 3
- 8
-
4Thank you for the code, sorry dumb question, why are you using strtok a second time? Also, what does "If the return value is true ,you can print the other group." mean? – SSH This Dec 14 '12 at 16:22
Look at strtok(). strtok() is not a re-entrant function.
strtok_r() is the re-entrant version of strtok(). Here's an example program from the manual:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *str1, *str2, *token, *subtoken;
char *saveptr1, *saveptr2;
int j;
if (argc != 4) {
fprintf(stderr, "Usage: %s string delim subdelim\n",argv[0]);
exit(EXIT_FAILURE);
}
for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
token = strtok_r(str1, argv[2], &saveptr1);
if (token == NULL)
break;
printf("%d: %s\n", j, token);
for (str2 = token; ; str2 = NULL) {
subtoken = strtok_r(str2, argv[3], &saveptr2);
if (subtoken == NULL)
break;
printf(" --> %s\n", subtoken);
}
}
exit(EXIT_SUCCESS);
}
Sample run which operates on subtokens which was obtained from the previous token based on a different delimiter:
$ ./a.out hello:word:bye=abc:def:ghi = :
1: hello:word:bye
--> hello
--> word
--> bye
2: abc:def:ghi
--> abc
--> def
--> ghi

- 117,907
- 20
- 175
- 238
-
1Please do not recommend `strtok`, it's non-reentrant. Its "grown up brother" `strtok_r` is a lot better. – Sergey Kalinichenko Apr 27 '12 at 10:54
-
1@Thiruvalluvar: it's not just thread-safety - what if you want to tokenise two different strings at the same time, e.g. in the same loop ? – Paul R Apr 27 '12 at 11:04
-
-
@SSHThis An example is already there in the accepted answer. I don't want to repeat the same. – P.P Dec 14 '12 at 16:24
-
-
-
-
@monamona Noted that in the answer "Here's an example program from the manual" and provided a link too ;) – P.P Mar 08 '23 at 16:19
-
Which I saw to late... and just tried, throws a segmentation fault, when copies 1:1 from the manual. I'm trying to figure out where to create a bug report, you do know know that by coincidence? x) – monamona Mar 08 '23 at 16:22
-
It's likely that the bug is in your usage. See the answer for an example run. If you're certain, it's a bug, you can file at https://bugzilla.kernel.org/ or even submit a patch. See https://www.kernel.org/doc/man-pages/contributing.html for howto. – P.P Mar 08 '23 at 16:40
-
I copied the code from your usage exactly, that's why I was so confused. It seems the error comes from calling strtok every time in the loop while giving it the original string. strtok has to be used rahter like in the Answer from @Andrew down below. – monamona Mar 10 '23 at 05:03
-
@monamona The example is specifically about strtok**_r** which is a re-entrant and better version of strtok. – P.P Mar 10 '23 at 08:20
-
I apologize, I missed that detail.... Your code works fine, no insult was intended. However the code from the manual is actually broken, so I still submitted a bug report. Thanks for your patience <3 – monamona Mar 10 '23 at 11:32
-
One option is strtok
example:
char name[20];
//pretend name is set to the value "My name"
You want to split it at the space between the two words
split=strtok(name," ");
while(split != NULL)
{
word=split;
split=strtok(NULL," ");
}

- 6,254
- 16
- 59
- 93
You could simply replace the separator characters by NULL characters, and store the address after the newly created NULL character in a new char* pointer:
char* input = "asdf|qwer"
char* parts[10];
int partcount = 0;
parts[partcount++] = input;
char* ptr = input;
while(*ptr) { //check if the string is over
if(*ptr == '|') {
*ptr = 0;
parts[partcount++] = ptr + 1;
}
ptr++;
}
Note that this code will of course not work if the input string contains more than 9 separator characters.

- 5,594
- 4
- 34
- 49
I came up with this.This seems to work best for me.It converts a string of number and splits it into array of integer:
void splitInput(int arr[], int sizeArr, char num[])
{
for(int i = 0; i < sizeArr; i++)
// We are subtracting 48 because the numbers in ASCII starts at 48.
arr[i] = (int)num[i] - 48;
}

- 175
- 7
This is how I do it.
void SplitBufferToArray(char *buffer, char * delim, char ** Output) {
int partcount = 0;
Output[partcount++] = buffer;
char* ptr = buffer;
while (ptr != 0) { //check if the string is over
ptr = strstr(ptr, delim);
if (ptr != NULL) {
*ptr = 0;
Output[partcount++] = ptr + strlen(delim);
ptr = ptr + strlen(delim);
}
}
Output[partcount++] = NULL;
}

- 1,134
- 3
- 11
- 12

- 11
- 2
In addition, you can use sscanf
for some very simple scenarios, for example when you know exactly how many parts the string has and what it consists of. You can also parse the arguments on the fly. Do not use it for user inputs because the function will not report conversion errors.
Example:
char text[] = "1:22:300:4444:-5";
int i1, i2, i3, i4, i5;
sscanf(text, "%d:%d:%d:%d:%d", &i1, &i2, &i3, &i4, &i5);
printf("%d, %d, %d, %d, %d", i1, i2, i3, i4, i5);
Output:
1, 22, 300, 4444, -5
For anything more advanced, strtok() and strtok_r() are your best options, as mentioned in other answers.

- 1,778
- 1
- 20
- 28
Solution from mic_e was exactly what I was looking for (Thank you) in order to parse Replies from a SIM7600 Module, including the GPS Data from AT+CGNSSINFO. In my first method I created I used strtok which ignored consecutive delimiters. Since the data from AT+CGNSSINFO could have empty fields (i.e. Course) my Routine did not parse all Data correctly. I changed my method according to mic_e's solution and I have now the desired result including empty fields.
char* parts[16]; // change according to total expected fields
char* split2(char* input, char delimiter, int element, int length = 0){
int partcount = 0;
parts[partcount++] = input;
char* ptr = input;
while (*ptr) { //check if the string is over
if (*ptr == delimiter) {
*ptr = 0;
parts[partcount++] = ptr + 1;
}
ptr++;
}
if (length != 0) {
parts[element][length] = '\0';
}
return parts[element];
}
// TEST
char TEST[85] = { "3,04,00,00,ddmm.mmmmmm,N,dddmm.mmmmmm,E,210323,133128.0,999.9,0.0,,14.3,2.2,14.1" };
for (int i = 0; i < 16; i++)
{
//Serial.print(i); Serial.print("\t"); Serial.println(parts[i]);
Serial.print(i); Serial.print("\t"); Serial.println(split2(TEST,',',i));
}

- 53
- 3