无法理解strtok和sscanf的这种行为

时间:2015-03-22 18:08:55

标签: c strtok scanf

我想在“\ 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, '\0', 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

...

正如您所看到的,第一行正确地放入结构中,但是从第二次迭代开始,即使将标记设置为下一行并且似乎具有正确的内容,只有结构的第一个元素是set(nodeId),但不是另外两个。

我相信我对strtok / sscanf的理解不足。

谢谢!

编辑:这是一个mvce。有了这个,即使第一个令牌也没有被sscanf正确解析。这可能必须与“%s”我试图用IP地址设置..

#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);
}

1 个答案:

答案 0 :(得分:2)

您为此struct数组分配了内存

node *ft = malloc(32 * sizeof(node));

但是你没有初始化每个struct元素,每个元素都有一个指向未分配任何内存的字符串的指针。然后,将此未初始化的字符串指针作为%s参数传递给scanf(),这将导致未定义的行为。如果你很幸运,它可以在字符串指针刚刚发生时指向你拥有的内存而不会破坏其他内容。

我无法解释为什么ft[1].port被打印为0,但您已编辑了输出,因此无法将其视为您的实际输出。 (它说“apres”而不是“after”)。