我可以使用自己的内存分配char指针吗?

时间:2019-03-30 12:32:06

标签: c memory

我正在上大学的第二学期,所以我才开始编码。 最近,我们了解了有关二叉树的一些知识。所以我只想编写自己的代码。我决定编写一本二叉树通讯录。

首先,我将结构保存到.txt文件中。 (我希望它在txt文件中,而不是二进制文件中,因为我可以在程序之后读取它。)之后,我尝试再次将其加载到节点中以重建我的二进制树。

在这里,我们使用缩短的版本。我评论了重要部分。

#define CLEN 100

struct binarytree {
    struct binarytree *left;
    struct binarytree *right;
    char *firstname;
    char *lastname;
    char *city;
    char *street;
    char *addr;
    char *tel;
} typedef btree;

//-----------------------------------------

btree *creatnullnode(void);
btree *loadtree(char *filename);

//-----------------------------------------

btree *creatnullnode(void) {
    btree *node = malloc(sizeof(btree));
    node->left  = NULL;
    node->right = NULL;

    //TODO: the memmory is not right allocated..
    node->firstname = (char*)malloc(CLEN * sizeof(char));
    node->lastname  = (char*)malloc(CLEN * sizeof(char));
    node->city      = (char*)malloc(CLEN * sizeof(char)); 
    node->street    = (char*)malloc(CLEN * sizeof(char));
    node->addr      = (char*)malloc(CLEN * sizeof(char));
    node->tel       = (char*)malloc(CLEN * sizeof(char));
    return node;
}

btree *loadtree(char *filename) {
    FILE *fp;
    btree *tree = NULL;
    btree *node = creatnullnode();
    char ch = "";
    int lines = 0;

    fp = fopen(filename,"r");
    if (!fp) {
        printf("Error. no file\n");
        return NULL;
    } else {
        while (!feof(fp)) {
            ch = fgetc(fp);
            if (ch == '\n')
                lines++;
        }
        fseek(fp, 0,(int)lines % 2);

        //TODO: right here the memory of every char can't be read anymore
        fscanf(fp, "%s\t\t%s\t\t\t%s\t%s\t\t%s\t\t%s\n",
               &node->firstname, &node->lastname, &node->addr, &node->city, 
               &node->street, &node->tel);

        tree = insertnode(tree, node);

        fseek(fp, 0, 0);
        //rekursiveload(&tree, fp);      //TODO: - ausprogrammieren -
    }

    fclose(fp);
    return tree;
}

在调试时,我发现内存分配不正确。但是我不知道如何解决。

在分配g后将char []设置为:node->firstname = 0x007db250 "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍýýýýM¸Þµ¦æ"  调试器说:<Error reading the characters of the string.>之后的fscanf

1 个答案:

答案 0 :(得分:2)

您的代码中存在几个问题:

  • while (!feof(fp))对于测试文件结尾始终是错误的:Why is “while (!feof(file))” always wrong? 您应该这样写:

        while ((ch = fgetc(fp)) != EOF) {
            ...
    
  • 您应该为从文件中读取的每一行创建一个新节点。当前,您为每个节点重复使用相同的内存,并使用新数据覆盖字段。代码片段中缺少的insertnode很可能在列表中创建了一个循环,当您尝试释放它时会导致未定义的行为。

  • char ch = "";不正确:""是字符串,而不是char,并且必须将ch定义为int才能读取字节fgetc()并存储EOF

  • fseek(fp, 0,(int)lines % 2);是没有意义的。您想达到什么目的?您可以尝试使用rewind(fp)fseek(fp, 0L, SEEK_SET)倒带视频流,但只能读取一行。

  • fscanf(fp, "%s\t\t%s\t\t\t%s\t%s\t\t%s\t\t%s\n", &node->firstname, ...有多个问题:您不能防止错误输入导致太多字符存储到目标数组中,并且应该将指针传递给目标数组,而不是指针地址。换句话说,代码应为:

        char eol;
        if (fscanf(fp, "%99s%99s%99s%99s%99s%99s%c",
            node->firstname, node->lastname, node->addr, 
            node->city, node->street, node->tel, &eol) != 7 || eol != '\n') {
            /* invalid input... */
        }
    

    一种更安全的读取此输入的方法是将一行读入更大的char数组中,并使用sscanf()将该行解析为节点字段...但是请查看您的格式字符串,看来您正在处理TAB分隔值和

  • fscanf()sscanf()甚至strtok()都无法正确解析文本文件中的TAB分隔值。您需要为此编写自己的代码。建议您使用strcspn()来计算字段长度,并使用strndup()来分配char数组中某个范围的字符串。