简体   繁体   English

如何有效使用strtok函数

[英]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. 我正在尝试使用strtok拆分字符串,但事实是它不起作用。 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: 原始的while循环是:

    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. 但是,如果将str更改为data及其相应的定界符(&=),则它将变为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. 顺便说一句,strtok_r函数也不起作用。

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). data声明为指向字符串文字的第一个字符的指针,该指针当然是只读的,因此当strtok()尝试对其进行修改时,它将失败(调用未定义的行为)。


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. 因此,这就是为什么将指向字符串文字的指针声明为const char *不是声明为 char * ,如果这样做,我将找到您并const限定您的身份

  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 : 您所观察到的行为可以通过com.lang.c FAQ中的问题1.32来解释:

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]. 如果尝试为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: 字符串文字(C源代码中双引号字符串的正式术语)可以以两种略有不同的方式使用:

  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). 作为char数组的初始化程序,如在char a []的声明中一样,它指定该数组中字符的初始值(并在必要时指定其大小)。
  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. 在表达式上下文中,通常将数组立即转换为指针(请参见第6节),因此第二个声明将p初始化为指向未命名数组的第一个元素。

strtok break memory block. strtok中断存储块。 And literal strings can't modofiy. 文字字符串不能模化。 So you can't use strtoke for both. 因此,您不能同时使用strtoke 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. 这不会修改内存块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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