0

I've been having quite a few issues with Pset5 and I can't figure anything out. I've been playing around with the placement of 'char word[LENGTH+1]' but I always get an error: "use of undeclared identifier 'word'", no matter what I do. I've tried omitting the code but that doesn't work either. What am I missing? And are there any other obvious errors to my code that I need to fix? Explanations for why something works would be greatly appreciated!

bool check(const char *word)
{
node *trav = root;
char newword[LENGTH+1];

for (int j = 0; j < strlen(word); j++){
    newword[j] = tolower(word[j]);
}
    for (int i = 0; i < strlen(word); i++){
        if (isalpha(word[i])){
            //if node does not exist
            if (trav->children[newword[i] - 'a'] == NULL){
                misspelled_words++;
                printf("Misspelled");
                return false;
            }
            //if node does exist
            else{
                trav = trav->children[newword[i]-'a'];
            }
        }
        //if letter is an apostrophe
        else if (word[i] == 26){
            if (trav->children[26] == NULL){
                misspelled_words++;
                printf("Misspelled");
                return false;
            }
            //if node does exist
            else{
                trav = trav->children[26];
            }
        }
        printf("Number of misspelled words = %i ", misspelled_words);
        printf("Bool = %d ",trav->is_word);
        return trav->is_word;
    }
    printf("Didn't work");
    return false;
  }

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

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

//make sure dictionary opens
if (dict== NULL)
{
    fprintf(stderr, "Could not open %s.\n", dictionary);
    return false;
}
fprintf(stderr, "%s opened\n", dictionary);

char word[LENGTH + 1];
root = calloc(1,sizeof(node));

 //read file until end
while (fscanf(dict, "%s", word) != EOF){
    //point temporary curser at root
    node *trav = root;
    //scanning each letter in word
    for (int i = 0; i < strlen(word); i++){
        char letter = word[i];
        char lowletter = tolower(letter);
        //if letter is in alphabet
        if (isalpha(letter)){
        //checking to see if node exists
            if (trav->children[lowletter - 'a'] == NULL){
                //if doesn't exist
                //allocating memory for node
                trav->children[lowletter - 'a'] = (node*) 
calloc(1,sizeof(node));
                trav = trav->children[lowletter - 'a'];
            }
            else {
                //points curser to node
                trav = trav->children[lowletter - 'a'];
            }
        }
        //else if apostrophe
        //checking to see if node exists
        else if (trav->children[26] == NULL){
            //if doesn't exist
            //allocating memory for node
            trav->children[26] = (node*) calloc(1,sizeof(node));
            trav = trav->children[26];
        }
        else{
            //points curser to node
            trav = trav->children[26];
        }
        //moving trav back to root
        trav = root;
    }

    //setting bool to true to signify end of word
    trav->is_word = true;
    printf(" %s ", word);
    printf("%d",trav->is_word);
    word_count ++;
}
printf(" word_count = %i\n", word_count);
fclose(dict);
return true;
}

EDIT: I updated my code. I think I just have logistical errors now. Check returns is_word as false after every word.

1
  • There shouldn't be a problem with this unless you're placing it in the wrong place or missing the semicolon. Can you please edit your question and show or explain in detail what you're trying to do and exactly where you're placing that line of code? – Cliff B Jan 4 '19 at 20:21
1

You use word in load without definition. The char word[LENGTH + 1]; should go somewhere inside load, but before it is used in the fscanf. Could be inside the loop or before, doesn't matter as you use a particular value only through a single iteration.

A global variable word would work, but then you have check with a parameter of the same name (which is about same as a local variable with an externally initialised value), which means within that function, word can never mean the global variable (the parameter in the inner scope "shadowing" the global variable), which can lead to some confusion, so never do that. You don't need that variable to transfer information between function calls anyway (only global variables needed are your data structure, or at least some root pointer, and maybe the number of words, which is exactly what the code shown has).

//root points to base children nodes
for (int i = 0; i < 27; i ++){
    root->children[i] = NULL;
}

This makes no sense, in multiple ways. First, there shouldn't be loops outside the functions. Then, you just set root to NULL, and now you want to access the members of the structure it is pointing to. Remember Binky? You need to allocate some root node first. BTW, global variables are always initialised, to all zeroes by default (which might represent 0, '\0', NULL, false, depending on data type), similar to what calloc does.

strcmp is meant for strings, will read until it finds a difference or a null terminator, you are comparing characters, so this might read content behind the variables. char is a kind of integer, so you can use all the comparison operators like <, <=, >, >=, ==, !=.

What's the ASCII value of lower-case characters and the apostrophe? Looks like you got that in load, but not in check.

In load, you always need to do the trav = trav->children[index], whether trav->children[index] existed previously or not. It's more like "We want to walk in that direction (always!), but we might need to build a path first (depends on existing paths)".

I don't think '\n' ever appears in the strings. But the word is finished when you reach the end of the inner loop. Same in check, just place the final return after your loop, no if needed.

8
  • This was so useful! I was able to take 20+ errors all the way down to 1. The last issue of my code is that I now have a segmentation fault with 'if (trav->children[lowletter - 'a'] == NULL){ //if doesn't exist //allocating memory for node trav->children[lowletter - 'a'] = (node*) calloc(1,sizeof(node)); trav = trav->children[lowletter - 'a']; }' I've looked at similar problems but I can't figure out what exactly I need to do. – Tenacity Jan 8 '19 at 19:57
  • This would crash if either trav is pointing to an invalid node (might be uninitialised, NULL, or you freed the node it is pointing to), or you use an index that's out of bounds. Do you calloc a root node? – Blauelf Jan 9 '19 at 10:11
  • In load I used calloc for root and that solved the issue. Now it seems like I have logistical issues to work out. My code loads the last word of the dictionary twice and then doesn't count any word as misspelled. Is my code not recognizing when the dictionary ends and is reloading the last word? Thanks! – Tenacity Jan 16 '19 at 20:54
  • I just went through and tried to debug it myself by printing how many words were loaded with a small dictionary of 8. My code was actually loading 40 words. Whenever I print the words in check they sometimes come back with weird characters in addition to the letters that spell them. Is there just something very wrong with my code? – Tenacity Jan 16 '19 at 21:16
  • Last word twice sounds like an issue with not understanding feof. You could move the fscanf into your loop condtion, like while (fscanf(...) != EOF), removing any mention of feof. Having each word multiple times would be due to the trav->is_word = true; etc. code being in the inner loop, but belong into the outer loop, after the inner loop. – Blauelf Jan 17 '19 at 9:10

You must log in to answer this question.

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