您的代码将在此行崩溃:
strcat(data,strtok_r(NULL," ",&save));
因为你从来没有为data. strcat将尝试写入NULL内存地址。
另一件需要注意的是,您不应该依赖save检查行尾。根据strtok的手册页:
saveptr 参数是一个指向 char * 变量的指针,strtok_r() 内部使用该变量来维护解析相同字符串的连续调用之间的上下文。
依靠saveptroutside of的值strtok_r打破了抽象层,你不应该假设任何关于如何strtok使用saveptr. 这是不好的做法。
一个稍微好一点的方法是保留一个指向返回的前一个标记strtok的指针和一个指向当前标记的指针。当strtok返回 NULL 时,意味着没有更多的标记,那么prev将指向最后一个标记,即你的key. 这是一些代码:
char *key = NULL, *save=NULL;
char *prev, *curr;
char comando[1024];
char data[1024];
data[0] = '\0';
fgets(comando, 512, stdin);
prev = curr = strtok_r(comando, " ",&save);
while (curr != NULL) {
prev = curr;
curr = strtok_r(NULL, " ", &save);
if (curr != NULL)
strcat(data, prev);
}
key = prev;
请注意,我data通过将其声明为数组而不是指针来分配空间。该指令
data[0] = '\0';
是否可以确保strcat在第一次调用中找到空终止字节。
prev你可以直接用替换使用key,我这样保留是为了使代码更具可读性。
一个忠告:永远记住它strtok会破坏性地修改它的参数(你失去了分隔字节的标识),并且你不能用常量字符串调用它。
注意: data将包含连接的每个单词。你失去了空间。我不确定这是否是你想要的。如果不是,您可能想要使用比strcat(顺便说一句,这不是很有效)更好的东西。例如,您的代码用于使用前导空格sprintf将标记打印到data其中,并保留指向下一个空闲位置的指针data。