当我尝试将节点插入二叉树时,我收到了段错误。我用gdb运行程序,这是我发现的关于segfault的内容,但我真的不知道在insert和create函数中要改变什么。感谢您的帮助。
Program received signal SIGSEGV, Segmentation fault.
__strcmp_sse42 () at ../sysdeps/x86_64/multiarch/strcmp.S:260
260 movdqu (%rsi), %xmm2
(gdb) where
#0 __strcmp_sse42 () at ../sysdeps/x86_64/multiarch/strcmp.S:260
#1 0x0000000000400a42 in insert_into_commands_tree (node=0x7fffffffe0b0,
data=0x602270) at lab8.c:116
#2 0x00000000004009d7 in create_commands_tree (commands=0x7fffffffe0b0,
file=0x7fffffffe4a1 "commands.dat") at lab8.c:104
#3 0x0000000000400835 in main (argc=2, argv=0x7fffffffe1b8) at lab8.c:48
我的程序所做的是读取文本文件并解析字符串,然后将它们存储到二叉树中。然后用户输入一个命令,我搜索树,看看该命令是否列在树中。我将发布我的完整代码,所以你们都可以看到它,然后发布我读入的文件和示例输出,希望有人可以帮助我解决这个段错误。非常感谢提前。我的老师也向我们提供了main和tokenizer功能。
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#define COMMAND_NAME_LEN 50
#define MAX_SPLIT_SIZE 50
#define MAX_BUFF_SIZE 50
typedef struct Command_ {
char name[COMMAND_NAME_LEN];
int expected_param_count;
struct Command_ *left;
struct Command_ *right;
}Command;
typedef struct StringArray_ {
char **strings;
int size;
}StringArray;
StringArray* tokenizer (char *string, const char* delimiters);
void free_string_array(StringArray *sr);
void create_commands_tree(Command **commands, const char *file);
void insert_into_commands_tree(Command** node, char** data);
Command* get_command(Command *node, const char *command);
Command* create_command(char **data);
void destroy_commands_tree(Command* node);
void display_commands(Command *node);
int main (int argc, char *argv[]) {
if (argc < 2) {
printf("%s is missing commands.dat\n", argv[0]);
return 0;
}
Command* options = NULL;
create_commands_tree(&options,argv[1]);
int checking = 1;
char input_buffer[MAX_BUFF_SIZE];
do {
printf("Command: ");
fgets(input_buffer,MAX_BUFF_SIZE,stdin);
StringArray* parsed_input = tokenizer(input_buffer," \n");
Command* c = get_command(options,parsed_input->strings[0]);
if( c && parsed_input->size == c->expected_param_count) {
if (strcmp(c->name, "quit") == 0){
checking = 0;
}
printf("Valid command used\n");
}
else {
printf("Invalid command, please try again\n");
}
free_string_array(parsed_input);
}while (checking);
destroy_commands_tree(options);
}
void create_commands_tree(Command **commands, const char *file) {
FILE *input;
input = fopen(file, "r");
char strings[100];
StringArray *temp2;
while(fgets(strings,100,input)){
temp2 = tokenizer(strings, "\n");
insert_into_commands_tree(commands,temp2->strings);
}
}
void insert_into_commands_tree(Command** node, char** data) {
if(*node == NULL){
*node = create_command(data);
}
else if( *node != NULL){
if(strcmp(data[0],(*node)->name) < 0)
insert_into_commands_tree(&(*node)->left,data);
else if(strcmp(data[0], (*node)->name) > 0)
insert_into_commands_tree(&(*node)->right,data);
}
}
Command* create_command(char **data) {
Command* new_;
new_ = (Command*)malloc(sizeof(Command));
strncpy(new_->name, data[0], COMMAND_NAME_LEN);
new_->expected_param_count = atoi(data[1]);
new_->right = NULL;
new_->left = NULL;
return new_;
}
Command* get_command(Command *node, const char *command) {
Command *temp = node;
int compare;
if(temp){
compare = strcmp(node->name, command);
if(compare == 0){
return temp;
}
else if(compare < 0){
return (get_command(node->right, command));
}
else{
if(compare > 0){
return (get_command(node->left, command));
}}
}
return temp;
}
void destroy_commands_tree(Command* node) {
if( node == NULL){
return;
}
destroy_commands_tree(node->left);
destroy_commands_tree(node->right);
free(node);
}
void display_commands(Command *node) {
printf("\npickup <item>");
printf("\nhelp ");
printf("\nquit ");
printf("\nload <file>\n\n");
}
StringArray* tokenizer (char *string, const char* delimiters){
StringArray* sr = malloc(sizeof(StringArray));
sr->strings = malloc(MAX_SPLIT_SIZE * sizeof(char *));
size_t len;
char* hold;
(sr->strings)[0] = malloc(MAX_BUFF_SIZE * sizeof(char));
hold = strtok(string, delimiters);
int i;
for(i = 1; i < MAX_SPLIT_SIZE; i++){
hold = strtok(NULL, delimiters);
if(hold == NULL){
sr->size = i + 1;
break;
}
(sr->strings)[i] = malloc(MAX_BUFF_SIZE * sizeof(char));
strcpy((sr->strings)[i], hold);
}
return sr;
}
void free_string_array(StringArray *sr) {
int i;
for(i = 0; i < sr->size; ++i){
free(sr->strings[i]);
}
free(sr->strings);
free(sr);
}
以下是给出的示例输出:
]$ ./a.out commands.dat
Command: pickup
Invalid command, please try again
Command: pickup ball
Valid command used
Command: quit 1
Invalid command, please try again
Command: load
Invalid command, please try again
Command: load bak.sav
Valid command used
Command: help
Valid command used
Command: help 2
Invalid command, please try again
Command: quit
Valid command used
我们读到的文件如下:
pickup,2
help,1
quit,1
load,2
答案 0 :(得分:0)
此代码存在以下几个问题:
insert_into_commands_tree
如上面的评论所述,条件应为if (*node == NULL)
。这可能是导致段错误的原因。
此外,if ... else if
结构在这里有点多余,因为它是真/假条件。你可以简单地使用:
void insert_into_commands_tree(Command** node, char** data) {
if(*node == NULL) {
*node = create_command(data);
}
else {
if(strcmp(data[0],(*node)->name) < 0)
insert_into_commands_tree(&(*node)->left,data);
else if(strcmp(data[0], (*node)->name) > 0)
insert_into_commands_tree(&(*node)->right,data);
}
}
(但它只是一个小细节)
create_commands_tree
你在这里做的是用fgets
读取输入文件的一行,并将此行与toker "\n"
分开,这是没用的(因为fgets
已经分隔了这些行) 。我想你的意思是:
temp2 = tokenizer(strings, ",");
tokenizer
此功能的输出不是它应该的。这里的主要问题是您不会将第一个令牌复制到StringArray
。以下是有效(和简化的)tokenizer
函数:
StringArray* tokenizer (char *string, const char* delimiters)
{
StringArray* sr = malloc(sizeof(StringArray));
sr->strings = malloc(MAX_SPLIT_SIZE * sizeof(char *));
char* hold;
int i = 0;
hold = strtok(string, delimiters);
while ((hold != NULL) && (i < MAX_SPLIT_SIZE))
{
(sr->strings)[i] = malloc(MAX_BUFF_SIZE * sizeof(char));
strncpy((sr->strings)[i], hold, MAX_SPLIT_SIZE);
i++;
hold = strtok(NULL, delimiters);
}
sr->size = i;
return sr;
}
通过这些修改,您的代码似乎符合您的期望。