Моя программа проверки правописания (часть 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
Эти ошибки странные. Моя программа определенно распознает односимвольные слова, такие как «a» и «i», правильно принимает апострофы, et c. Я знаю это, так как я запустил решение персонала рядом со своим и программно сравнил слова с ошибками в 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;
}