Язык C: реализовать массив, содержащий BST строк (слов) из текстового файла - PullRequest
0 голосов
/ 02 декабря 2018

Я пытаюсь создать небольшую программу, которая читает слова из текстового файла неизвестного размера и сохраняет эти слова в массив деревьев двоичного поиска (BST).Каждый индекс в массиве представляет длину слов в этом дереве BST.

Например, индекс 0 не содержит слов, но индекс 1 содержит дерево BST со словами длиной в одну букву, а индекс 5 содержит дерево BST со словами длиной 5 букв и т. Д. Все деревья BST сбалансированы с помощьюсравнивая две строки, чтобы определить, больше или меньше новая строка, чем корневая строка, и затем назначить ее соответствующим образом.

Мой исходный код содержит непрозрачные объекты (указатели void).Но я включил уменьшенную версию программы, которую я пытаюсь понять.Я включил 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 );
    }
}

Еще раз спасибо!

1 Ответ

0 голосов
/ 02 декабря 2018

Два основных совета:

  1. Вместо отладочного вывода вы можете использовать отладчик, чтобы найти точное местоположение ошибки (например, узнать, как использовать gdb).Конечно, вы можете использовать отладочный вывод, но это может занять больше времени, и вы должны очистить его после этого.
  2. Не игнорируйте предупреждения компилятора.

Мой компилятор говорит:

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 подпись и заставить его вернуть только что созданный Root.Я не понимаю сценарий, когда вам нужно инициировать существующее дерево, поэтому это кажется естественным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...