C++ Split String

Split string with delimiters in C

You can use the strtok() function to split a string (and specify the delimiter to use). Note that strtok() will modify the string passed into it. If the original string is required elsewhere make a copy of it and pass the copy to strtok().

EDIT:

Example (note it does not handle consecutive delimiters, "JAN,,,FEB,MAR" for example):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

char** str_split(char* a_str, const char a_delim)
{
char** result = 0;
size_t count = 0;
char* tmp = a_str;
char* last_comma = 0;
char delim[2];
delim[0] = a_delim;
delim[1] = 0;

/* Count how many elements will be extracted. */
while (*tmp)
{
if (a_delim == *tmp)
{
count++;
last_comma = tmp;
}
tmp++;
}

/* Add space for trailing token. */
count += last_comma < (a_str + strlen(a_str) - 1);

/* Add space for terminating null string so caller
knows where the list of returned strings ends. */
count++;

result = malloc(sizeof(char*) * count);

if (result)
{
size_t idx = 0;
char* token = strtok(a_str, delim);

while (token)
{
assert(idx < count);
*(result + idx++) = strdup(token);
token = strtok(0, delim);
}
assert(idx == count - 1);
*(result + idx) = 0;
}

return result;
}

int main()
{
char months[] = "JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC";
char** tokens;

printf("months=[%s]\n\n", months);

tokens = str_split(months, ',');

if (tokens)
{
int i;
for (i = 0; *(tokens + i); i++)
{
printf("month=[%s]\n", *(tokens + i));
free(*(tokens + i));
}
printf("\n");
free(tokens);
}

return 0;
}

Output:

$ ./main.exe
months=[JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC]

month=[JAN]
month=[FEB]
month=[MAR]
month=[APR]
month=[MAY]
month=[JUN]
month=[JUL]
month=[AUG]
month=[SEP]
month=[OCT]
month=[NOV]
month=[DEC]

Parse (split) a string in C++ using string delimiter (standard C++)

You can use the std::string::find() function to find the position of your string delimiter, then use std::string::substr() to get a token.

Example:

std::string s = "scott>=tiger";
std::string delimiter = ">=";
std::string token = s.substr(0, s.find(delimiter)); // token is "scott"
  • The find(const string& str, size_t pos = 0) function returns the position of the first occurrence of str in the string, or npos if the string is not found.

  • The substr(size_t pos = 0, size_t n = npos) function returns a substring of the object, starting at position pos and of length npos.


If you have multiple delimiters, after you have extracted one token, you can remove it (delimiter included) to proceed with subsequent extractions (if you want to preserve the original string, just use s = s.substr(pos + delimiter.length());):

s.erase(0, s.find(delimiter) + delimiter.length());

This way you can easily loop to get each token.

Complete Example

std::string s = "scott>=tiger>=mushroom";
std::string delimiter = ">=";

size_t pos = 0;
std::string token;
while ((pos = s.find(delimiter)) != std::string::npos) {
token = s.substr(0, pos);
std::cout << token << std::endl;
s.erase(0, pos + delimiter.length());
}
std::cout << s << std::endl;

Output:

scott
tiger
mushroom

How to split a string to 2 strings in C

#include <string.h>

char *token;
char line[] = "SEVERAL WORDS";
char *search = " ";

// Token will point to "SEVERAL".
token = strtok(line, search);

// Token will point to "WORDS".
token = strtok(NULL, search);

Update

Note that on some operating systems, strtok man page mentions:

This interface is obsoleted by strsep(3).

An example with strsep is shown below:

char* token;
char* string;
char* tofree;

string = strdup("abc,def,ghi");

if (string != NULL) {

tofree = string;

while ((token = strsep(&string, ",")) != NULL)
{
printf("%s\n", token);
}

free(tofree);
}

Split string by a substring

I known strtok() but it just split by one character as delimiter

Nopes, it's not.

As per the man page for strtok(), (emphasis mine)

char *strtok(char *str, const char *delim);

[...] The delim argument specifies a set of bytes that delimit the tokens in the parsed string. [...] A sequence of two or more contiguous delimiter bytes in the parsed string is considered to be a single delimiter. [...]

So, it need not be "one character" as you've mentioned. You can using a string, like in your case "/USING=" as the delimiter to get the job done.

How can I split a C-string twice with strtok in C?

strtok accepts multiple delimiters, and since your data structure seems to not care whether the current element is a ',' or a '#' character (in other words, you're not building a 2d structure requiring nested looping), you can just provide a delimiter string and make one call to strtok in the loop.

Here's a minimal example you can adapt to your environment:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
char delimiters[] = "#,";
char text[] = "0.4,0.1,-4.1#100,200,300#-32.13,23.41,100#20,25,30";
int size = 3 * 4; // or 3 * 17;
float res[size];
res[0] = atof(strtok(text, delimiters));

for (int i = 1; i < size; i++) {
res[i] = atof(strtok(NULL, delimiters));
}

for (int i = 0; i < size; i++) {
printf("%.2f ", res[i]);
}

puts("");
return 0;
}

Output:

0.40 0.10 -4.10 100.00 200.00 300.00 -32.13 23.41 100.00 20.00 25.00 30.00

It's a good idea to check the return value of strtok in the above code.

If you want to avoid strtok (there are good reasons to), there's strtok_r or write it by hand with a loop:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
char delimiters[] = "#,";
char text[] = "0.4,0.1,-4.1#100,200,300#-32.13,23.41,100#20,25,30";
int size = 3 * 4; // or 3 * 17;
float res[size];
int res_size = 0;
int last_index = 0;

for (int i = 0, len = strlen(text); i < len; i++) {
if (!strchr(delimiters, text[i])) {
continue;
}
else if (i - last_index >= 32 || res_size >= size) {
fprintf(stderr, "buffer size exceeded\n");
return 1;
}

char buf[32] = {0};
strncpy(buf, text + last_index, i - last_index);
res[res_size++] = atof(buf);
last_index = i + 1;
}

for (int i = 0; i < res_size; i++) {
printf("%.2f ", res[i]);
}

puts("");
return 0;
}

Trying to split a string in C by a space and use the second word

For your use case you should be using

char *strstr(const char *haystack, const char *needle);

it finds the substring in the provided string.

For example:

char receive[1024];
int read = recv(client_socket, &receive, 1024, 0);
receive[read] = '\0';

if (strstr(receive, "user")) {
printf("User has requested chat with....");
}

Is there a function to split by the FIRST instance of a delimiter in C?

The first time you call strtok, use the delimiter you want to split with.

For the second call, use an empty delimiter string (if you really want the rest of the string) or use "\n", in the case that your string might include a newline character and you don't want that in the split (or even "\r\n"):

    const char* first = strtok(buf, ":");
const char* rest = strtok(NULL, "");
/* or: const char* rest = strtok(NULL, "\n"); */

Splitting a string and using index to call the desired element

You can store the last two items in an array and print the second last item.

[...]
char delim[] = ".";
char *lastElement[2] = {0}; /* 1. To store delimited items */

char *ptr = strtok(str, delim);

while(ptr != NULL)
{
lastElement[0] = lastElement[1]; /* 2. Update */
lastElement[1] = ptr;
printf("'%s'\n", ptr);
ptr = strtok(NULL, delim);
}
if(lastElement[0]) { /* 3. Does second last item exist */
printf("%s\n", lastElement[0]); /* 4. Second last item */
}
[...]

Check on ideone

This idea can be extended to get any arbitrary element also.

C - split string into an array of strings

Since you've already looked into strtok just continue down the same path and split your string using space (' ') as a delimiter, then use something as realloc to increase the size of the array containing the elements to be passed to execvp.

See the below example, but keep in mind that strtok will modify the string passed to it. If you don't want this to happen you are required to make a copy of the original string, using strcpy or similar function.

char    str[]= "ls -l";
char ** res = NULL;
char * p = strtok (str, " ");
int n_spaces = 0, i;

/* split string and append tokens to 'res' */

while (p) {
res = realloc (res, sizeof (char*) * ++n_spaces);

if (res == NULL)
exit (-1); /* memory allocation failed */

res[n_spaces-1] = p;

p = strtok (NULL, " ");
}

/* realloc one extra element for the last NULL */

res = realloc (res, sizeof (char*) * (n_spaces+1));
res[n_spaces] = 0;

/* print the result */

for (i = 0; i < (n_spaces+1); ++i)
printf ("res[%d] = %s\n", i, res[i]);

/* free the memory allocated */

free (res);

res[0] = ls
res[1] = -l
res[2] = (null)


Related Topics



Leave a reply



Submit