CS50:Speller (pset5) 产生的输出与工作人员的解决方案完全相同,但检查了 50 returns 个错误。发生了什么?
CS50: Speller (pset5) produces output that is exactly the same as the staff's solution, but check50 returns many errors. What's happening?
我的拼写程序(pset5 的一部分)运行良好,输出与工作人员的解决方案完全匹配。但是,当我 运行 我的程序通过 check50 时,我的脚本仍然有几个错误:
:) dictionary.c, dictionary.h, and Makefile exist
:) speller compiles
:) handles most basic words properly
:( handles min length (1-char) words
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:( handles max length (45-char) words
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:( handles words with apostrophes properly
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:( spell-checking is case-insensitive
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:) handles substrings properly
:) program is free of memory errors
这些错误是 st运行ge。我的程序肯定能识别单字符单词,例如 "a" 和 "i," 正确使用撇号等。我知道这一点,因为我 运行 我旁边的工作人员的解决方案并以编程方式比较了拼写错误的单词Excel:都匹配了。
这是我的代码。我找不到让 check50 旅行的原因。感谢任何勇敢的灵魂回答!
// Implements a dictionary's functionality
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.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;
// Number of buckets in hash table
const unsigned int N = 26;
// Hash table
node *table[N]; // This looks like just the beginning of the list
// Variable added by me: A counter for each word added into the dictionary
int wordLoadedCount = 0;
// Returns true if word is in dictionary else false
// This is where the actual dictionary is put to work.
// check will only be passed words that contain letters and possibly apostrophes
bool check(const char *word)
{
// CASE INSENSITIVE
// 0. Remove apostrophes from the word [???]
// 1. Hash word to obtain a hash value
int index = hash(word);
// 2. Access linked list at the index in the hash table
//Pointer to the first node: table[index]
// 3. Traverse linked list, looking for the word.
// CODE FROM WEEK 5 LECTURE
// Print List / Loop Through Linked List
for (node *tmp = table[index]; tmp != NULL; tmp = tmp->next)
{
if (strcasecmp(word, tmp->word) == 0)
{
return true;
}
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
//Objective: Return a number from 0 to 25 given the first letter of the word.
//Initialize index variable
int index = 26;
//Check the first letter of the word and convert it to an index from 0 to 25:
// Convert the first number to its ASCII-equivalent int
int firstLetter = (int)word[0];
// Case: Uppercase letters
if (firstLetter >= 65 && firstLetter <= 90)
{
// We want index = 0 when ASCII value = 65
index = firstLetter - 65;
}
// Case: /Lowercase letters
else if (firstLetter >= 97 && firstLetter <= 122)
{
//We want index = 0 when ASCII value = 97
index = firstLetter - 97;
}
//Check to make sure the return value is actually between 0 and 25 (that the value
//was actually changed
if (index == 26)
{
printf("We could not hash %s.\n", word);
return -1;
}
//Return index as intended
return index;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
// 1. Open dictionary file
FILE *file = fopen(dictionary, "r");
// Intermediate check to see if the file opened
if (file == NULL)
{
printf("Could not open %s.\n", dictionary);
unload();
return false;
}
//Initialize a buffer variable where we are storing each word
char storedWord[LENGTH + 1];
// 2. Read strings from the file one at the time
while(fscanf(file, "%s", storedWord) != EOF)
{
//3. Create a new node for each word
node *newNode = malloc(sizeof(node));
//Check if malloc() returns NULL
if (newNode == NULL)
{
printf("You program ran out of memory\n");
return false;
}
//Copy the word into the newly created node using strcpy()
strcpy(newNode->word, storedWord);
newNode->next = NULL;
// Update "word loaded" count.
wordLoadedCount++;
// 4. Hash word to obtain hash value / index
int index = hash(storedWord);
//5. Insert node into the hash table at that location
// If this bucket of the hash table is empty (not pointing at anything yet)
// I'm not sure if this step is necessary
if (table[index] == NULL)
{
table[index] = newNode;
newNode->next = NULL;
}
// If it is not empty:
else if (table[index] != NULL)
{
//a. Point new node to the existing first node
newNode->next = table[index];
//b. Point the list head to the new node
table[index] = newNode;
}
}
//Close the file to release memory
fclose(file);
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
// If the dictionary was loaded...
if (wordLoadedCount > 1)
{
// Go through hash stucture created in load() and count the words stored
// I will do this inside the load function itself
return wordLoadedCount;
}
// Return 0 if the dictionary not loaded
return 0;
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
// Loop through each bucket in the hash table
for (int i = 0; i < N; i++)
{
// COPIED FROM WEEK 5 LECTURE CODE
// "Free list
// Since we're freeing each node as we go along, we'll use a while loop
// and follow each node's next pointer before freeing it, but we'll see
// this in more detail in Problem Set 5."
while (table[i] != NULL)
{
node *tmp = table[i]->next;
free(table[i]);
table[i] = tmp;
}
//Check to see if we did in fact clear the memory allocated to the hash table.
if (table[i] != NULL)
{
printf("Something went wrong while freeing memory in unload() function.\n");
return false;
}
}
//Return true if sucessful
return true;
}
创建一个单词词典。将它用作 ./speller
的两个参数。程序会产生这些计数结果吗?
WORDS MISSPELLED: 0
WORDS IN DICTIONARY: 1
WORDS IN TEXT: 1
集中精力在size
函数上寻找问题。
我的拼写程序(pset5 的一部分)运行良好,输出与工作人员的解决方案完全匹配。但是,当我 运行 我的程序通过 check50 时,我的脚本仍然有几个错误:
:) dictionary.c, dictionary.h, and Makefile exist
:) speller compiles
:) handles most basic words properly
:( handles min length (1-char) words
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:( handles max length (45-char) words
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:( handles words with apostrophes properly
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:( spell-checking is case-insensitive
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:) handles substrings properly
:) program is free of memory errors
这些错误是 st运行ge。我的程序肯定能识别单字符单词,例如 "a" 和 "i," 正确使用撇号等。我知道这一点,因为我 运行 我旁边的工作人员的解决方案并以编程方式比较了拼写错误的单词Excel:都匹配了。
这是我的代码。我找不到让 check50 旅行的原因。感谢任何勇敢的灵魂回答!
// Implements a dictionary's functionality
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.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;
// Number of buckets in hash table
const unsigned int N = 26;
// Hash table
node *table[N]; // This looks like just the beginning of the list
// Variable added by me: A counter for each word added into the dictionary
int wordLoadedCount = 0;
// Returns true if word is in dictionary else false
// This is where the actual dictionary is put to work.
// check will only be passed words that contain letters and possibly apostrophes
bool check(const char *word)
{
// CASE INSENSITIVE
// 0. Remove apostrophes from the word [???]
// 1. Hash word to obtain a hash value
int index = hash(word);
// 2. Access linked list at the index in the hash table
//Pointer to the first node: table[index]
// 3. Traverse linked list, looking for the word.
// CODE FROM WEEK 5 LECTURE
// Print List / Loop Through Linked List
for (node *tmp = table[index]; tmp != NULL; tmp = tmp->next)
{
if (strcasecmp(word, tmp->word) == 0)
{
return true;
}
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
//Objective: Return a number from 0 to 25 given the first letter of the word.
//Initialize index variable
int index = 26;
//Check the first letter of the word and convert it to an index from 0 to 25:
// Convert the first number to its ASCII-equivalent int
int firstLetter = (int)word[0];
// Case: Uppercase letters
if (firstLetter >= 65 && firstLetter <= 90)
{
// We want index = 0 when ASCII value = 65
index = firstLetter - 65;
}
// Case: /Lowercase letters
else if (firstLetter >= 97 && firstLetter <= 122)
{
//We want index = 0 when ASCII value = 97
index = firstLetter - 97;
}
//Check to make sure the return value is actually between 0 and 25 (that the value
//was actually changed
if (index == 26)
{
printf("We could not hash %s.\n", word);
return -1;
}
//Return index as intended
return index;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
// 1. Open dictionary file
FILE *file = fopen(dictionary, "r");
// Intermediate check to see if the file opened
if (file == NULL)
{
printf("Could not open %s.\n", dictionary);
unload();
return false;
}
//Initialize a buffer variable where we are storing each word
char storedWord[LENGTH + 1];
// 2. Read strings from the file one at the time
while(fscanf(file, "%s", storedWord) != EOF)
{
//3. Create a new node for each word
node *newNode = malloc(sizeof(node));
//Check if malloc() returns NULL
if (newNode == NULL)
{
printf("You program ran out of memory\n");
return false;
}
//Copy the word into the newly created node using strcpy()
strcpy(newNode->word, storedWord);
newNode->next = NULL;
// Update "word loaded" count.
wordLoadedCount++;
// 4. Hash word to obtain hash value / index
int index = hash(storedWord);
//5. Insert node into the hash table at that location
// If this bucket of the hash table is empty (not pointing at anything yet)
// I'm not sure if this step is necessary
if (table[index] == NULL)
{
table[index] = newNode;
newNode->next = NULL;
}
// If it is not empty:
else if (table[index] != NULL)
{
//a. Point new node to the existing first node
newNode->next = table[index];
//b. Point the list head to the new node
table[index] = newNode;
}
}
//Close the file to release memory
fclose(file);
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
// If the dictionary was loaded...
if (wordLoadedCount > 1)
{
// Go through hash stucture created in load() and count the words stored
// I will do this inside the load function itself
return wordLoadedCount;
}
// Return 0 if the dictionary not loaded
return 0;
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
// Loop through each bucket in the hash table
for (int i = 0; i < N; i++)
{
// COPIED FROM WEEK 5 LECTURE CODE
// "Free list
// Since we're freeing each node as we go along, we'll use a while loop
// and follow each node's next pointer before freeing it, but we'll see
// this in more detail in Problem Set 5."
while (table[i] != NULL)
{
node *tmp = table[i]->next;
free(table[i]);
table[i] = tmp;
}
//Check to see if we did in fact clear the memory allocated to the hash table.
if (table[i] != NULL)
{
printf("Something went wrong while freeing memory in unload() function.\n");
return false;
}
}
//Return true if sucessful
return true;
}
创建一个单词词典。将它用作 ./speller
的两个参数。程序会产生这些计数结果吗?
WORDS MISSPELLED: 0
WORDS IN DICTIONARY: 1
WORDS IN TEXT: 1
集中精力在size
函数上寻找问题。