简体   繁体   中英

how to effectively use strtok function

Yes, I'm a newbie as well. And I have been having this problem for quite some time. I'm trying to use strtok to split off a string, but the thing is it does not work. I have looked at the example on the man-pages as well as those online, and I still don't have the answer.

In the code below, I tried to use the sample code given as an answer in this site. The original while loop is:

    char str[] = "hello world how are you?\n";
    char *res;

    res = strtok(str, " \n");
    puts(res);
    while (res != NULL)
    {
        res = strtok(NULL, " \n");
        if(res!=NULL)
            puts(res);
    }

but when a change the str to data, and its respective delimiters (&=), it becomes a Segmentation Fault. How do I fix this? What's wrong in the code? Here is the complete code.

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

int main()
{
    char *data;

    data = "integer1=1&integer2=2&integer3=3&integer4=4";
    puts(data);

    char str[] = "hello world how are you?\n";
    char *res;

    res = strtok(data, "=&");
    puts(res);
    while (res != NULL)
    {
        res = strtok(NULL, "=&");
        if(res!=NULL)
            puts(res);
    }

    return 0;
}

by the way, the strtok_r function doesn't work either.

This:

char str[] = "hello world how are you?\n";

creates an array and initializes it with the contents of the string literal. This, however:

char *data;

data = "integer1=1&integer2=2&integer3=3&integer4=4";

declares data to be a pointer to the first character of the string literal, which is, of course, read-only, so when strtok() tries to modify it, it fails (invoking undefined behavior).


Notes:

  1. So that's why you declare pointers to string literals as const char * and explicitly not as char * , and if you do so, I will find you and const-qualify you.

  2. Arrays are not pointers, they never were, and they never will be either.

The behaviour you're observing can be explained by question 1.32 in com.lang.c FAQ :

What is the difference between these initializations?

 char a[] = "string literal"; char *p = "string literal"; 

My program crashes if I try to assign a new value to p[i].

And the answer is:

A string literal (the formal term for a double-quoted string in C source) can be used in two slightly different ways:

  1. As the initializer for an array of char, as in the declaration of char a[] , it specifies the initial values of the characters in that array (and, if necessary, its size).
  2. Anywhere else, it turns into an unnamed, static array of characters, and this unnamed array may be stored in read-only memory, and which therefore cannot necessarily be modified. In an expression context, the array is converted at once to a pointer, as usual (see section 6), so the second declaration initializes p to point to the unnamed array's first element.

strtok break memory block. And literal strings can't modofiy. So you can't use strtoke for both. Try this:

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

int main(){
    char *data;

    data = "integer1=1&integer2=2&integer3=3&integer4=4";
    char *cur, *res;

    cur = data;
    res = strpbrk(cur, "=&");
    while (res != NULL)
    {
        fwrite(cur, 1, res-cur, stdout);
        fputc('\n', stdout);

        cur = res + 1;
        res = strpbrk(cur, "=&");
    }
    fputs(cur, stdout);

    return 0;
}

This doesn't modify memory block.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM