C Strtok_r分段故障

C Strtok_r分段故障,c,C,我知道以前有人问过这个问题,但之前的回答说不能修改字符串文字,除非我误解了,否则我不会。我可以成功地使用strtok_r,直到输入的最后一行,然后出现seg故障。为什么会发生这种情况?这是我的代码的简化版本。从打印我知道它通过get b进行处理,但是有seg故障吗 #include <stdio.h> #include <string.h> //strlen #include <stdlib.h> void handler(char * inpu

我知道以前有人问过这个问题,但之前的回答说不能修改字符串文字,除非我误解了,否则我不会。我可以成功地使用strtok_r,直到输入的最后一行,然后出现seg故障。为什么会发生这种情况?这是我的代码的简化版本。从打印我知道它通过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;
}
#包括
#包括//strlen
#包括
无效处理程序(字符*输入){
char*end_str;
char*token=strtok\u r(输入“\n”和结束\u str);
char*endd_str;
char*token2=strtok_r(token,“,&endd_str);
while(令牌!=0){
printf(“%s\n”,标记);
令牌=strtok_r(NULL、\n、&end_str);
while(令牌2!=0){
token2=strtok_r(NULL,“,&endd_str);
printf(“%s\n”,token2);}
}
}
int main(int argc,char*argv[])
{
字符测试[100]=“集合a,10.5\n集合b,11.5\n集合b\n集合e,a,b\n集合g,a,b”;
处理程序(测试);
返回0;
}
非常适合我(MS Visual C++)。唯一的区别是使用
strtok_s
而不是
strtok_r
,因为它是Windows而不是POSIX

在这里,我对您的代码添加了一些修改

#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;
}
#包括//strlen
#包括
无效处理程序(字符*输入){
char*end_str;
char*token=strtok_s(输入“\n”,&end_str);//标记化输入字符串
char*endd_str;
char*token2=NULL;
while(令牌!=0){
printf(“%s\n”,标记);
token2=strtok_s(token,“,&endd_str);//重新排序第一个标记
while(令牌2!=0){
printf(“%s\n”,token2);//替换printf调用以避免空字符串输出和第一个令牌丢失
token2=strtok_s(NULL,“,&endd_str);}
token=end_str;//“重要”还原字符指针指向最后一个未加密的输入字符
token=strtok_s(token、\n、&end_str);//与printf问题相同,适用于所有循环体
}
}
int main(int argc,char*argv[])
{
字符测试[100]=“集合a,10.5\n集合b,11.5\n集合b\n集合e,a,b\n集合g,a,b”;
处理程序(测试);
返回0;
}

您正在交错
strtok\u r
使用相同字符串的调用。在调用
token2=strtok_r(NULL,“,&endd_str)之前的内部
while
循环的第二次迭代中
endd\u str
指向一个空字符串,因为它所匹配的字符串已到达末尾,因此
strtok\u r
返回
NULL
。将该
NULL
传递到
printf
会导致SEGFULT

每次解析
“\n”
分隔符后,重新开始在
delimeter中循环。不要再做外面的,直到你把里面的都累坏了。另外,将
strtok_r
调用移动到循环的末尾,以便
while
条件正确检查它们

您需要执行以下操作:

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
    }
}
输出:

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

提供的代码是否也会失败?如果没有,您就没有提供足够的数据让任何人告诉您它失败的原因。请参阅无法使用您提供的示例代码重新创建seg故障。您确定是
strtok\u r
导致seg故障,而不是其他原因。为什么您认为程序执行会产生有意义的结果?你可以查看生成的二进制代码,看看在你的情况下会发生什么。我不认为目前提出的问题提供了一个MCVEMind来解释“s”和“r”之间的区别@Mr_Pouet:Windows操作系统的功能相同,POSIX的功能相同,只是命名不同而已。