我陷入了一件相当琐碎的事情...... 所以,基本上我希望第一个和最后一个之间的“单词”转到数据,最后一个转到键。
仅限C-POSIX,请
strtok_r是走的路还是我离开了?别的什么?
char *key = NULL, *data=NULL, *save=NULL;
char comando[1024];
fgets(comando, 512, stdin);
strtok_r(comando, " ",&save);
while(strcmp(save,"\n")){
strcat(data,strtok_r(NULL," ",&save));
}
key = strtok_r(NULL, "\n",&save);
P.S:comando是1024,因为内存不是问题,比抱歉更安全。 fgets读取512'因为这是标准unix终端的char行限制。
答案 0 :(得分:1)
您的代码将在此行崩溃:
strcat(data,strtok_r(NULL," ",&save));
因为您从未为data
预留空间。 strcat
将尝试写入NULL
内存地址。
另外需要注意的是,您不应该依赖save
来检查行尾。根据{{1}}的联系方式:
saveptr参数是指向使用的char *变量的指针 内部由strtok_r()来维护之间的上下文 连续调用解析相同的字符串。
依赖于strtok
之外saveptr
的值会破坏抽象层,您不应该假设strtok_r
如何使用strtok
。这是不好的做法。
稍微好一点的方法是保留指向saveptr
返回的前一个标记的指针,以及指向当前标记的指针。当strtok
返回NULL时,意味着没有其他令牌,则strtok
将指向最后一个令牌,即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
中保留指向下一个空闲位置的指针。
答案 1 :(得分:1)
我建议用以下代码替换你的循环(printf()仅用于测试):
strtok_r(comando, " ", &save);
char *res = NULL;
while (NULL != (res = strtok_r(NULL, " ", &save))) {
if (key != NULL) {
//strcat(data, key); // FIXME
printf("data = %s\n", key);
}
key = res;
}
printf("key = %s\n", key);
strcat()也不应该与NULL参数一起使用 - 它会导致崩溃。所以数据指针应指向某个数组。运行代码的结果:
┌─(16:08:22)─(michael@lorry)─(~/tmp/strtok)
└─► gcc -o main main.c; echo "one two three four five" | ./main
data=two
data=three
data=four
key = five
答案 2 :(得分:1)
您的代码有问题
char *key = NULL, *data=NULL, *save=NULL;
稍后,您使用strcat
向data
添加字符串,但您没有为data
分配存储空间。这将导致分段错误。
fgets(comando, 512, stdin);
fgets
最多读取的数字少于传递给它的数字。因此,如果用户输入512个字符,则该字符串将没有终止\n
。此外,检测错误或文件结尾的唯一方法是检查fgets
的返回结果。如果它为NULL,则表示您已到达文件末尾(用户已按下ctrl-d)或出现错误。在任何一种情况下,缓冲区的内容都是不确定的。
while(strcmp(save,"\n"))
我认为你不能依赖于你的save
指针将指向未消耗字符串的其余部分的假设。
strtok_r(comando, " ",&save);
strtok_r
通过返回NULL
指针表示它已到达数据末尾。你不能不看它就扔掉返回的结果。此外,这将使用尾随\n
作为最后一个标记的一部分。
strcat(data,strtok_r(NULL," ",&save));
正如我之前所说,data
是一个空指针。此外,strtok_r
可以返回NULL
我会做更多的事情:
char* currentTok = strtok_r(commando, " \n", &save); // separator is space or \n
char* previousTok = NULL;
while (currentTok != NULL)
{
if (previousTok != NULL)
{
// save previousTok in data unless its the first token
}
previousTok = currentTok;
currentTok = strtok_r(NULL, " \n", &save);
}
char* key = previousTok;