behaviour of strtok()

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • raphael1
    New Member
    • Mar 2010
    • 4

    behaviour of strtok()

    I made some tests and noticed that after the function that call strtok() finish, the strings generated by strtok() doesnt exist anymore. Why it hapens and how to work around?
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    strtok doesn't generate any strings, it just mangles and returns pointers into the middle of the string you provide to it on the first call.

    Are you allocating temporary memory in your function and freeing it? Because that would explain the behaviour you describe. Alternitively post your code.

    Comment

    • raphael1
      New Member
      • Mar 2010
      • 4

      #3
      Thanks, I understood this part.

      Now I'd like to know why i get a segmentation fault when passing the variable text to function split.

      Code:
      char** split(char* text) {
      
          char **array = malloc(sizeof(char*)*50);
          int loop;
      
          array[0]= strtok(text," -:!");
      
          if(array[0]==NULL)
          {
            printf("No test to search.\n");
            exit(0);
          }
      
          for(loop=1;loop<50;loop++)
          {
            array[loop]=strtok(NULL," -:!");
            if(array[loop]==NULL)
              break;
         }
      
         return array;
      }
      
      int main(void) {
      
          char* text = "Rio2010 – Copa do mundo: Brasil!";
          char** array = split(text);
          int loop;
      
          for(loop=0;loop<50;loop++)
          {
            if(array[loop]==NULL)
              break;
            printf("Item #%d is %s.\n",loop,array[loop]);
          }
      
          return 0;
      }
      When I use malloc, it work properly

      Code:
      char *texto = malloc(sizeof(char)*33);
        texto[0] = 'R';
        texto[1] = 'i';
        texto[2] = 'o';
        texto[3] = '2';
        texto[4] = '0';
        texto[5] = '1';
        texto[6] = '0';
        texto[7] = ' ';
        texto[8] = '-';
        texto[9] = ' ';
        texto[10] = 'C';
        texto[11] = 'o';
        texto[12] = 'p';
        texto[13] = 'a';
        texto[14] = ' ';
        texto[15] = 'd';
        texto[16] = 'o';
        texto[17] = ' ';
        texto[18] = 'm';
        texto[19] = 'u';
        texto[20] = 'n';
        texto[21] = 'd';
        texto[22] = 'o';
        texto[23] = ':';
        texto[24] = ' ';
        texto[25] = 'B';
        texto[26] = 'r';
        texto[27] = 'a';
        texto[28] = 's';
        texto[29] = 'i';
        texto[30] = 'l';
        texto[31] = '!';
        texto[32] = '\0';

      Comment

      • Banfa
        Recognized Expert Expert
        • Feb 2006
        • 9067

        #4
        That is because test points to a character constant "Rio2010 – Copa do mundo: Brasil!". On a lot of platforms character constants are actually constant so an attempt to modify them is an error and strtok would attempt to modify the string passed to it.

        Generally it is best to declare pointers to character constants as

        const char* text = "Rio2010 – Copa do mundo: Brasil!";

        to void this issue, the const on the pointer will cause a compiler error if passed to a function expecting a non-const pointer.

        You don't get the error when you malloc because you has allocated writable data to contain the string. There are other ways to do this

        char* text = strdup("Rio2010 – Copa do mundo: Brasil!");

        Also allocates the data on the heap (similarly to malloc) but also does the copy for you. The pointer returned from strdup should be free'd. Or you could put the data on the stack like this

        char text[] = "Rio2010 – Copa do mundo: Brasil!";

        This allocates an array on the stack, the compiler automatically calculates the size for you and initialises the array as well.

        Comment

        • raphael1
          New Member
          • Mar 2010
          • 4

          #5
          Thank you again, Banfa.

          One more thing, inside the function split, I'd like to to alocate memory for the array according to the number of substrings. There is a way to do this?

          Comment

          • Banfa
            Recognized Expert Expert
            • Feb 2006
            • 9067

            #6
            Bot easily and if you did you would have to have a way to pass that number back to the caller. You could do something link parse the string twice, the first time counting the number of resulting strings and the second time creating your array. Or you could use realloc to repeatedly increase the size of the array as required but this would be very in efficient if the array ended up being large.

            Alternatively you could do something like return a link list rather than an array.

            Comment

            • raphael1
              New Member
              • Mar 2010
              • 4

              #7
              Thank you. I'm gonna use the realloc. I think it's better for my case.

              Comment

              Working...