17

My string is "A,B,C,D,E"
And the separator is ","
How can I get the remaining string after doing strtok() once, that is "B,C,D,E"

char a[] = "A,B,C,D,E";
char * separator = ",";
char * b = strtok(a,separator);
printf("a: %s\n", a);
printf("b: %s\n", b);

The output is:
a: A
b: A

But how to get the result
a: B,C,D,E
b: A

Thanks.

Eric Tseng
  • 553
  • 3
  • 8
  • 22

7 Answers7

27

You can vary the set of delimiters, so simply pass an empty string:

char a[] = "A,B,C,D,E";
char * separator = ",";
char * b = strtok(a, separator);
printf("b: %s\n", b);
char * c = strtok(NULL, "");
printf("c: %s\n", c);
Neil
  • 54,642
  • 8
  • 60
  • 72
  • 2
    **Passing no delimiter is the way to go!** In my case, I have used `strtok` more than once, and at some point I needed the remainder. So **not** using `strtok` was not a solution. Neither summing characters because I was `toking` on space, and it could contain a variable number of consecutive spaces, etc. – Paschalis Jun 23 '15 at 13:35
12

Don't use strtok() for this, since that's not what it's for.

Use strchr() to find the first separator, and go from there:

char a[] = "A,B,C,D,E";
const char separator = ',';
char * const sep_at = strchr(a, separator);
if(sep_at != NULL)
{
  *sep_at = '\0'; /* overwrite first separator, creating two strings. */
  printf("first part: '%s'\nsecond part: '%s'\n", a, sep_at + 1);
}
unwind
  • 391,730
  • 64
  • 469
  • 606
1

Try this:

char a[] = "A,B,C,D,E";
char * end_of_a = a + strlen(a); /* Memorise the end of s. */
char * separator = ",";
char * b = strtok(a, separator);
printf("a: %s\n", a);
printf("b: %s\n", b);

/* There might be some more tokenising here, assigning its result to b. */

if (NULL != b)
{
  b = strtok(NULL, separator);
}

if (NULL != b)
{ /* Get reference to and print remainder: */
  char * end_of_b = b + strlen(b);

  if (end_of_b != end_of_a) /* Test whether there really needs to be something, 
                        will say tokenising did not already reached the end of a, 
                        which however is not the case for this example.  */
  {
    char * remainder = end_of_b + 1;
    printf("remainder: `%s`\n", remainder);
  }   
}
alk
  • 69,737
  • 10
  • 105
  • 255
1

strtok remembers the last string it worked with and where it ended. To get the next string, call it again with NULL as first argument.

char a[] = "A,B,C,D,E";
const char *separator = ",";
char *b = strtok(a, separator);
while (b) {
    printf("element: %s\n", b);
    b = strtok(NULL, separator);
}

Note: This is not thread safe.

Atle
  • 1,867
  • 12
  • 10
0

If using strtok is not a requirement, you can use strchr instead since the separator is a single character:

char a[] = "A,B,C,D,E";
char *sep = strchr(a, ',');
*sep = '\0';
puts(a);
puts(sep + 1);
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
0

printf("a: %s\n", a+1+strlen(b));

Try this

nav_jan
  • 2,473
  • 4
  • 24
  • 42
  • Please see *larsmans* comments to *dasblinkenlight*'s answer on this approach. It as well applies to your answer. – alk Nov 01 '13 at 10:09
0

There's much better ways to work with ip addresses, but this is a practical example of needing to change delimeter at a certain point during execution from '.' to '/'.

struct Ip split_ip_by_octet(char ip_string[]) {

    struct Ip ip;
    char * value_before_delimeter = strtok(ip_string, "."); // N. 

    if (value_before_delimeter != NULL) {
        sscanf(value_before_delimeter, "%d", &ip.octet_1);
        value_before_delimeter = strtok(NULL, ".");        // n.N.

        sscanf(value_before_delimeter, "%d", &ip.octet_2);
        value_before_delimeter = strtok(NULL, ".");        // n.n.N.n/n

        sscanf(value_before_delimeter, "%d", &ip.octet_3);
        value_before_delimeter = strtok(NULL, "/");        // n.n.n.N/n

        sscanf(value_before_delimeter, "%d", &ip.octet_4);
        value_before_delimeter = strtok(NULL, "");         // n.n.n.n/N

        sscanf(value_before_delimeter, "%d", &ip.mask);
    }
    return ip; 
}
b0bu
  • 1,062
  • 1
  • 9
  • 24