0

我正在 Visual Studio 2010 Ultimate Beta (Win 7) 上开发 C89。我不认为我使用malloc()正确。我是C新手,所以请原谅初学者的问题。

我的程序的目标是计算**argv使用树时单词的出现次数。

hist.c

#include "tree.h"
#include <stdlib.h>

int main(int argc, char *argv[]) {
    unsigned int i;
    struct tree *tree;
    tree = new_tree();

    for (i = 1; i < argc; i++) {
        tree_add(tree, argv[i]);
    }

    tree_dump(tree);
    tree_free(tree);

    return 0;
}

tree_add.c:

#include "tree.h"
#include <stdlib.h>
#include <string.h>

struct tree *tree_add(struct tree *tree, char *value) {
    if (tree == NULL) {
        tree = new_tree();
        tree->value = value;
        tree->count = 0;
    }
    else if (tree->value == NULL) {
        tree->value = value;
    }
    else if (tree->value == value) {
        tree->count++;
    }
    else if (strcmp(value, tree->value) < 0) {
        tree_add(tree->left, value);
    }
    else if (strcmp(value, tree->value) > 0) {
        tree_add(tree->right, value);
    }
}

struct tree *new_tree() {
    struct tree * tree;
    tree = malloc(sizeof *tree);
    tree->left = NULL;
    tree->right = NULL;
    tree->value = NULL;
    tree->count = 0;
    return tree;
}

我得到的错误是:

0xC0000005:访问冲突读取位置 0x00000000。

我在网上查了一下,看来这个错误是由于试图访问分配不正确的内存造成的。那么我做错了什么?

更新代码以反映评论。现在我有一个新问题。当value == "x"tree->value == "x"

else if (tree->value == value) {

在调试器中,我看到了tree->valueis 0x00553373 "x" char *,而valueis 0x00553375 "x" char *。最后一位的十六进制值不同。这里有什么问题?我是否错误地检查了字符串相等性?

4

6 回答 6

3

这部分应该如何工作?

    如果(树 == NULL){
        树->值=值;
        树->计数= 0;
    }

我问是因为它会尽可能地尝试取消对 NULL 的引用。代码相当于:

    如果(树 == NULL){
        (NULL)->值 = 值;
        (NULL)->count = 0;
    }

因此,当它尝试到达value结构的元素时,它将接收 AV。

我认为您缺少的是您需要调用树中malloc()每个节点。您不能像在此处所做的那样在开始时调用它一次,它只会为一个节点分配足够的内存。

你的意思可能是这样的:

    if (tree->left == NULL) {
        tree->left = malloc(sizeof struct tree);
        树=树->左;
    }
    /* ... */

然后你的tree_free()函数必须以深度优先的顺序递归遍历树,首先调用free()最向叶的元素,通过最终释放你分配的第一个块在根处完成。

于 2010-02-11T16:16:59.723 回答
2
if (tree == NULL) {
    tree->value = value;
    tree->count = 0;
}

这里有个问题,如果tree为NULL就不能使用,必须先分配

此外,您应该存储 strcmp 的返回值,而不是执行两次

于 2010-02-11T16:15:26.310 回答
2

一些问题 :

tree = malloc(sizeof tree);

我认为您的意思是sizeof *tree,您只是为代码中的指针分配空间,而不是为整个结构分配空间。

if (tree == NULL) {
    tree->value = value;
    tree->count = 0;
}

如果树为 NULL 则tree->value不行。

于 2010-02-11T16:16:08.370 回答
1

strcmp 需要两个字符串并且不能处理空值。请注意,char *c="\0"与 不一样char *c = 0。第一个是指向具有单个空元素的 char 数组的指针,第二个是空指针。

于 2010-02-11T16:14:48.183 回答
1

您在 tree_add 中的检查不正确,这里:

if (tree == NULL) { 
    tree->value = value; 
    tree->count = 0; 
} 

由于在原始调用中 tree 不是 NULL,因此您不会写入 tree->value 并且它将保持 NULL。然后,当您调用 strcmp 时,您会在尝试从 tree->value 读取时遇到访问冲突。

你从来没有真正分配 tree->left 和 tree->right - 你需要在使用之前用 malloc 分配它们。

于 2010-02-11T16:15:45.043 回答
0

除了其他注释之外,“tree_add”需要返回树,“tree_add”调用需要保存该结果。(虽然递归调用不应该将它们保存为树,而是作为左/右指针)。

于 2010-02-11T16:41:40.660 回答