CS50 - LOAD - Получить случайный символ из ниоткуда при попытке выполнить загрузку - PullRequest
0 голосов
/ 15 ноября 2018

Я новичок в программировании на C. Я пытаюсь сделать pset5 в CS50, пытаясь понять концепции памяти, связанного списка и хэш-таблицы. Я написал код, и он скомпилирован, но, похоже, что-то не так, потому что каждый раз, когда я пытался выполнить код, он возвращает какое-то мусорное значение. Может ли кто-нибудь помочь мне с этим? Большое спасибо.

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

#include "dictionary.h"

#define DICTIONARY "dictionaries/small"

typedef struct node
{
char WORD[LENGTH + 1];
struct node *next;
}
node;

int hash(char *word);

int main(void)
{
node **HASHTABLE = malloc(sizeof(node) * 26);

//open the dictionary
FILE *dic = fopen(DICTIONARY, "r");
if (dic == NULL)
{
    fprintf(stderr, "Could not open the library\n");
    return 1;
}

int index = 0;
char word[LENGTH + 1];

for (int c = fgetc(dic); c != EOF; c = fgetc(dic))
{
    word[index] = c;
    index++;

    if (c == '\n')
    {
        int table = hash(word);
        printf("%d\n", table);
        //create a newnode
        node *newnode = malloc(sizeof(node));
        strcpy(newnode->WORD, word);
        newnode->next = NULL;

        printf("Node: %s\n", newnode->WORD);
        index = 0;

        //add new node to hash table
        if (HASHTABLE[table] == NULL)
        {
            HASHTABLE[table] = newnode;
        }
        else
        {
            HASHTABLE[table]->next = newnode;
        }
    }
}
for(int i = 0; i < 26; i++)
{
    node *p = HASHTABLE[i];
    while (p != NULL)
    {
        printf("%s", p->WORD);
        p = p->next;
    }
}

//free memory
for(int i = 0; i < 26; i++)
{
    node *p = HASHTABLE[i];
    while (p != NULL)
    {
        node *temp = p->next;
        free(p);
        p = temp;
    }
}
free(HASHTABLE);
}


int hash(char *word)
{
int i = 0;
if (islower(word[0]))
    return i = word[0] - 'a';
if (isupper(word[0]))
    return i = word[0] - 'A';
return 0;
}

enter image description here

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Причина мусора в том, что вы не завершили нулем строка:

strcpy(newnode->WORD, word);

strcpy ожидает, что src будет указывать на строку с нулевым символом в конце. Просто добавив 0 в конце. Просто прекратить это с

word[index] = 0;

до strcpy.

Кроме этого, те, что в ответе Эндрю Хенле также должны быть рассмотрены, но я не буду повторять их здесь.


Кстати, дальше вы заметите, что

HASHTABLE[table]->next = newnode;

не будет работать должным образом - этот код всегда вставляет узел как второй. Но вы хотите всегда вставить новый узел безоговорочно как head , с

newnode->next = HASHTABLE[table];
HASHTABLE[table] = newnode;

Не должно быть никаких особых условий для вставки первого узла в корзину .

0 голосов
/ 15 ноября 2018

Ваш код имеет серьезные проблемы, которые приводят к неопределенному поведению.

Два из них являются результатом этой строки:

node **HASHTABLE = malloc(sizeof(node) * 26);

, которая выделяет 26 node структуры , но переменная HASHTABLE ожидает адрес указателя на массив node * указателей (это ** в объявлении node **HASHTABLE).

Итак, вы должны заменить его на что-то вроде:

node **HASHTABLE = malloc( 26 * sizeof( *HASHTABLE ) );

Обратите внимание, что я использовал разыменованное значение переменной, присваиваемой - HASHTABLE.В данном случае это означает node (на один * меньше, чем в объявлении).Поэтому, если тип HASHTABLE изменяется, вам не нужно вносить какие-либо другие изменения в оператор malloc().

Эта проблема, хотя и технически неопределенное поведение, скорее всего, не вызовет никаких проблем.

Однако с

node **HASHTABLE = malloc( 26 * sizeof( *HASHTABLE ) );

по-прежнему существует проблема, которая вызовет проблем - и серьезных.

Этот массив из 26 указателей неинициализировано - вы не знаете, что в них .Они могут указывать куда угодно.Так что это не будет работать хорошо, если вообще:

    if (HASHTABLE[table] == NULL)

Это означает, что это указывает на неизвестное место:

    HASHTABLE[table]->next = newnode;

И , что вызовет все видыпроблем.

Самое простое решение?Инициализируйте все значения до нуля, используя calloc() вместо malloc():

node **HASHTABLE = calloc( 26, sizeof( *HASHTABLE ) );

Пока это не исправлено, любые результаты всей вашей программы в лучшем случае сомнительны.

...