Reputation: 11
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
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