【问题标题】:segmentation fault in speller cs50拼写器 cs50 中的分段错误
【发布时间】:2020-08-08 05:26:39
【问题描述】:

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

【问题讨论】:

  • 您在load() 函数中的以下行中的条件错误:while (fscanf(dict, "%s", word) == EOF)== 应该是 !==
  • 谢谢。我改变了它。我仍然遇到分段错误。

标签: c cs50


【解决方案1】:

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

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

修改后:

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

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

【讨论】:

  • 谢谢。但在我阅读您的评论之前,我已经替换了整个部分,现在我正在使用 strcasecmp。据我所知,它不区分大小写,这使得您提到的部分变得不必要。但是,更新后的代码在我使用 strcasecmp 的行的检查函数中仍然存在 seg 错误(请参阅我已编辑帖子底部的更新)。你能看出问题出在哪里吗?
  • 谢谢。我使用了模运算符,我目前正在寻找代码中的其他错误,因为我仍然得到 seg 错误
  • 到目前为止,我已经尽可能地更新了代码,并且得到了一些结果。不幸的是,几乎整个文本都拼写错误(查看结果)并且字典的大小等于 N。此外,每当我尝试按照您的建议使用小字典时,我都会收到消息说它不可能打开。你能看到我需要改进代码的地方吗?
猜你喜欢
  • 2020-08-25
  • 2020-12-20
  • 2021-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-02
  • 2020-09-22
相关资源
最近更新 更多