ошибка сегментации в speller cs50 - PullRequest
0 голосов
/ 24 апреля 2020

В настоящее время я работаю над pset5, и всякий раз, когда я пытаюсь скомпилировать, я получаю ошибку сегментации. Я не мог найти, где лежит ошибка, и я был бы очень признателен за помощь эксперта здесь. Намекнуть на ошибки совершенно нормально.

Код:

// Implements a dictionary's functionality

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "dictionary.h"

int word_count = 0;

// Represents a node in a hash table
typedef struct node
{
    char word[LENGTH + 1];
    struct node *next;
}
node;

// Number of buckets in hash table
const unsigned int N = 27;

// Hash table
node *table[N];

// Returns true if word is in dictionary else false
bool check(const char *word)
{
    // Converting word to lower case
    char *lower_word = NULL;
    strcpy(lower_word, word);
    int len = 0;
    len = sizeof(lower_word);
    for (int i = 0; i < len; i++)
    {
        lower_word[i] = tolower(lower_word[i]);
    }

    node *head = NULL;
    node * cursor = NULL;
    cursor = head;

    while (cursor != NULL)
    {
        cursor = head;
        if (cursor -> word == lower_word)
        {
            return true;
        }
        else
        {
            cursor = cursor -> next;
        }
    }
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    // TODO
    // From: http://www.cse.yorku.ca/~oz/hash.html
    unsigned long sdbm(char *word);
    {
        unsigned long hash = 0;
        int c;
        while ((c = *word++))
        {
            hash = c + (hash << 6) + (hash << 16) - hash;
            // Deleted free(word);

        }
        return hash;
    }
    return 0;
}

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    // Opening the file
    FILE *dict = fopen(dictionary, "r");
    if (dict == NULL)
    {
        return false;
    }

    // Read strings from file
    char word[LENGTH + 1];

    for (int i = 0; i < N; i++)
    {
        table[i] = NULL;
    }

    while (fscanf(dict, "%s", word) == EOF)
    {
        // Create a new node
        node *n = malloc(sizeof(node));
        n -> next = NULL;

        if (n == NULL)
        {
            return 1;
        }

        // Insert word into node
        int x = hash(word);

        strcpy(n -> word, word);

        // Set position x in table equal to node

        if(table[x] == NULL)
        {
            table[x] = n;
        }
        else
        {
            n = table[x];
            table[x] = n;
        }

        // Count word for size function
        word_count++;
    }
    fclose(dict);
    return true;
}

// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
    // TODO
    int table_size = 0;
    table_size = sizeof(table)/sizeof(table[0]);
    int count = 0;
    for (int i = 0; i < table_size; i++)
    {
        count++;
    }
    return count;
    return 0;
}

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    // TODO
    int table_size = 0;
    table_size = sizeof(table)/sizeof(table[0]);

    node *cursor = NULL;
    node* tmp = NULL;
    for (int i = 0; i < table_size; i++)
    {
        while (cursor != NULL)
        {
            tmp = cursor;
            cursor = cursor -> next;
            free(tmp);
        }
    }
    return true;
}

Ввод:

./speller texts/lalaland.txt

Вывод:

MISSPELLED WORDS

Segmentation fault

Кто-то сталкивался CS50 pset5 а можно мне? Для получения дополнительной информации, пожалуйста, обратитесь к: https://cs50.harvard.edu/x/2020/psets/5/speller/

Я много раз наблюдал прохождения и также проходил шорты, но я не делаю успехов.

обновление функция проверки:

{
    // Hash word to obtainhash value

    int bucket = hash(word);

    // Traverse linked list and look for the word using strcmp

    node *cursor = NULL;
    node *head = table[bucket];
    cursor = head;

    while (cursor != NULL)
    {
        if (strcasecmp(cursor -> word, word) == 0)
        {
            return true;
        }
        else
        {
            cursor = cursor -> next;
        }
    }
    return false;

}

обновление 2:

// Implements a dictionary's functionality

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <ctype.h>
#include "dictionary.h"

#define HASHMAX 1000

int word_count = 0;

// Represents a node in a hash table
typedef struct node
{
    char word[LENGTH + 1];
    struct node *next;
}
node;

// Number of buckets in hash table
const unsigned int N = 143091;


// Hash table
node *table[N];

// Returns true if word is in dictionary else false
bool check(const char *word)
{
    // Hash word to obtainhash value

    int bucket = hash(word);

    // Traverse linked list and look for the word using strcmp

    node *cursor = NULL;
    node *head = table[bucket];
    cursor = head;

    while (cursor != NULL)
    {
        if (strcasecmp(cursor -> word, word) == 0)
        {
            return true;
        }
        else
        {
            cursor = cursor -> next;
        }
    }
    return false;

}

// Hashes word to a number
unsigned int hash(const char *word)
{
    // TODO
    // From: http://www.cse.yorku.ca/~oz/hash.html
    unsigned long sdbm(char *word);
    {
        unsigned long hash = 5381;
        int c;
        while ((c = *word++))
        {
            hash = c + (hash << 6) + (hash << 16) - hash;
            // Deleted free(word);

        }
        return hash % HASHMAX;
    }
    return 0;
}

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    // Opening the file
    FILE *dict = fopen(dictionary, "r");
    if (dict == NULL)
    {
        return false;
    }

    // Read strings from file
    char word[LENGTH + 1];

    for (int i = 0; i < N; i++)
    {
        table[i] = NULL;
    }

    while (fscanf(dict, "%s", word) != EOF)
    {
        // Create a new node
        node *n = malloc(sizeof(node));
        n -> next = NULL;

        if (n == NULL)
        {
            return 1;
        }

        // Insert word into node
        int x = hash(word);

        strcpy(n -> word, word);

        // Set position x in table equal to node

        if(table[x] == NULL)
        {
            table[x] = n;
        }
        else
        {
            n = table[x];
            table[x] = n;
        }

        // free(n);

        // Count word for size function
        word_count++;
    }
    fclose(dict);
    return true;
}




// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
    // TODO
    int table_size = sizeof(table)/sizeof(table[0]);
    int count = 0;
    for (int i = 0; i < table_size; i++)
    {
        count++;
    }
    return count;
    return 0;
}

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    // TODO
    int table_size = sizeof(table)/sizeof(table[0]);
    node *cursor = NULL;
    node* tmp = NULL;
    for (int i = 0; i < table_size; i++)
    {
        node *head = table[i];
        while (cursor != NULL)
        {
            tmp = cursor;
            cursor = cursor -> next;
            free(tmp);
        }
    }
    return true;
}

Результаты:

WORDS MISSPELLED:     17263
WORDS IN DICTIONARY:  143091
WORDS IN TEXT:        17756
TIME IN load:         0.02
TIME IN check:        0.01
TIME IN size:         0.00
TIME IN unload:       0.00
TIME IN TOTAL:        0.03

1 Ответ

1 голос
/ 24 апреля 2020

Непосредственная причина ошибки: NULL является константой, что означает, что ее нельзя изменить, эта строка char *lower_word = NULL; устанавливает lower_word в NULL, эта строка strcpy(lower_word, word); пытается ее изменить. Сег Вина.

Возможно, рассмотрите возможность простой итерации по слову и установки каждого символа в нижнее значение "на месте".

После редактирования:

table выделяется для N (27) элементов. Функция hash возвращает значения WAY больше 27. Вы можете изменить функцию ha sh на простой алфавитный указатель (что-то вроде tolower(word[i]) - 'a') ИЛИ использовать по модулю (%) оператор для ограничения размера ковша.

Возможно, это не единственные проблемы в программе, но, конечно, ошибка сегмента должна быть исправлена, прежде чем вы сможете добиться реального прогресса. debug50 ваш друг (и намного легче использовать с небольшим словарем!)

...