简体   繁体   English

Strtok_r分段错误

[英]Strtok_r segmentation fault

I know this has been asked before, but previous answers have said you can't modify a string literal, and unless I am misunderstanding I am not. 我知道之前已经问过,但之前的答案都说你不能修改字符串文字,除非我误解我不是。 I can sucesfully use strtok_r until the very last line of input, then I get a seg fault. 我可以使用strtok_r直到最后一行输入,然后我得到一个seg错误。 Why would this happen? 为什么会这样? Heres a simplified version of my code. 这是我的代码的简化版本。 From printing I know it processes through get b, but then there is a seg fault? 从打印我知道它通过get b处理,但是有一个seg错误?

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

    void handler(char * input){
    char * end_str;
    char * token =strtok_r(input, "\n", &end_str);
    char * endd_str;
    char * token2= strtok_r(token, " ", &endd_str);
    while(token!=0){
        printf("%s\n",token);
        token=strtok_r(NULL,"\n",&end_str);
        while(token2 !=0){
            token2 =strtok_r(NULL," ",&endd_str);
            printf("%s\n",token2);}
    }

}

int main(int argc , char *argv[])
{
    char test[100]="set a,10.5\nset b,11.5\nget b\nadd e,a,b\nsub g,a,b";
    handler(test);
    return 0;
}

You're interleaving strtok_r calls working off of the same string. 你正在strtok_r使用相同字符串的strtok_r调用。 On the second iteration of the inner while loop, before the call to token2 =strtok_r(NULL," ",&endd_str); 在内部while循环的第二次迭代中,在调用token2 =strtok_r(NULL," ",&endd_str); , endd_str points to an empty string because the string it was matching against reached the end, so strtok_r returns NULL . endd_str指向一个空字符串,因为它匹配的字符串到达​​了结尾,所以strtok_r返回NULL Passing that NULL to printf causes the segfault. 将该NULL传递给printf会导致段错误。

After each parse of the "\\n" delimiter, do a fresh start of looping through the " " delimeter. 在每次解析"\\n"分隔符后,重新开始循环" "分隔符。 Don't do the outer one again until you've exhausted the inner one. 在内心耗尽之前,不要再做外面的。 Also, move your strtok_r calls to the end of the loop so the while condition checks them properly. 另外,将strtok_r调用移动到循环结束,以便while条件正确检查它们。

You need to do the following: 您需要执行以下操作:

void handler(char * input){
    char * end_str;
    char * token =strtok_r(input, "\n", &end_str);
    while(token!=0){
        printf("%s\n",token);
        char * endd_str;
        char * token2= strtok_r(token, " ", &endd_str);
        while(token2 !=0){
            printf("%s\n",token2);
            token2 =strtok_r(NULL," ",&endd_str);    // call at end of loop
        }
        token=strtok_r(NULL,"\n",&end_str);          // call at end of loop
    }
}

Ouput: 输出继电器:

set a,10.5
set
a,10.5
set b,11.5
set
b,11.5
get b
get
b
add e,a,b
add
e,a,b
sub g,a,b
sub
g,a,b

Works perfectly for me (MS Visual C++). 适合我(MS Visual C ++)。 Only difference is usage strtok_s instead of strtok_r considering it is Windows instead of POSIX. 唯一的区别是使用strtok_s而不是strtok_r因为它是Windows而不是POSIX。

Here I have added some modifications to your code. 在这里,我为您的代码添加了一些修改。

#include <string.h>   //strlen
#include <stdlib.h>

void handler(char * input){
    char * end_str;
    char * token =strtok_s(input, "\n", &end_str); // tokenize input string
    char * endd_str;
    char * token2 = NULL;

    while(token!=0){

        printf("%s\n",token);

        token2 = strtok_s(token, " ", &endd_str); // retokenize first token
        while(token2 !=0){
            printf("%s\n",token2); // replace printf call to avoid null string output and first token miss
            token2 =strtok_s(NULL," ",&endd_str);}

        token = end_str; // "important" restore char pointer to point the last untokenized input character

        token=strtok_s(token,"\n",&end_str); // the same as printf issue is for all loops body
    }

}

int main(int argc , char *argv[])
{
    char test[100]="set a,10.5\nset b,11.5\nget b\nadd e,a,b\nsub g,a,b";
    handler(test);
    return 0;
}

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

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