Assume that we have a C string
text = "0.4,0.1,-4.1#100,200,300#-32.13,23.41,100#<...>#20,25,30"
The goal is to split that string first with #
and then ,
because I'm after each values between #
and there are three separate values between ,
.
The string text
contains 17 elements of 3 numbers with separator ,
and 16 elements of #
I did try to solve this with this code.
char *min_max_bias_char;
float min_max_bias_float[3*17]; /* 3 values per each analog input channel */
for(uint8_t i = 0; i <= 16; i++) {
if(i == 0)
min_max_bias_char = strtok(text, DELIMITER);
else
min_max_bias_char = strtok(NULL, DELIMITER);
min_max_bias_float[0 + i*3] = atoff(strtok(min_max_bias_char, ",")); /* Min value */
min_max_bias_float[1 + i*3] = atoff(strtok(NULL, ",")); /* Max value */
min_max_bias_float[2 + i*3] = atoff(strtok(NULL, ",")); /* Bias value */
}
Where I first split the text string text
depending on #
and then I take the first index of min_max_bias_char
and split that on the delimiter ,
.
This did not work out very well because as soon I do strtok(min_max_bias_char)
then strtok
forget about the min_max_bias_char = strtok(NULL, DELIMITER);
statement.
Now I got the array min_max_bias_float
that holds the values inside of an array {0.4,0.1,-4.1,100,200,300,-32.13,23.41,100,<...>,20,25,30}
This is the output. So how can I solve this issue? I'm trying to split string twice.
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;
}