2015-06-16 2 views
1

Я создал древовидную структуру, прочитал слова из файла и зарегистрировал их в дереве. Но enter() не работает должным образом. Я отлаживал с помощью gdb и устанавливал линию 42 точки останова. Затем я ввел print *nodeprint *root.двоичный код дерева не работает должным образом

(gdb) print node 
$9 = (struct node *) 0x603250 
(gdb) print *node 
$10 = {left = 0x0, right = 0x0, word = 0x0} 
(gdb) print root 
$11 = (struct node *) 0x0 
(gdb) print *root 
Cannot access memory at address 0x0 

Почему root ничего не говорит? Почему не node->word Точка в виде данного слова?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <ctype.h> 

struct node { 
    struct node *left; 
    struct node *right; 
    char *word; 
}; 

static struct node *root = NULL; 

void memory_error(void) { 
    fprintf(stderr, "Error: Out of memory\n"); 
    exit(8); 
} 

char *save_string(char *string) { 
    char *new_string; 

    new_string = malloc((unsigned) (strlen(string) + 1)); 

    if (new_string == NULL) 
    memory_error(); 

    strcpy(new_string, string); 

    return (new_string); 
} 

void enter(struct node *node, char *word) { 
    int result; 

    if (node == NULL) { 
    node = malloc(sizeof(struct node)); 
    if (node == NULL) 
     memory_error(); 

    node->left = NULL; 
    node->right = NULL; 
    node->word = save_string(word); 
    return; 
    } 

    result = strcmp(node->word, word); 

    if (result == 0) 
    return; 

    if (result < 0) 
    enter(node->right, word); 
    else 
    enter(node->left, word); 
} 

void scan(char *name) { 
    char word[100]; 
    int index; 
    int ch; 
    FILE *in_file; 

    in_file = fopen(name, "r"); 
    if (in_file == NULL) { 
    fprintf(stderr, "Error: Unable to open %s\n", name); 
    exit(8); 
    } 

    while (1) { 
    while (1) { 
     ch = fgetc(in_file); 

     if (isalpha(ch) || (ch == EOF)) 
    break; 
    } 

    if (ch == EOF) 
     break; 

    word[0] = ch; 
    for (index = 1; index < sizeof(word); index++) { 
     ch = fgetc(in_file); 
     if (!isalpha(ch)) 
    break; 
     word[index] = ch; 
    } 

    word[index] = '\0'; 

    enter(root, word); 
    } 

    fclose(in_file); 
} 

void print_tree(struct node *top) { 
    if (top == NULL) 
    return; 

    print_tree(top->left); 
    printf("%s\n", top->word); 
    print_tree(top->right); 
} 

int main(int argc, char *argv[]) { 
    if (argc != 2) { 
    fprintf(stderr, "Error: Wrong number of parameters\n"); 
    fprintf(stderr, "  on the command line\n"); 
    fprintf(stderr, "Usage is:\n"); 
    fprintf(stderr, "   words 'file'\n"); 
    exit(8); 
    } 

    scan(argv[1]); 
    print_tree(root); 
    return (0); 
} 

Я передал этой программе следующий текст в качестве аргумента «a.txt».

apple 
orange 
lemon 
banana 
pine 
stroberry 
ruby 
perl 
python 
c 

ответ

1

Похоже, что вы никогда не присвоить любое значение root. Помните, что C передает аргументы по значению, поэтому, когда вы вызываете enter(root, word); от scan(), enter() не может изменить значение root. Однако он меняет свою локальную копию, но этого недостаточно.

Та же проблема возникает, когда вы рекурсивно вызываете enter.

Один из способов фиксации этого может передать указатель на указатель узла, так что вы можете изменить его таким образом:

enter(&root, word); 

с этой декларацией:

void enter(struct node **nodep, char *word) { 

и адаптировать все виды использования из node внутри, чтобы стать *nodep.

5

Ни в коем случае не назначайте root. Поэтому он всегда останется NULL.

Обратите внимание, что в enter вы назначаете узел, но фактически не сохраняете результирующий узел в любом месте. Вы можете захотеть вернуть новый узел и вместо этого сделать root = enter(root, word).

+0

Альтернативно, если по какой-то причине вы не хотите возвращать 'root' (потому что, скажем, вы хотите вернуть код ошибки), вы можете передать указатель на' root', чтобы вы могли назначьте 'root' внутри функции. – Thomas

2

, как @nneonneo отметил, вы должны либо вернуть новый измененный корень, или передать корень в качестве ссылки указатель, имеющий void enter(struct node **node, char *word) и называя его enter(&root, word);

0

Вы назначаете узел в enter(), но поскольку он передан копией, а не ссылкой, узел не изменяется вне функции.

Либо вернуть новый узел root = enter(root, word) или передать по ссылке: enter(&root, word), изменяя след войти в void enter(struct node **node, char *word) и все экземпляры узла в пределах до * узла.

Смежные вопросы