sean_rasku
sean_rasku

Reputation: 11

My function is being skipped over and I cannot tell why

I'm building a linked list that is only supposed to contain a single instance of a word and for some reason the first word I read in is being skipped over and the output cuts out the next word as I continue to build the linked list. For the first word it also skips over the checkforRepeat function. I can't tell what's wrong at this point, so any help would be greatly appreciated! Input to Function: list list word hello word contains end

EDIT

I figured out why my function wasn't being called, but now am having trouble figuring out why the memory is getting stamped on because when I plug the input it I get list,list,word,hello,contains,end instead of list,word,hello,contains,end.

typedef struct NODE{
    char* word;
    struct NODE* next;
    struct NODE* prev;
    struct NODE* first;
    struct NODE* last;
} node;

int checkforRepeat(node** first_node, char* wordtofind, int listsize){
    node* findrepeats = *first_node;
    if (findrepeats == NULL) {
        return 0;
    }
    printf("\n\nWord to find: %s\n\n", wordtofind);
    printList(*first_node);
    printf("\n");
    int i = 1;
    while (1) {
        if (findrepeats->next == NULL) {
            break;
        }
        else {
            printf(" %s, ", findrepeats->word);
            if (strcmp(wordtofind, findrepeats->word) == 0 ) {
                printf("|%s|, ", findrepeats->word);
                return 1;
            }
            else findrepeats = findrepeats->next;
        }
        i++;
    }
    return 0;
}


void addNode(char* newword, node** address_of_first_node, int* sizeoflist){
    
    if(*newword > 47 && *newword < 58){
        return;
    }
    node *added_node;
    node *head = *address_of_first_node;
    added_node = malloc(sizeof(node));
    printf("\n\nWord before function: %s\n\n", newword);
    
    if (checkforRepeat(address_of_first_node, newword, *sizeoflist) == 1) {
        return;
    }
    added_node->word = newword;
    added_node->next = NULL;
    
    if(head == NULL){
        *address_of_first_node = added_node;
        added_node->prev = NULL;
        added_node->first = *address_of_first_node;
        added_node->last = added_node;

    }
    else{
        node *last_node = head;
        while (1) {
            if (last_node->next == NULL) break;
            else {
                last_node->last = added_node;
                last_node = last_node->next;
            }
        }
        last_node->next = added_node;
        added_node->first = *address_of_first_node;
        added_node->prev = last_node;
        added_node->last = added_node;

    }
    *sizeoflist = *sizeoflist + 1;
    
}
void printList(node *data){
    while (1) {
        if (data->next == NULL) {
            printf("%s", data->word);
            break;
        }
        printf("%s,", data->word);
        data = data->next;
    }
}
int main(){
    node* list_of_nodes = NULL;
    char* deletednodes = malloc(20 * sizeof(char));
    int* sizeoflist = malloc(sizeof(int));
    *sizeoflist = 0;
    int j = 0;
    while (1) {
        char* wrd = malloc(20);
        if (scanf("%s", wrd) == EOF) break;
        addNode(wrd, &list_of_nodes, sizeoflist);
    }

    printList(list_of_nodes);

}

Upvotes: 1

Views: 65

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 754450

Here's code that works, with reasonably comprehensive debugging added. The primary change is removing the test if (i == listsize) in checkforRepeat(). There were knock-on effects as the list size was no longer needed, and the checkforRepeat() code doesn't need a pointer to pointer to a struct NODE; a simple pointer is sufficient.

Also, you have:

struct NODE{
    char* word;
    struct NODE* next;
    struct NODE* prev;
    struct NODE* first;
    struct NODE* last;
} typedef node;

Putting the keyword typedef after the structure definition is not technically wrong (yet), but it is using an obsolescent feature of C. C11 §6.11.5 Storage class specifiers: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. The keywords typedef, static, register, extern, auto, _Thread_local are storage class specifiers.

Code updated to check for memory allocation failures, and when a word is repeated, updated to avoid leaks of the word allocated in main() (though that free() is uncomfortably distant from the allocation) and avoiding leaking a node too. However, the code does not attempt to free the list at the end, even though doing so would not be hard.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct NODE
{
    char *word;
    struct NODE *next;
    struct NODE *prev;
    struct NODE *first;
    struct NODE *last;
} node;

static
int checkforRepeat(node *first_node, char *wordtofind)
{
    printf("-->> %s(): check for [%s]\n", __func__, wordtofind);
    node *findrepeats = first_node;
    if (findrepeats == NULL)
    {
        printf("<<-- %s(): empty list, word [%s] not found\n", __func__, wordtofind);
        return 0;
    }
    printf("Word to find: %s\n", wordtofind);
    while (findrepeats != NULL)
    {
        printf(" %s, ", findrepeats->word);
        if (strcmp(wordtofind, findrepeats->word) == 0)
        {
            printf("|%s|, ", findrepeats->word);
            printf("\n<<-- %s(): found word [%s], return 1\n", __func__, wordtofind);
            return 1;
        }
        findrepeats = findrepeats->next;
    }
    printf("\n<<-- %s(): did not find word [%s], return 0\n", __func__, wordtofind);
    return 0;
}

static
void addNode(char *newword, node **address_of_first_node)
{
    printf("-->> %s(): [%s]\n", __func__, newword);
    if (*newword > 47 && *newword < 58)
    {
        return;
    }
    printf("---- %s(): [%s]\n", __func__, newword);
    node *head = *address_of_first_node;
    printf("Word before function: %s\n", newword);

    if (checkforRepeat(head, newword) == 1)
    {
        printf("<<-- %s(): repeated word: %s\n", __func__, newword);
        return;
    }
    node *added_node = malloc(sizeof(node));
    if (added_node == NULL)
    {
        free(newword);
        fprintf(stderr, "failed to allocate memory for new node\n");
        exit(EXIT_FAILURE);
    }
    added_node->word = newword;
    added_node->next = NULL;

    if (head == NULL)
    {
        *address_of_first_node = added_node;
        added_node->prev = NULL;
        added_node->first = *address_of_first_node;
        added_node->last = added_node;
    }
    else
    {
        node *last_node = head;
        while (1)
        {
            if (last_node->next == NULL)
                break;
            else
            {
                last_node->last = added_node;
                //printf("%s.\n", last_node->last->word);
                last_node = last_node->next;
            }
        }
        last_node->next = added_node;
        added_node->first = *address_of_first_node;
        added_node->prev = last_node;
        added_node->last = added_node;
    }
    printf("<<-- %s(): added node for [%s]\n", __func__, newword);
}

static void printList(const char *tag, node *node)
{
    printf("%s:\n", tag);
    while (node != NULL)
    {
        printf("Word [%s]\n", node->word);
        node = node->next;
    }
}

int main(void)
{
    node *list_of_nodes = NULL;
    while (1)
    {
        char *wrd = malloc(20);
        if (wrd == NULL)
        {
            fprintf(stderr, "failed to allocate memory for new word\n");
            exit(EXIT_FAILURE);
        }
        if (scanf("%19s", wrd) == EOF)
            break;
        addNode(wrd, &list_of_nodes);
        printList("After adding word", list_of_nodes);
    }
    /* ...omitted... */
    return 0;
}

Sample output (source skip19.c, program skip19):

$ skip19 <<< 'hello world how are you doing world'
-->> addNode(): [hello]
---- addNode(): [hello]
Word before function: hello
-->> checkforRepeat(): check for [hello]
<<-- checkforRepeat(): empty list, word [hello] not found
<<-- addNode(): added node for [hello]
After adding word:
Word [hello]
-->> addNode(): [world]
---- addNode(): [world]
Word before function: world
-->> checkforRepeat(): check for [world]
Word to find: world
 hello, 
<<-- checkforRepeat(): did not find word [world], return 0
<<-- addNode(): added node for [world]
After adding word:
Word [hello]
Word [world]
-->> addNode(): [how]
---- addNode(): [how]
Word before function: how
-->> checkforRepeat(): check for [how]
Word to find: how
 hello,  world, 
<<-- checkforRepeat(): did not find word [how], return 0
<<-- addNode(): added node for [how]
After adding word:
Word [hello]
Word [world]
Word [how]
-->> addNode(): [are]
---- addNode(): [are]
Word before function: are
-->> checkforRepeat(): check for [are]
Word to find: are
 hello,  world,  how, 
<<-- checkforRepeat(): did not find word [are], return 0
<<-- addNode(): added node for [are]
After adding word:
Word [hello]
Word [world]
Word [how]
Word [are]
-->> addNode(): [you]
---- addNode(): [you]
Word before function: you
-->> checkforRepeat(): check for [you]
Word to find: you
 hello,  world,  how,  are, 
<<-- checkforRepeat(): did not find word [you], return 0
<<-- addNode(): added node for [you]
After adding word:
Word [hello]
Word [world]
Word [how]
Word [are]
Word [you]
-->> addNode(): [doing]
---- addNode(): [doing]
Word before function: doing
-->> checkforRepeat(): check for [doing]
Word to find: doing
 hello,  world,  how,  are,  you, 
<<-- checkforRepeat(): did not find word [doing], return 0
<<-- addNode(): added node for [doing]
After adding word:
Word [hello]
Word [world]
Word [how]
Word [are]
Word [you]
Word [doing]
-->> addNode(): [world]
---- addNode(): [world]
Word before function: world
-->> checkforRepeat(): check for [world]
Word to find: world
 hello,  world, |world|, 
<<-- checkforRepeat(): found word [world], return 1
<<-- addNode(): repeated word: world
After adding word:
Word [hello]
Word [world]
Word [how]
Word [are]
Word [you]
Word [doing]
$

Upvotes: 2

Related Questions