I made a string separator below. It's like strtok, but it separates based on entire strings instead of single char delimiters. Any comments/answers on how I could improve the performance or readability would be great. I'm also leaking some memory according to valgrind, but that is only a minor concern for my use case.
It takes two char arrays, a buffer(string?) and a separator. It returns an array of strings containing all of the separated strings. For example, if the buffer is foobar
and the separator is foo
, it'll return {"bar", NULL}
. But if I'm passed foobarfoobarfoobar
and the separator is bar
, it'll return {"foo", "foo", "foo", NULL}
.
Edit: Comments added to clarify intended functionality.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char **sepstr(const char *buf, const char *sep){
int i = 0, j = 0, k = 0, l = 0, stringCount = 0;
/* If separator > buffer, return NULL */
while (buf[i]) i++;
while (sep[j]) j++;
if (j > i) return NULL;
char **strings = malloc(0);
/* While we're not at the end of the buffer */
while (*(buf+k)){
/* If the characters match, check to see if it is the separator */
if (*(buf+k) == *(sep)){
for (l = 0; l < j; l++){
/* If it isn't the separator, break */
if (*(buf+k+l) != *(sep+l)) break;
/* If it is the separator and the separator isn't the
beginning, add buf to buf+k bytes as a string */
if (l == j-1 && k != 0){
strings = realloc(strings, (stringCount+1)*sizeof (char *));
strings[stringCount] = malloc(k+1);
memcpy(strings[stringCount++], buf, k);
buf += (j + k), k = -1;
/* If it is the separator, but it's the beginning
of the string, skip it */
} else if (l == j-1 && k == 0) {
buf += j, k = -1;
}
}
}
k++;
}
/* Add a string for the left over bytes if sep isn't the end */
if (i != k && *(buf)){
while (buf[l]) l++;
strings = realloc(strings, (stringCount+1) * sizeof (char *));
strings[stringCount] = malloc(l+1);
memcpy(strings[stringCount++], buf, l);
}
/* Append NULL to array of strings */
strings = realloc(strings, (stringCount+1) * sizeof (char *));
strings[stringCount] = malloc(sizeof NULL);
strings[stringCount] = NULL;
return strings;
}
int main(){
const char buffer[] = "foobarfoobarfoobar";
const char separator[] = "bar";
char **strings = sepstr(buffer, separator);
while(*strings){
printf("%s\n", *(strings));
free(*(strings++));
}
free(strings);
return 0;
}
for (l = 0; l < k; l++) strings[stringCount][l] = *(buf+l);
to remove dependency onstring.h
and removestring.h
. \$\endgroup\$