C 语言:实现一个包含文本文件中字符串(单词)的 BST 的数组
C Language: Implement an array containing BST's of strings ( words ) from a text file
我正在尝试创建一个小程序,从未知大小的文本文件中读取单词并将这些单词存储到二进制搜索树 (BST) 数组中。数组中的每个索引代表该 BST 树中单词的长度。
例如,索引 0 不包含单词,但索引 1 包含一棵 BST 树,单词长度为一个字母,索引 5 包含一棵 BST 树,单词长度为 5 个字母等。所有 BST 树通过比较平衡两个字符串判断新字符串是大于还是小于根字符串,然后相应地赋值。
我的原始代码包含不透明对象(空指针)。但是,我已经包含了我试图理解的程序的较小版本。我包含了 printf
语句来展示我的调试方法,因为程序一直在崩溃。我每天都为此工作数小时,但我一辈子都做不到 运行。出于某种原因,我无法确定我是否正确使用了指针,因此在对这段代码进行了大约 5 次不同的重写之后,我决定只使用基础知识,但我似乎也无法让它工作。
请帮忙,这让我筋疲力尽。感谢您的慷慨和考虑,提前帮助我解决这个问题。
我的输出如下:
A CHECKPOINT
B CHECKPOINT
C CHECKPOINT
1 CHECKPOINT
2 CHECKPOINT
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct my_string{
char* data;
struct my_string *left, *right;
} My_string;
void init( My_string* Root, char* data );
int main(int argc, char* argv[]){
My_string* myStringArray[ 30 ] = {NULL};
/*My_string* Root = NULL;*/
FILE *fp = NULL;
char new_string[ 30 ];
fp = fopen( "dictionary.txt", "r");
int string_length = 0;
printf( "A CHECKPOINT\n");
while( fscanf( fp, "%1024s" , new_string ) == 1 ){
printf( "B CHECKPOINT\n");
string_length = strlen( new_string );
printf( "C CHECKPOINT\n");
init( myStringArray[ string_length ], new_string );
printf( "D CHECKPOINT\n");
}
printf( "" );
fclose(fp);
return 0;
}
void init( My_string* Root, char* data ){
printf( "1 CHECKPOINT\n");
int compare = 0;
if( Root == NULL ){
printf( "2 CHECKPOINT\n");
(*Root).data = ( My_string* )malloc( sizeof( My_string ));
printf( "3 CHECKPOINT\n");
if( !Root ) exit(1);
Root->data = data;
Root->left = Root->right = NULL;
}
else{
if( compare = strncmp( data, Root->data, 36 ) == 0 )return;
else if( compare == -1 ) init( Root->left, data );
else init( Root->right, data );
}
}
再次感谢!
两条一般性建议:
- 您可以使用调试器代替调试输出来查找错误的确切位置(例如,了解如何使用
gdb
)。当然,您可以使用 debug-output,但它可能需要更多时间,并且您必须在此之后进行清理。
- 不要忽略编译器警告。
我的编译器说:
a.c:37:22: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
(*Root).data = ( My_string* )malloc( sizeof( My_string ));
在这里您尝试取消引用 Root
并为 data
字段赋值。由于Root
是NULL
,这里程序就崩溃了。看起来你打算在这里给 Root
赋值,但是做了一个类型。
所以它应该是这样的:
Root = ( My_string* )malloc( sizeof( My_string ));
顺便说一句,你的代码还有一个问题:当你将Root
作为函数参数传递时,它在你退出函数后不会改变:
My_string* Root = NULL;
init(Root, data);
// Root is NULL here
解决此问题的一种方法是将指针传递给 Root
:
init(&Root, data);
void init( My_string** Root_ptr, char* data ){
...
}
并相应地修改代码。
另一种方法是更改 init
签名并使其 return 成为新创建的 Root
。我不明白你需要初始化现有树的场景,所以这似乎是很自然的事情。
我正在尝试创建一个小程序,从未知大小的文本文件中读取单词并将这些单词存储到二进制搜索树 (BST) 数组中。数组中的每个索引代表该 BST 树中单词的长度。
例如,索引 0 不包含单词,但索引 1 包含一棵 BST 树,单词长度为一个字母,索引 5 包含一棵 BST 树,单词长度为 5 个字母等。所有 BST 树通过比较平衡两个字符串判断新字符串是大于还是小于根字符串,然后相应地赋值。
我的原始代码包含不透明对象(空指针)。但是,我已经包含了我试图理解的程序的较小版本。我包含了 printf
语句来展示我的调试方法,因为程序一直在崩溃。我每天都为此工作数小时,但我一辈子都做不到 运行。出于某种原因,我无法确定我是否正确使用了指针,因此在对这段代码进行了大约 5 次不同的重写之后,我决定只使用基础知识,但我似乎也无法让它工作。
请帮忙,这让我筋疲力尽。感谢您的慷慨和考虑,提前帮助我解决这个问题。
我的输出如下:
A CHECKPOINT
B CHECKPOINT
C CHECKPOINT
1 CHECKPOINT
2 CHECKPOINT
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct my_string{
char* data;
struct my_string *left, *right;
} My_string;
void init( My_string* Root, char* data );
int main(int argc, char* argv[]){
My_string* myStringArray[ 30 ] = {NULL};
/*My_string* Root = NULL;*/
FILE *fp = NULL;
char new_string[ 30 ];
fp = fopen( "dictionary.txt", "r");
int string_length = 0;
printf( "A CHECKPOINT\n");
while( fscanf( fp, "%1024s" , new_string ) == 1 ){
printf( "B CHECKPOINT\n");
string_length = strlen( new_string );
printf( "C CHECKPOINT\n");
init( myStringArray[ string_length ], new_string );
printf( "D CHECKPOINT\n");
}
printf( "" );
fclose(fp);
return 0;
}
void init( My_string* Root, char* data ){
printf( "1 CHECKPOINT\n");
int compare = 0;
if( Root == NULL ){
printf( "2 CHECKPOINT\n");
(*Root).data = ( My_string* )malloc( sizeof( My_string ));
printf( "3 CHECKPOINT\n");
if( !Root ) exit(1);
Root->data = data;
Root->left = Root->right = NULL;
}
else{
if( compare = strncmp( data, Root->data, 36 ) == 0 )return;
else if( compare == -1 ) init( Root->left, data );
else init( Root->right, data );
}
}
再次感谢!
两条一般性建议:
- 您可以使用调试器代替调试输出来查找错误的确切位置(例如,了解如何使用
gdb
)。当然,您可以使用 debug-output,但它可能需要更多时间,并且您必须在此之后进行清理。 - 不要忽略编译器警告。
我的编译器说:
a.c:37:22: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
(*Root).data = ( My_string* )malloc( sizeof( My_string ));
在这里您尝试取消引用 Root
并为 data
字段赋值。由于Root
是NULL
,这里程序就崩溃了。看起来你打算在这里给 Root
赋值,但是做了一个类型。
所以它应该是这样的:
Root = ( My_string* )malloc( sizeof( My_string ));
顺便说一句,你的代码还有一个问题:当你将Root
作为函数参数传递时,它在你退出函数后不会改变:
My_string* Root = NULL;
init(Root, data);
// Root is NULL here
解决此问题的一种方法是将指针传递给 Root
:
init(&Root, data);
void init( My_string** Root_ptr, char* data ){
...
}
并相应地修改代码。
另一种方法是更改 init
签名并使其 return 成为新创建的 Root
。我不明白你需要初始化现有树的场景,所以这似乎是很自然的事情。