无法理解 strtok 和 sscanf 的这种行为
Can't understand this behaviour of strtok and sscanf
我想在“\n”上拆分字符串,解析令牌,并将一些值存储在结构中。
这是实际代码:
typedef struct {
char *address;
int port;
unsigned int nodeId;
} node;
...
node *ft = malloc(32 * sizeof(node));
...
int function (char *addr, int port, node * ft) {
char request[BUFSIZE], answer[8192];
char *token;
int c = 0;
snprintf(request, sizeof(request), "Keyword");
request(addr, port, request, answer);
printf("answer at this point is:\n%s\n", answer);
memset(&token, '[=10=]', sizeof(token));
token = strtok(answer, "\n");
while (token != NULL) {
printf("c = %d\n", c);
printf("Token:\n%s\n", token);
printf("Token addr:%p\n", &token);
sscanf(token,
"nodeId:%u nodeAddress:%s nodePort:%d",
&ft[c].nodeId, ft[c].address, &ft[c].port);
printf("id: %u\n", ft[c].nodeId);
printf("addr: %s\n", ft[c].address);
printf("port: %d\n", ft[c].port);
token = strtok(NULL, "\n");
printf("Token after:\n%s\n", token);
printf("==========================\n");
c++;
}
return c;
}
输出如下:
answer at this point is:
nodeId:65228883 nodeAddress:127.0.0.1 nodePort:3081
nodeId:65228883 nodeAddress:127.0.0.1 nodePort:3081
nodeId:65228883 nodeAddress:127.0.0.1 nodePort:3081
nodeId:65228883 nodeAddress:127.0.0.1 nodePort:3081
nodeId:65228883 nodeAddress:127.0.0.1 nodePort:3081
c = 0
Token:
nodeId:65228883 nodeAddress:127.0.0.1 nodePort:3081
Token addr:0x7fff05bac308
id: 65228883
addr: 127.0.0.1
port: 3081
Token after:
nodeId:65228883 nodeAddress:127.0.0.1 nodePort:3081
==========================
c = 1
Token:
nodeId:65228883 nodeAddress:127.0.0.1 nodePort:3081
Token addr:0x7fff05bac308
id: 65228883
addr: (null)
port: 0
Token apres:
nodeId:65228883 nodeAddress:127.0.0.1 nodePort:3081
...
正如你所看到的,第一行被正确地放入结构中,但是从第二次迭代开始,即使标记被设置到下一行并且似乎有正确的内容,也只有第一个元素结构已设置 (nodeId),但其他两个未设置。
我相信我对strtok/sscanf的理解不足可能与此有关。
谢谢!
编辑:这是一个 mvce。这样一来,即使是第一个标记也无法被 sscanf 正确解析。这可能必须与我尝试设置 IP 地址的“%s”有关..
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
char answer[8192] = "nodeId:107813116 nodeAddress:10.190.233.184 nodePort:3081\nnodeId:107813116 nodeAddress:10.190.233.184 nodePort:3081\nnodeId:107813116 nodeAddress:10.190.233.184 nodePort:3081\nnodeId:107813116 nodeAddress:10.190.233.184 nodePort:3081\nnodeId:107813116 nodeAddress:10.190.233.184 nodePort:3081";
const char s[2] = "\n";
char *token;
typedef struct {
char *address;
int port;
unsigned int nodeId;
} node;
node * ft = malloc(32 * sizeof(node));
/* get the first token */
token = strtok(answer, s);
int c = 0;
/* walk through other tokens */
while (token != NULL) {
printf("c = %d\n", c);
printf("Token:\n%s\n", token);
printf("Token addr:%p\n", &token);
sscanf(token,
"nodeId:%u nodeAddress:%s nodePort:%d",
&ft[c].nodeId, ft[c].address, &ft[c].port);
printf("id: %u\n", ft[c].nodeId);
printf("addr: %s\n", ft[c].address);
printf("port: %d\n", ft[c].port);
token = strtok(NULL, "\n");
printf("Token after:\n%s\n", token);
printf("==========================\n");
c++;
}
return(0);
}
您像这样为 struct
数组分配了内存
node *ft = malloc(32 * sizeof(node));
但您还没有初始化每个 struct
元素,每个元素都有一个指向未分配任何内存的字符串的指针。然后将这个未初始化的字符串指针作为 %s
参数传递给 scanf()
,这将导致未定义的行为。如果幸运的话,它会在字符串指针 刚好 指向您拥有的不会损坏任何其他内容的内存时起作用。
我无法解释为什么 ft[1].port
被打印为 0
但你已经编辑了输出,所以不能相信它是你的 actual 输出。 (它说 "apres" 而不是 "after")。