strtok wont accept: char *str
Asked Answered
C

3

4

strtok wont work correctly when using char *str as the first parameter (not the delimiters string).

Does it have something to do with the area that allocates strings in that notation? (which as far as i know, is a read-only area).

thanks in advance

example:

//char* str ="- This, a sample string.";   // <---doesn't work
char str[] ="- This, a sample string.";   // <---works
char delims[] = " ";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str,delims);
while (pch != NULL)
{
  printf ("%s\n",pch);
  pch = strtok (NULL, delims);
}
return 0;
Clite answered 27/3, 2010 at 15:31 Comment(0)
S
7

In the first case, you pass a string literal to strtok(). As strtok() modifies this string, and as string literals cannot legally be modified, you end up with undefined behaviour. In the second case, the compiler copies the string into the array. Array contents can be modified, so this code is OK.

Solemnize answered 27/3, 2010 at 15:35 Comment(1)
i see. wasn't aware of that behavior of the function. thank youClite
P
2

strtok modifies its 1st argument.

In your case 1 the argument to strtok is a string literal which cannot be modified and hence strtok fails . But in case 2 the argument is a modifiable char array which strtok modifies and breaks into smaller strings.

Parboil answered 27/3, 2010 at 15:32 Comment(1)
i see. well, you and the other guy were very helpful, thanks.Clite
C
0

here is a code, all aspect should be pationed.

  • getting char pointer
  • using strdup for using char pointer in strtok_r
  • using strtok_r to be threadsafe
  • free result strdup when were done cuz it uses malloc inside

give me a hint if i forgot anything

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

#define WHITE " \t\n" // white space, tab and newline for tokenizing arguments
#define MAXARGC 50 // max number of arguments in buf 

void handlecommand(int argc, char *argv[])
{
    // do some handle code, in this example, just print the arguments
    for(int i = 0; i < argc; i++)
        printf("argv[%d]='%s'\n", i, argv[i]);
}

void parsecommand(char * cmdstr)
{
    char *cmdstrdup = strdup(cmdstr);
    if(cmdstrdup == NULL)
      //insuficient memory, do some errorhandling. 
      return; 
    char *saveptr;
    char *ptr;
    char *argv[MAXARGC]; 
    int argc;

    if((ptr = strtok_r(cmdstrdup, WHITE, &saveptr)) == NULL)
    {
        printf("%s\n", "no args given");
        return;
    } 

    argv[argc = 0] = cmdstrdup;
    while(ptr != NULL) {
        ptr = strtok_r(NULL, WHITE, &saveptr);
        if(++argc >= MAXARGC-1) // -1 for room for NULL at the end
            break;
        argv[argc] = ptr;
    }

    // handle command before free
    handlecommand(argc, argv);

    // free cmdstrdup, cuz strdup does malloc inside
    free(cmdstrdup);
}

int main(int argc, char const *argv[])
{
    parsecommand("command arg1 arg2 arg3\targ4\narg5 arg6  arg7");
    return 0;
}

Result

argv[0]='command'
argv[1]='arg1'
argv[2]='arg2'
argv[3]='arg3'
argv[4]='arg4'
argv[5]='arg5'
argv[6]='arg6'
argv[7]='arg7'
Canoewood answered 11/4, 2015 at 22:23 Comment(2)
Your answer has a lot of unnecessary story in it, the backpack, when you started programming, etc., you might try to minimize that. You could also work on spelling and capitalization. I know that you like the book you're reading, but using the header file provided with it makes your code sample hard to run as is, you might prefer standard includes. And last, but not least, if you're going to answer a 5 year old question don't say you haven't tested your code. It waited 5 years, it can wait a little longer for you to test.Vulgarize
thx for your critic. removed unuseful story, testet the program, added required header.Canoewood

© 2022 - 2024 — McMap. All rights reserved.