views:

150

answers:

5
+4  Q: 

Double split in C

OK. For example I have this line in my txt file:

1|1,12;7,19;6,4;8,19;2,2
As you can see, it has 2 parts, separated by |. I have no problems getting both parts, and separating second part 1,12;7,19;6,4;8,19;2,2 using ; separator. BUT I do have problems with separating further by , to get first and second number of each set.

This is my current code:

  result = strtok(result, ";");

  while(result != NULL ) {
      printf("%s\n", result);
      result = strtok(NULL, ";");
  }

It outputs me:

1,12
7,19
6,4
8,19
2,2

OK, great. But when I try to 'strtok' (I'm using this method for splitting) like this:

 result = strtok(result, ";");

 while(result != NULL ) {
     //printf("%s\n", result);
     help    = strtok(result, ",");    
     while(help != NULL) {
         printf("<%s>", help);
         help = strtok(NULL, ",");
     }

     result  = strtok(NULL, ";");
 }

I only get "<1>,<12>" like there is only one set in this set of numbers. I dont understand where are the rest of the numbers. Instead, output should be: <1>,<12>,<7>,<19>,<6>,<4>,<8>,<19>,<2>,<2>. Could someone please give a solution, how to get EACH number of each set this set of numbers. Maybe there are other methods or I'm doing something wrong :)

Thank you!

+2  A: 

char *strtok(char *str, const char *delim); (from man pages)
The delim argument specifies a set of characters that delimit the tokens in the parsed string. The caller may specify different strings in delim in successive calls that parse the same string.

So, use both ; and , as delimiter to get all the numbers.

//this will delimit result whenever ";" or "," is found
result = strtok(result, ";,"); 

while(result != NULL ) {
    printf("%s\n", result);
    result = strtok(NULL, ";,");
}
N 1.1
+1  A: 

The first strtok splits the original into several null terminated strings. The second strtok is only applied to the first of these strings - it stops at the first null-terminator created by the first strtok call. You need to call the second strtok code for EACH of the strings created by the first.

anon
+4  A: 

In addition to what Neil pointed out regarding modifying the original string, the strtok() function is not designed to be used in a nested manner like you describe. You may wish to investigate the strtok_r() function, or avoid the use of the strtok* family altogether.

Greg Hewgill
+1, for pointing the nested limitation.
codaddict
A: 

C's strtok is pretty evil in that it modifies the source string, inserting NULL in place of your separator. Thus your second loop stops when it reaches the NULL inserted by the outer loop. What you want is to save the pointers to your ;-separated strings somewhere else, and then strtok each of them separately.

Or, if you do want to use nested loops, see here.

Mihai
Wow. Thanks guys! Works great! Never thought it was so simple.
Dmitri
A: 

As others have pointed out, strtok() isn't reentrant - it maintains internal state about the string it's parsing, so it can't be used to parse two different strings simultaneously (which means two different non-NULL values for its first argument, so your situation counts).

If you have the reentrant version strtok_r() available, you can change your code to use it like so:

char *st_result, *st_help;
result = strtok_r(result, ";", &st_result);

while (result) {
     printf("[%s]", result);
     help = strtok_r(result, ",", &st_help);    
     while (help) {
         printf("<%s>", help);
         help = strtok_r(NULL, ",", &st_help);
     }

     result = strtok_r(NULL, ";", &st_result);
}
caf