您的代码将在此行崩溃:
strcat(data,strtok_r(NULL," ",&save));
因为你从来没有为data
. strcat
将尝试写入NULL
内存地址。
另一件需要注意的是,您不应该依赖save
检查行尾。根据strtok
的手册页:
saveptr 参数是一个指向 char * 变量的指针,strtok_r() 内部使用该变量来维护解析相同字符串的连续调用之间的上下文。
依靠saveptr
outside 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
。