无法理解 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")。