我正在上大学的第二学期,所以我才开始编码。 最近,我们了解了有关二叉树的一些知识。所以我只想编写自己的代码。我决定编写一本二叉树通讯录。
首先,我将结构保存到.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
答案 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
数组中某个范围的字符串。