0

i have a problem with declaring root. first I wrote a trie struct in dictionary.h and declared a root nodenode* root = NULL;. and then i allocated memory for root in mainroot = calloc(1,sizeof(node));. something wrong happened when i run make make speller
I haven't written any function yet, I just included some additional libraries in dictionary.h

speller.c

/****************************************************************************
 * speller.c
 *
 * Computer Science 50
 * Problem Set 5
 *
 * Implements a spell-checker.
 ***************************************************************************/

#include <ctype.h>
#include <stdio.h>
#include <sys/resource.h>
#include <sys/time.h>

#include "dictionary.h"
#undef calculate
#undef getrusage

// default dictionary
#define DICTIONARY "/home/cs50/pset5/dictionaries/large"

// prototype
double calculate(const struct rusage* b, const struct rusage* a);

int main(int argc, char* argv[])
{
    root = calloc(1,sizeof(node));
    // check for correct number of args
    if (argc != 2 && argc != 3)
    {
        printf("Usage: speller [dictionary] text\n");
        return 1;
    }

    // structs for timing data
    struct rusage before, after;

    // benchmarks
    double time_load = 0.0, time_check = 0.0, time_size = 0.0, time_unload = 0.0;

    // determine dictionary to use
    char* dictionary = (argc == 3) ? argv[1] : DICTIONARY;

    // load dictionary
    getrusage(RUSAGE_SELF, &before);
    bool loaded = load(dictionary);
    getrusage(RUSAGE_SELF, &after);

    // abort if dictionary not loaded
    if (!loaded)
    {
        printf("Could not load %s.\n", dictionary);
        return 1;
    }

    // calculate time to load dictionary
    time_load = calculate(&before, &after);

    // try to open text
    char* text = (argc == 3) ? argv[2] : argv[1];
    FILE* fp = fopen(text, "r");
    if (fp == NULL)
    {
        printf("Could not open %s.\n", text);
        unload();
        return 1;
    }

    // prepare to report misspellings
    printf("\nMISSPELLED WORDS\n\n");

    // prepare to spell-check
    int index = 0, misspellings = 0, words = 0;
    char word[LENGTH+1];

    // spell-check each word in text
    for (int c = fgetc(fp); c != EOF; c = fgetc(fp))
    {
        // allow only alphabetical characters and apostrophes
        if (isalpha(c) || (c == '\'' && index > 0))
        {
            // append character to word
            word[index] = c;
            index++;

            // ignore alphabetical strings too long to be words
            if (index > LENGTH)
            {
                // consume remainder of alphabetical string
                while ((c = fgetc(fp)) != EOF && isalpha(c));

                // prepare for new word
                index = 0;
            }
        }

        // ignore words with numbers (like MS Word can)
        else if (isdigit(c))
        {
            // consume remainder of alphanumeric string
            while ((c = fgetc(fp)) != EOF && isalnum(c));

            // prepare for new word
            index = 0;
        }

        // we must have found a whole word
        else if (index > 0)
        {
            // terminate current word
            word[index] = '\0';

            // update counter
            words++;

            // check word's spelling
            getrusage(RUSAGE_SELF, &before);
            bool misspelled = !check(word);
            getrusage(RUSAGE_SELF, &after);

            // update benchmark
            time_check += calculate(&before, &after);

            // print word if misspelled
            if (misspelled)
            {
                printf("%s\n", word);
                misspellings++;
            }

            // prepare for next word
            index = 0;
        }
    }

    // check whether there was an error
    if (ferror(fp))
    {
        fclose(fp);
        printf("Error reading %s.\n", text);
        unload();
        return 1;
    }

    // close text
    fclose(fp);

    // determine dictionary's size
    getrusage(RUSAGE_SELF, &before);
    unsigned int n = size();
    getrusage(RUSAGE_SELF, &after);

    // calculate time to determine dictionary's size
    time_size = calculate(&before, &after);

    // unload dictionary
    getrusage(RUSAGE_SELF, &before);
    bool unloaded = unload();
    getrusage(RUSAGE_SELF, &after);

    // abort if dictionary not unloaded
    if (!unloaded)
    {
        printf("Could not unload %s.\n", dictionary);
        return 1;
    }

    // calculate time to unload dictionary
    time_unload = calculate(&before, &after);

    // report benchmarks
    printf("\nWORDS MISSPELLED:     %d\n", misspellings);
    printf("WORDS IN DICTIONARY:  %d\n", n);
    printf("WORDS IN TEXT:        %d\n", words);
    printf("TIME IN load:         %.2f\n", time_load);
    printf("TIME IN check:        %.2f\n", time_check);
    printf("TIME IN size:         %.2f\n", time_size);
    printf("TIME IN unload:       %.2f\n", time_unload);
    printf("TIME IN TOTAL:        %.2f\n\n",
     time_load + time_check + time_size + time_unload);

    // that's all folks
    return 0;
}

/**
 * Returns number of seconds between b and a.
 */
double calculate(const struct rusage* b, const struct rusage* a)
{
    if (b == NULL || a == NULL)
    {
        return 0.0;
    }
    else
    {
        return ((((a->ru_utime.tv_sec * 1000000 + a->ru_utime.tv_usec) -
                 (b->ru_utime.tv_sec * 1000000 + b->ru_utime.tv_usec)) +
                ((a->ru_stime.tv_sec * 1000000 + a->ru_stime.tv_usec) -
                 (b->ru_stime.tv_sec * 1000000 + b->ru_stime.tv_usec)))
                / 1000000.0);
    }
}

dictionary.h

/****************************************************************************
 * dictionary.h
 *
 * Computer Science 50
 * Problem Set 5
 *
 * Declares a dictionary's functionality.
 ***************************************************************************/

#ifndef DICTIONARY_H
#define DICTIONARY_H
# include<ctype.h>
# include<stdio.h>
# include <stdlib.h>
#include <stdbool.h>

// maximum length for a word
// (e.g., pneumonoultramicroscopicsilicovolcanoconiosis)
#define LENGTH 45
typedef struct node
{
    bool is_word;
    struct node* children[27];

}
node;
node* root = NULL;
/**
 * Returns true if word is in dictionary else false.
 */
bool check(const char* word);

/**
 * Loads dictionary into memory.  Returns true if successful else false.
 */
bool load(const char* dictionary);

/**
 * Returns number of words in dictionary if loaded else 0 if not yet loaded.
 */
unsigned int size(void);

/**
 * Unloads dictionary from memory.  Returns true if successful else false.
 */
bool unload(void);

#endif // DICTIONARY_H

dictionary.c

/****************************************************************************
 * dictionary.c
 *
 * Computer Science 50
 * Problem Set 5
 *
 * Implements a dictionary's functionality.
 ***************************************************************************/

#include <stdbool.h>

#include "dictionary.h"

/**
 * Returns true if word is in dictionary else false.
 */
bool check(const char* word)
{
    // TODO
    return false;
}

/**
 * Loads dictionary into memory.  Returns true if successful else false.
 */
bool load(const char* dictionary)
{

    return false;
}

/**
 * Returns number of words in dictionary if loaded else 0 if not yet loaded.
 */
unsigned int size(void)
{
    // TODO
    return 0;
}

/**
 * Unloads dictionary from memory.  Returns true if successful else false.
 */
bool unload(void)
{
    // TODO
    return false;
}
4
  • Post your dictionary.c file. There is a declaration of node in line 22.
    – ChrisG
    Commented Sep 13, 2015 at 18:33
  • i edited my question and posted the link of dictionary.c. i really didn't define root again in dictionary.c.
    – kawegan
    Commented Sep 13, 2015 at 19:12
  • It looks like you loaded the bare skeleton of dictionary.c that downloads with the pset instead of your actual code. Can you update?
    – Cliff B
    Commented Sep 13, 2015 at 20:13
  • i haven't done anything in dictionary.c. i haven't written any function yet.
    – kawegan
    Commented Sep 13, 2015 at 20:24

2 Answers 2

1

This is the one pset that demonstrates where a global variable is appropriate. There are some rules that you have to remember about globals though.

If you want something to be a global variable, it must be declared OUTSIDE of main or any function call, and before it is used inside any of them.

If you declare a variable inside of a function or main with the same name, it will create a local variable and will be used inside that local code instead of the global. This usually causes problems because programmers don't realize which they are using, and generally, no error will be shown by the compiler. It believes you know what you're doing.

If you declare a var inside a function or main, and then declare it again, it will throw a compiler error. The exception to this is if the second declaration is inside a sub-block of code, in other words, inside a new set of curly braces that will define its scope. In this case, the inner local variable will supersede the outer local variable, the same way that a local will supersede a global, described earlier. This, like the previous example, is called declaring a shadow variable. Sometimes, the compiler will warn about this, but not always (depending on compiler flags).

If you have any statement along the lines of node* root =... that is a declaration. If you want to use the previously declared variable root, it cannot be preceded with a variable type, such as node *. That would make it a declaration with an initialization instead of an assignment statement.

Finally, unless you want to override your global var with a local var, you can only declare it once across all of the files in the project. In terms of this pset, that includes speller.c (which should not be changed at all or it will fail check50), dictionary.c and dictionary.h. Any additional declarations will be seen as either an error or a local var that supercedes the global var inside of the local scope.

I'd bet that I've covered the problem that you're having, but would have to see actual code if I haven't. So, armed with this info, you need to review your code.

If this answers your question, please click the check mark to accept this and remove the question from the unanswered pool. Let's keep up on forum maintenance. ;-)

0

Why are you defining "root" in speller.c?

First, the specs clearly say that we're not supposed to alter speller.c at all.

Second, the compiler is correct. You're defining root in your main function, and probably also in your line 22 of dictionary.c.

2
  • even if i define root in the load function.i get the same error. i edited the question and posted dictionary.c. i didn't define root again in dictionary.c.that's really weird
    – kawegan
    Commented Sep 13, 2015 at 19:10
  • 1
    You're also defining your root in the .h file (i hadn't noticed that before. Sorry about that). You shouldn't do that. So, please remove the assignment of your root variable to NULL inside the header file. The linker sees the two definitions, and which one should it use?
    – Irene
    Commented Sep 13, 2015 at 21:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .