-7

My input string is 1,2,3:4,5,6:7,5,8 First I need to split 1, 2, 3 set wit : delimiter. Then again I need to split 1 2 3 with , delimiter. So I need to do outer split and inner split till the end of input string.. Please explain me with some example

Bhuvana
  • 1
  • 2
  • `strtok`use it. – user2736738 Dec 28 '17 at 18:28
  • 3
    Welcome to Stack Overflow! Kindly show your research / debugging effort so far. Please read [Ask] page first. – Sourav Ghosh Dec 28 '17 at 18:28
  • Here is a similar post you might find useful: https://stackoverflow.com/questions/9210528/split-string-with-delimiters-in-c – Junk junk Dec 28 '17 at 18:30
  • Second iteration strtok gives segments fault – Bhuvana Dec 28 '17 at 18:36
  • Using `strtok()` for this is a path to insanity if you are not careful. You can’t nest sequences of calls. You could split on colons and save each of three pointers, and then iterate over each of the saved pointers with commas. Are you only dealing with 3x3 splits, or could you have 20 colons and 1-30 commas in each? – Jonathan Leffler Dec 28 '17 at 18:40
  • "*need to split 1:2:3*": There is no "*1:2:3*" in your input. At least as per what you are writing. – alk Dec 28 '17 at 18:49
  • @JonathanLeffler if you need to nest `strtok`, then you should use `strtok_r` which is a reentrant version of `strtok`. Either way, you're right, you have to be careful with these functions. – Pablo Dec 28 '17 at 18:49
  • 13 commas in each ( 13 fields in each set), but colons depends on the input received (not fixed) . Need to split the entire string into sets with : delimiter, then needs to split each set with , delimiter.. Each set have only 13 fields. So after splitting this 13 fields, need to put it in a structure. – Bhuvana Dec 28 '17 at 18:51
  • @Bhuvana you have 13 columns in total and where the `:` appears is random? On each line? Can you post two or three actual lines of your input? – Pablo Dec 28 '17 at 18:54
  • @Pablo: yes to `strtok_r()` on POSIX or`strtok_s()` on Windows. Or use `strcspn()` and maybe `strspn()`, or perhaps `strpbrk()`. These don’t mutilate the source string, so I prefer them (meaningful error reporting is easier, all else apart). – Jonathan Leffler Dec 28 '17 at 18:58
  • input string cintains some sets. Sets are separated by :delimiter, each set have 13 fields, these 13 fields are separated by , delimiter. First I need to extract set 1, then extract each fields of set, will put it in one structure. Then need to extract the set 2, then 13 fields of set 2... Similarly need to loop through the end of string – Bhuvana Dec 28 '17 at 19:03
  • Possible duplicate of [Split string with delimiters in C](https://stackoverflow.com/questions/9210528/split-string-with-delimiters-in-c) – dandan78 Dec 28 '17 at 19:18
  • @Bhuvana I've made an update of my example with nested `strtok`s. – Pablo Dec 28 '17 at 20:30

1 Answers1

3

As coderredoc says, strtok is the function you need.

#include <string.h>
char *strtok(char *str, const char *delim);

But strtok have some quirks you have to remember:

  1. Only in the first call you have to pass the source (str), subsequent calls of strtok must be passed with NULL

  2. Strtok modifies the source. Do not use unmodifiable strings or string literal ("this is a string literal")

  3. Because of the previous point, you should always do a copy of the source.

Simple example

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

int main(void)
{
    const char *text = "Hello:World:!";

    char *tmp = strdup(text);
    if(tmp == NULL)
        return 1; // no more memory

    char *token = strtok(tmp, ":");

    if(token == NULL)
    {
        free(tmp);
        printf("No tokens\n");
        return 1;
    }

    printf("Token: '%s'\n", token);

    while(token = strtok(NULL, ":"))
        printf("Token: '%s'\n", token);

    free(tmp);

    return 0;
}

Expected output

Token: 'Hello'
Token: 'World'
Token: '!'

Update

If you need to nest strtok, you should use strtok_r as mentioned before. Here is an update of my example above. If I'm not mistaken, input will have the same format as yours (more or less, mine has different set sizes, but same principle)

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

int main(void)
{
    const char *input ="v1,v2,v3,v4,v5:w1,w2,w3,w4,w5:x1,x2,x3,x4:y1,y2,y3,y4,y5,y6";

    char *input_copy = strdup(input);
    char *set_track, *elem_track;  // keep track for strtok_r
    char *set, *value;

    char *_input = input_copy;

    int setnum = 0;

    while(set = strtok_r(_input, ":", &set_track))
    {
        _input = NULL; // for subsequent calls of strtok_r

        printf("Set %d contains: ", ++setnum);

        // in this case I don't care about strtok messing with the input
        char *_set_input = set; // same trick as above
        while(value = strtok_r(_set_input, ",", &elem_track))
        {
            _set_input = NULL; // for subsequent calls of strtok_r
            printf("%s, ", value);
        }

        puts("");
    }

    free(input_copy);
    return 0;
}

Expected output

Set 1 contains: v1, v2, v3, v4, v5, 
Set 2 contains: w1, w2, w3, w4, w5, 
Set 3 contains: x1, x2, x3, x4, 
Set 4 contains: y1, y2, y3, y4, y5, y6, 
Pablo
  • 13,271
  • 4
  • 39
  • 59