首页 > 解决方案 > 拼写器 cs50 中的分段错误

问题描述

目前,我正在研究 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

标签: ccs50

解决方案


错误的近因:NULL 是一个常数,这意味着它不能被改变,这一行char *lower_word = NULL;设置lower_word为 NULL,这一行strcpy(lower_word, word);试图改变它。段错误。

也许考虑简单地迭代单词并将每个字符设置为“就地”降低。

编辑后:

table分配给 N (27) 个元素。该hash函数返回的值WAY大于 27。您可以将哈希函数更改为简单的字母索引(类似于tolower(word[i]) - 'a')或使用模 ( %) 运算符来限制存储桶大小。

这些可能不是程序中唯一的问题,但当然需要修复 seg 错误才能取得真正的进展。debug50是你的朋友(和小字典一起使用更容易!)


推荐阅读