C 我可以用自己的内存分配一个字符指针吗?

C 我可以用自己的内存分配一个字符指针吗?,c,memory,C,Memory,我在大学的第二学期,所以我刚开始编码。 最近我们学习了一些关于二叉树的知识。所以我只想编写自己的代码。我决定编写一个二叉树联系人簿 首先,我将结构保存到一个.txt文件中。(我希望它是一个txt文件,而不是二进制文件,因为这样我就可以在程序运行后读取它。)之后,我尝试在节点中再次加载它以重建我的二叉树 这是一个简短的版本。我评论了重要的部分 #define CLEN 100 struct binarytree { struct binarytree *left; struct

我在大学的第二学期,所以我刚开始编码。 最近我们学习了一些关于二叉树的知识。所以我只想编写自己的代码。我决定编写一个二叉树联系人簿

首先,我将结构保存到一个.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;
}

调试时,我发现内存分配不正确。但我不知道如何修复它

在分配分配分配后,在分配分配分配分配后,字符[]被设置为:<编码>节点>节点>节点>节点>节点>第一名=0x007db250<编码><编码>码码码>码码>码>码>码>码>码>码>码码>码码>码码>码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码码(2055555甲甲甲甲甲甲甲甲甲甲甲甲甲甲甲甲5555基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基基本555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555ÍࠇࠇࠇࠇࠇࠇࠇࠇýýM¸Þæ
调试器说:
fscanf

之后,代码中有几个问题:

  • 而(!feof(fp))
    在测试文件结尾时总是错误的: 你应该写以下内容:

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

  • char ch=”“
    不正确:
    是一个字符串,而不是
    char
    ch
    必须定义为
    int
    ,才能使用
    fgetc()
    读取字节并存储
    EOF

  • fseek(fp,0,(int)行%2)没有意义。你想达到什么目标?您可以尝试使用
    倒带(fp)
    fseek(fp,0L,SEEK\u SET)
    倒带流,但您只能读取一行

  • fscanf(fp),%s\t\t%s\t\t\t%s\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()
    将此行解析为节点字段……但从格式字符串看,似乎您正在处理制表符分隔的值和

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


如果您总是为字符串分配完全相同的常量大小,为什么不将它们创建为数组?例如,
char firstname[CLEN];
?顺便说一句,您的代码甚至不应该构建,更不用说运行并给出错误的结果了。最后,您所说的“内存分配不正确”是什么意思?你是怎么看的?发生了什么?应该发生什么?请阅读,以及。哦,我给你一个提示:当使用
fscanf
(和系列)和
%s
说明符,它需要一个指向目标字符串的第一个元素的指针,类型为
char*
。现在想一想,它的类型是什么,例如
&node->firstname
?应该注意的是,代码还有很多问题。包括未定义的行为(这似乎是问题背后的原因).@Someprogrammerdude是的,你是对的。代码可能充满了错误。但这就是我来这里的原因。它的其他部分工作得很好……或多或少……指针很酷。我想用它们来练习。我想在开始时说char firstname[CLEN]可以是easyer@Pleasure:我所做的正是您所期望的:指出错误,一些小错误,一些致命错误,并提供如何修复它们的答案。虽然我将定义固定数组的结构,例如
char firstname[CLEN],但分配似乎是正确的;
为了避免对每个字段进行单独分配,您应该到处检查分配失败。@chqrlie waiiit。我没有您快。thaaaaaank you!!!:)好的,我试试。我感谢你的回答。。还有很多改进。。建设性地接受一切让我成为“某个程序员”