【问题标题】:Program didnt exit/terminated correctly (CS50 Speller)程序没有正确退出/终止(CS50 Speller)
【发布时间】:2022-01-05 04:09:05
【问题描述】:

程序对与给定字典(CS50:Pset5 Speller)配对的文本运行拼写检查。字典文件为txt文件形式,以哈希表的形式加载到内存中。

检查函数接受从文本文件中读取的单词的参数。该词被散列并与给定的单个散列表中存在的任何元素进行比较。如果一个单词存在,则返回 true,否则返回 false。

Hash 是对任何给定单词进行散列,而 Load 函数是将字典中的单词加载到散列表中单词的相应散列索引。 Load Function 将指向字典的指针作为参数。

Size 函数通过指向现有的哈希表来测量字典的大小。

Unload 函数在哈希表的每个可能索引上重复,同时调用 ClearNodes 来检查连接到哈希表的链表中的内容。

我尝试将文本和字典的大小调整为较小的大小,并且我尝试在调用单个函数之前和之后放置断点(因为不知何故将断点放置在 main() loads the dictionaryFinished checking all the words in a given text 之后,然后在调试器中手动按step-over直到main()完成,设法使程序正常终止)。对于较小尺寸的字典和文本,我没有发现任何导致函数不返回值的相似之处。请记住,unload 函数假定此时始终返回 true 并且尚未完成。

Minimum Reproducible Example

非常感谢您的帮助。

// Implements a dictionary's functionality

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


#include "dictionary.h"

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

// TODO: Choose number of buckets in hash table
const unsigned int N = 17576;

// Hash table
node *table[N];

// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    //Create Word Hash Value
    int WordHashIndex = hash(word);
    node *Temp = table[WordHashIndex];

    //Jump to Hash Index
    while(Temp != NULL)
    {
        if(strcasecmp(Temp -> word, word) != 0)
        {
            Temp = Temp -> next;
        }
        else
        {
            return true;
        }
    }

    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    // TODO: Improve this hash function
    if(word[1] == '\0')
    {
        return (toupper(word[0]) - 65);
    }
    else if(word[2] == '\0')
    {
        return ((toupper(word[0]) - 65) + ((((toupper(word[1]) - 65) * 26) > -1) ? ((toupper(word[1]) - 65) * 26) : 0));
    }
    else
    {
        return ((toupper(word[0]) - 65) + ((((toupper(word[1]) - 65) * 26) > -1) ? ((toupper(word[1]) - 65) * 26) : 0) + ((((toupper(word[2]) - 65) * 676) > -1) ? ((toupper(word[2]) - 65) * 676) : 0));
    }
}

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    // TODO
    int HashedIndex = 0;
    char TempWord[LENGTH + 1];
    int CharLengthCounter = 0;

    FILE *LoadedDictionary = fopen(dictionary, "r");
    if(LoadedDictionary == NULL)
    {
        return false;
    }

    while(fscanf(LoadedDictionary, "%s", TempWord) != EOF)
    {
        HashedIndex = hash(TempWord);
        node *TempNode = NULL;

        //Jump To HashedIndex
        if(table[HashedIndex] != NULL)
        {
            TempNode = malloc(sizeof(node));
            TempNode -> next = table[HashedIndex] -> next;
            table[HashedIndex] -> next = TempNode;
            strcpy(TempNode -> word, TempWord);

        }
        else
        {
            TempNode = malloc(sizeof(node));
            table[HashedIndex] = TempNode;
            strcpy(table[HashedIndex] -> word, TempWord);
        }
    }

    if(LoadedDictionary != NULL)
    {
        free(LoadedDictionary);
        return true;
    }
    else
    {
        return false;
    }
}

// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
    // TODO
    node *Temp;
    int DictSize = 0;

    for(int Counter = 0; Counter < N; Counter++)
    {
        Temp = table[Counter];
        if(Temp != NULL)
        {
            DictSize++;
            while(Temp -> next != NULL)
            {
                Temp = Temp -> next;
                DictSize++;
            }
        }
        else
        {
            continue;
        }
    }

    if(DictSize != 0)
    {
        return DictSize;
    }
    else
    {
        return 0;
    }
}

//Check Node Data and Length Inside Each Table
bool ClearNodes(node *CurrentIndex)
{
    if(CurrentIndex != NULL)
    {
        if(CurrentIndex -> next != NULL)
        {
            if(ClearNodes(CurrentIndex -> next))
            {
                free(CurrentIndex);
                return true;
            }
        }
        else
        {
            free(CurrentIndex);
            return true;
        }
    }

    return false;
}

// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
    // TODO
    int TableElementsCheck = 0;

    for(int Counter = 0; Counter < N; Counter++)
    {
        ClearNodes(table[Counter]);
    }

        return true;
}

【问题讨论】:

  • 寻求调试帮助的问题通常应包括问题的minimal reproducible example。您发布的代码不完整,因为它不包含函数main,并且它引用了您尚未发布的头文件dictionary.h。此外,您没有提供任何重现错误的示例输入。
  • 旁注:如果你写的是return (toupper(word[0]) - 'A');而不是return (toupper(word[0]) - 65);,你的代码会更容易阅读。
  • @AndreasWenzel 感谢您的建议。如果添加这些文件会使它比现在更混乱,请原谅我。
  • "(since somehow manually step over the codes in debugger casuse[sic] the program to terminate)" -- 你确定你没有把“跨过”和“走出”混为一谈吗?一些调试器有一个功能,可以让你继续运行直到函数返回,我相信它通常被称为“跳出”。如果您在main 中使用该功能,那么这当然会运行您的程序,直到它终止。您使用的是哪个调试器?是CS50提供的吗?
  • @AndreasWenzel 因为以某种方式手动跳过调试器中的代码导致程序终止我所说的那一行,当断点放在load() function之后和@之后987654335@,如果您手动按下 step over 直到 main 完成,程序会以某种方式正常终止。我的错误我会改正的。

标签: c dictionary pointers hash cs50


【解决方案1】:

你的问题在load函数中至少有以下bug:

下面的块是错误的:

else
{
    TempNode = malloc(sizeof(node));
    table[HashedIndex] = TempNode;
    strcpy(table[HashedIndex] -> word, TempWord);
}

您忘记将TempNode-&gt;next 设置为NULL

还有一行

free(LoadedDictionary);

错了。您应该在函数fopen 返回的FILE * 上调用fclose 而不是free

修复这些错误后,输出显示正确:

MISSPELLED WORDS

A
is
not
a

此输出是正确的,因为您提供的字典中不存在这些单词。 catcaterpillar 这两个词没有打印错,因为它们在字典中。

【讨论】:

    猜你喜欢
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多