c - 从 C 中的文本文件中解析值

标签 c file-io text-files token

<分区>

Possible Duplicate:
Parsing text in C

假设我已经写入了这种格式的文本文件:

key1/value1
key2/value2
akey/withavalue
anotherkey/withanothervalue

我有一个像这样的链表:

struct Node
{
    char *key;
    char *value;
    struct Node *next;
};

保存值。我将如何读取 key1 和 value1?我正在考虑逐行放入缓冲区并使用 strtok(buffer, '/')。那行得通吗?还有什么其他方法可以工作,也许更快或更不容易出错?如果可以,请附上代码示例!

最佳答案

由于您的问题是优化内存碎片的一个很好的候选者,这里有一个实现,它使用一些简单的神秘魔法将所有字符串和结构本身分配到一 block 内存中。

当销毁节点时,您只需要对节点本身调用一次 free()

struct Node *list = NULL, **nextp = &list;
char buffer[1024];

while (fgets(buffer, sizeof buffer, file) != NULL) {
    struct Node *node;

    node = malloc(sizeof(struct Node) + strlen(buffer) + 1);
    node->key = strtok(strcpy((char*)(node+1), buffer), "/\r\n");
    node->value = strtok(NULL, "\r\n");
    node->next = NULL;
    *nextp = node;
    nextp = &node->next;
}

说明:

有 20 条评论和 1 条无法解释的反对票,我认为代码需要一些解释,特别是关于所采用的技巧:

  1. 构建链表:

    struct Node *list = NULL, **nextp = &list;
    ...
    *nextp = node;
    nextp = &node->next;
    

    这是一个以正向顺序迭代创建链表的技巧,而不必对列表的头部进行特殊处理。它使用指向下一个节点的指针。首先nextp指针指向链表头指针;在第一次迭代中,列表头通过这个指针到指针设置,然后 nextp 被移动到该节点的下一个指针。随后的迭代填充最后一个节点的下一个指针。

  2. 单一分配:

    node = malloc(sizeof(struct Node) + strlen(buffer) + 1);
    node->key = ... strcpy((char*)(node+1), buffer) ...
    

    我们必须处理三个指针:节点本身、键字符串和值字符串。这通常需要三个单独的分配(malloc、calloc、strdup ...),因此需要单独的释放(免费)。相反,在这种情况下,树元素的空间在 sizeof(struct Node) + strlen(buffer) + 1 中求和并传递给单个 malloc 调用,它返回单个内存块。此内存块的开头分配给结构本身的 node。附加内存 (strlen(buffer)+1) 紧跟在节点之后,它的地址是通过使用 node+1 的指针算法获得的。它用于复制从文件中读取的整个字符串(“key/value\n”)。

    由于 malloc 对每个节点调用一次,因此进行一次分配。这意味着您不需要调用 free(node->key)free(node->value)。事实上,它根本行不通。只需一个 free(node) 就可以在一个 block 中释放结构和两个字符串。

  3. 行解析:

    node->key = strtok(strcpy((char*)(node+1), buffer), "/\r\n");
    node->value = strtok(NULL, "\r\n");
    

    strtok 的第一次调用返回指向缓冲区本身开头的指针。它查找“/”(另外用于行尾标记)并用 NUL 字符断开字符串。因此,“key/value\n”在“key”和“value\n”之间被打破,中间有一个 NUL 字符,返回指向第一个的指针并存储在 node->key .对 strtok 的第二次调用将处理剩余的“value\n”,去除行尾标记并返回指向“value”的指针,该指针存储在 node->值

我希望这能解决所有关于上述解决方案的问题……对于一个封闭的问题来说太多了。 The complete test code is here .

关于c - 从 C 中的文本文件中解析值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2663644/

相关文章:

java - Java 相对路径与绝对路径

c - 从二进制文件 C 中写入和读取结构

java - 使用扫描仪解析文本文件时,为什么我在每个预期字符之间得到空字符?

php - 从以空格分隔的文本文件创建 PHP 数组

c - 将输出重定向到文件时 printf() 和 system() 的结果顺序错误

iphone - 从 ARM 动态库(框架)获取参数列表?

C函数作为参数?

Java:使用操作系统标准应用程序打开 jar 中的资源(txt 文件)

java - java中如何比较两个txt文件中的元素并将它们合并到一个文件中?

c++ - "Reading"POD 预增量结果不会产生未定义的行为。为什么呢?