Thread: Question about strtok function.

  1. #1
    Registered User
    Join Date
    Sep 2011
    Location
    Athens , Greece
    Posts
    357

    Question about strtok function.

    Hello to all. I have a specific question about strtok.

    Assuming that we have the string :

    Code:
     ***HELLO&SIR.\0
    & and * is the delimiters. My question is how strtok will work in the beginning?

    According to this

    To determine the beginning and the end of a token, the function first scans from the starting location for the first character not contained in delimiters (which becomes the beginning of the token). And then scans starting from this beginning of the token for the first character contained in delimiters, which becomes the end of the token. The scan also stops if the terminating null character is found.

    This end of the token is automatically replaced by a null-character, and the beginning of the token is returned by the function.


    strtok will replace the first * with '\0' and the next call will start from the second * puts '\0' there and again the same with the third * ?

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    No. It scans OVER the chars which are delimiters. You should try it however, and see what it does. That's the beauty of a computer program. Small checks, are easily made and tested.
    Last edited by Adak; 11-28-2013 at 04:03 PM.

  3. #3
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    For your case, strtok will scan past the three asterisks, remember that location, then scan until it finds another delimiter (or '\0'), null-terminate at that point and return the remembered location.

    If you want (at least) some of your delimiters to also be tokens (as is the case in C syntax, for example) then you can't use strtok, since it overwrites some of the delimiters.
    Last edited by oogabooga; 11-28-2013 at 04:15 PM.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  4. #4
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    For this reason strtok is kind of annoying to use. Depending on what you need you probably should make some utility funtions for calling it. For example this utility function will print the tokens returned by strtok along with the delimiters which were removed in between

    Code:
    void chop_string(const char *input_string, const char *delim)
    {
        char *token;
        char *str;
        char *temp_string = strdup(input_string);
    
        for (str = temp_string;
             (token = strtok(str, delim)) != NULL;
             str = NULL)
        {
            // print delimiter if applicable
            size_t pos;
            if ((pos = token - temp_string) > 0) {
                printf("delimiter: '%c'\n", input_string[pos-1]);
            }
            // print token
            printf("%s\n", token);
        }
        free(temp_string);
    }
    
    int main(void)
    {
        chop_string("one,two.three!four:five", ".,:!");
        return 0;
    }

  5. #5
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    @c99tut,
    Why not just write your own strtok that returns the token-ending delimiter?

    Code:
    #include <stdio.h>
    #include <string.h>
    
    char *
    my_strtok(
        char * str,
        const char * delims,
        char * del)
    {
        static char * start = NULL, * end = NULL;
    
        if (str)
            start = end = str;
        else if (end == NULL)
            return NULL;
        else
            start = end + 1;
    
        start += strspn(start, delims);
    
        end = strpbrk(start, delims);
        if (end) {
            *del = *end;
            *end = '\0';
        }else
            *del = '\0';
    
        return start;
    }
    
    
    int
    main()
    {
        char str[] = "***NO&SIR**I&DON'T&&LIKE*IT!";
        char *p, del;
    
        p = my_strtok(str, "*&", &del);
    
        while (p) {
            printf("%s\t", p);
            if (del)
                printf("{%c}\n", del);
            else
                printf("{null}\n");
            p = my_strtok(NULL, "*&", &del);
        }
    
        return 0;
    }
    Output:
    Code:
    NO      {&}
    SIR     {*}
    I       {&}
    DON'T   {&}
    LIKE    {*}
    IT!     {null}
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  6. #6
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    Quote Originally Posted by oogabooga View Post
    @c99tut,
    Why not just write your own strtok that returns the token-ending delimiter?
    Personally I don't find strtok intuitive or clear for the user code. Look at the main function and see what is trying to do. Is it clear what is happening? I would like to replace the printf statements from my previous version with a return statement to return the code. Then, by using the header file here (Coroutines in C) for coroutines, I can substitute the printf calls for return statements

    Code:
    #include "coroutine.h"
    char *next_token(ccrContParam, const char *input_string, const char *delim)
    {
        ccrBeginContext;
        char *token;
        char *str;
        char *temp_string;
        char *returnstr;
        ccrEndContext(cc);
        
        ccrBegin(cc);
        cc->temp_string = strdup(input_string);
        for (cc->str = cc->temp_string;
            (cc->token = strtok(cc->str, delim)) != NULL;
            cc->str = NULL)
        {
            // output delimiter if applicable
            size_t pos;
            if ((pos = cc->token - cc->temp_string) > 0) {
                char c[2];
                c[0] = input_string[pos-1];
                c[1] = '\0';
                cc->returnstr = strdup(c);
                ccrReturn(cc->returnstr);
                free(cc->returnstr);
            }
            // output token
            cc->returnstr = strdup(cc->token);
            ccrReturn(cc->returnstr);
            free(cc->returnstr);
        }
        free(cc->temp_string);
        ccrFinish(NULL);
    }
    It looks strange at first but notice the only difference is the printf is replaced by ccrReturn. I find it an advantage that main can just get tokens without having to care about a NULL parameter or whatever such nonsense

    Code:
    int main(void)
    {
    	const char str[] = "***NO&SIR**I&DON'T&&LIKE*IT!";
    	const char delim[] = "*&";
    	ccrContext cc = 0;
    	do {
    		char *token = next_token(&cc, str, delim);
    		printf("%s\n", token);
    	} while (cc);
    	
    	return 0;
    }

  7. #7
    Registered User
    Join Date
    Sep 2011
    Location
    Athens , Greece
    Posts
    357
    Quote Originally Posted by Adak View Post
    No. It scans OVER the chars which are delimiters. You should try it however, and see what it does. That's the beauty of a computer program. Small checks, are easily made and tested.
    I have tried the strtok. I have understood what it does of course. My problem is with the input that starts with *** characters. Sorry I am greek native speaker and I don't understand the phrasal verb "scan over" really sorry.

  8. #8
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by Mr.Lnx View Post
    I have tried the strtok. I have understood what it does of course. My problem is with the input that starts with *** characters. Sorry I am greek native speaker and I don't understand the phrasal verb "scan over" really sorry.
    There are code examples up above, have you run them yet? Do they meet your requirements?

    scan over means to move across, checking the data as you go.

    According to Google translation:
    σάρωση πάνω από τα μέσα που μετακινούνται εκτός, τον έλεγχο των δεδομένων καθώς πηγαίνετε.
    Which I assure you, is Greek to me! <ROFL!>

    I'm not a huge fan of strtok(), but if it fits your needs, use it of course. Otherwise, feel free to write your own function. Don't feel you must use strtok() only. There's always another way to do these tasks.

  9. #9
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Quote Originally Posted by Adak View Post
    scan over means
    According to Google translation:
    Code:
    戰國策·秦策三 范雎至秦 一段漏字
    范睢至秦,王庭迎,謂范睢曰:「寡人宜以身受令久矣。今者義渠之事急,寡人日自請太后。今義渠之事已,寡人
    Which I assure you, is Greek to me! <ROFL!>
    And Chinese to him! ;p

    Some real Greek here, in case the OP hasn't got it yet.
    Η strtok() θα διατρέξει ένα-ένα τα στοιχεία της συμβολοσειράς. Αυτό εννοεί ο Adak scan over.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Doubt about strtok function
    By ShashiKantSuman in forum C Programming
    Replies: 1
    Last Post: 03-04-2013, 05:03 PM
  2. strtok in function problem
    By ehitam in forum C Programming
    Replies: 13
    Last Post: 06-10-2012, 01:44 AM
  3. strtok function
    By Omnipotent in forum C Programming
    Replies: 7
    Last Post: 04-03-2011, 08:12 PM
  4. need to get a function pointer to strtok in the DLL
    By Anddos in forum C++ Programming
    Replies: 8
    Last Post: 02-04-2009, 04:42 PM
  5. strtok function
    By hello124 in forum C++ Programming
    Replies: 8
    Last Post: 04-23-2005, 06:58 AM