Почему функция printf влияет на мою программу speller? - PullRequest
0 голосов
/ 17 апреля 2020

Я использую функцию ha sh из inte rnet, и когда я использую функцию печати перед оператором return, она исправляет мою программу, но если я удаляю ее, она снова вызывает ошибки ... как буквально расстраивает, потому что я могу сделать printf("asfasfnasfnk\n");, и он будет выводить правильно, но как только я удаляю функцию printf, она снова глючит ...

unsigned int hash(const char *word)
{
    /* credits to...
     *https://www.reddit.com/r/cs50/comments/1x6vc8/pset6_trie_vs_hashtable/
     */
    unsigned long hash = 0;
    int n  = strlen(word);

    for (int i = 0; i < n; i++)
    {
        hash = (hash << 2) ^ word[i];
    }
    return hash % N;
}

Вывод:

MISSPELLED WORDS

A
is
not
a
caterpillar

WORDS MISSPELLED:     5
WORDS IN DICTIONARY:  2
WORDS IN TEXT:        6
TIME IN load:         0.00
TIME IN check:        0.00
TIME IN size:         0.00
TIME IN unload:       0.00
TIME IN TOTAL:        0.00
unsigned int hash(const char *word)
{
    /* credits to...
     *https://www.reddit.com/r/cs50/comments/1x6vc8/pset6_trie_vs_hashtable/
     */
    unsigned long hash = 0;
    int n  = strlen(word);

    for (int i = 0; i < n; i++)
    {
        hash = (hash << 2) ^ word[i];
    }
    printf("%s -> %lu\n", word, hash%N);
    return hash % N;
}

Вывод:

cat -> 1984
caterpillar -> 109622

MISSPELLED WORDS

a -> 97
A
cat -> 1984
is -> 471
is
not -> 1832
not
a -> 97
a
caterpillar -> 109622

WORDS MISSPELLED:     4
WORDS IN DICTIONARY:  2
WORDS IN TEXT:        6
TIME IN load:         0.00
TIME IN check:        0.00
TIME IN size:         0.00
TIME IN unload:       0.00
TIME IN TOTAL:        0.00

Слова в словаре - кошка и гусеница, слова в тексте - "Кошка не гусеница"

Функции:

// Implements a dictionary's functionality
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.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 = 200000;

// Hash table
node *table[N];

// Returns true if word is in dictionary else false
bool check(const char *word)
{
    // TODO
    int len = strlen(word);
    char *copy = malloc(sizeof(char) * len + 1);
    // change into lowercase the word
    for (int i = 0; i < len; i++)
    {
            copy[i] = tolower(word[i]);
    }
    // get the index by using the hash function
    int index = hash(copy);

    node *tmp = table[index];
    // check if the word is in the hash table
    while (tmp != NULL)
    {
        if (strcmp(tmp->word, copy) == 0)
        {
            free(copy);
            return true;
        }

        tmp = tmp->next;
    }

    free(copy);
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    /* credits to...
     *https://www.reddit.com/r/cs50/comments/1x6vc8/pset6_trie_vs_hashtable/
     */
    unsigned long hash = 0;
    int n  = strlen(word);

    for (int i = 0; i < n; i++)
    {
        hash = (hash << 2) ^ word[i];
    }
    return hash % N;
}

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    // TODO
    char *words = malloc(sizeof(char) * (LENGTH + 1));
    if (words == NULL)
    {
        return 1;
    }
    // initialize the hash table to NULL
    for (int i = 0; i < N; i++)
    {
        table[i] = NULL;
    }

    // open dictionary file
    FILE *indata = fopen(dictionary, "r");


    // 1 character for '\0' and another for '\n' because fgets takes a trailing new line
    // when it reads 'man' the value of words will be "man\n\0" so meaning 2 extra characters
    while (fgets(words, LENGTH + 2, indata) != NULL)
    {
        // get rid of the trailing new line from fgets
        words[strlen(words) - 1] = '\0';

        // allocate memory for the newNode
        node *newNode = malloc(sizeof(node));
        if (newNode == NULL)
        {
            return false;
        }

        // get the index by using the hash function
        int index = hash(words);

        strcpy(newNode->word, words);
        // make the newNode the head of the list
        newNode->next = table[index];
        table[index] = newNode;

    }

    // free memory and close the opened file
    free(words);
    fclose(indata);
    return true;
}

// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
    // TODO
    // counter of words loaded
    unsigned int counter = 0;
    // loop through the hash table
    for (int i = 0; i < N; i++)
    {
        node *tmp = table[i];

        while (tmp != NULL)
        {
            counter++;
            tmp = tmp->next;
        }
    }
    return counter;
}

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    // TODO
    // loop through the whole hash table
    for (int i = 0; i < N; i++)
    {
        while (table[i] != NULL)
        {
            node *tmp = table[i]->next;
            free(table[i]);
            table[i] = tmp;
        }
    }
    return true;
}

1 Ответ

0 голосов
/ 17 апреля 2020
// TODO
int len = strlen(word);
char *copy = malloc(sizeof(char) * len + 1);
// change into lowercase the word
for (int i = 0; i < len; i++)
{
        copy[i] = tolower(word[i]);
}
// get the index by using the hash function
int index = hash(copy);

Обратите внимание, что + 1 в malloc. Почему это там? Это должно позволить место для завершающего нулевого байта, который отмечает конец строки.

Скажите, что строка "test". Тогда strlen вернет 4. Ваш l oop будет перебирать от 0 до 3 включительно, копируя четыре буквы в слове.

Но вы не будете копировать завершающий нулевой байт в конце строки , Когда hash вызывает strlen на copy, кто знает, какое значение он получит, поскольку то, что вы передали, не является допустимой строкой.

Измените условие в for l oop до i <= len.

...