4

I'm trying to create a program that begins by parsing a number of strings and adding them into a Linked List, and then ending by printing out the occurrences of each string.

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef struct Node Node;

struct Node
{
    char* word;
    int count;
    struct Node *next;
};

Node *head = NULL;
Node *curr = NULL;

Node* listAdd(char* word, bool toEnd) {
    Node* tmp = head;
    while (tmp) {
        if (strcmp(tmp, word) == 0) {
            tmp->count++;
            return tmp;
        }
        tmp = tmp->next;
    }
    printf("allocate memory for node");
    Node *ptr = malloc(sizeof(Node));

    printf("initialize count to 0");
    ptr->count = 0;

    printf("allocate memory to hold word");
    ptr->word = malloc(strlen(word) + 1);

    printf("copy the current word");
    strcpy(ptr->word, word);

    ptr->next = NULL;

    if (toEnd)
    {
        curr->next = ptr;
        curr = ptr;
    }
    else
    {
        ptr->next = head;
        head = ptr;
    }
    return ptr;
}

void printList()
{
    Node *ptr = head;
    while (ptr)
    {
        printf("\nThe word [%s] has had [%d] occurrences.\n",ptr->word, ptr->count);
        ptr = ptr->next;
    }
}

char* readWord()
{
    static char buffer[100];
    scanf("%s", buffer);
    printf("listAdd() call");
    listAdd(buffer);
    return buffer;
}

int main(void)
{
    int i = 0;
    printf("How many words would you like to type?\n");
    scanf("%d", &i);
    for (i; i != 0; i--)
    {
        readWord();
    }
    printList();
}

Current output:

How many words would you like to input?
3
hi
bye
yes
How many words would you like to input?
Occurrences: 12086064

Any assistance would be greatly appreciated — I'm still a novice at C coming from C# :(

14
  • 1
    Suggest you persevere and debug this yourself rather than turning to SO straight away. In particular, fire up your favourite debugger, step through your program and check at each stage whether the code is operating as you expect. Or even a few trusty debug print statement will go a long way in helping you understand what your program is actually doing. Commented Oct 14, 2015 at 4:16
  • 1
    You don't use function searchList. count is not initialised.. Commented Oct 14, 2015 at 4:18
  • You also need to allocate space to hold the actual string in listAdd() e.g ptr->word = malloc(strlen(word) + 1); and then copy over the string strcpy(ptr->word, word); Commented Oct 14, 2015 at 4:24
  • @Cyclone Do I also need to allocate memory for the count too then? I think the searchList function was a pretty bad idea. I'm just going to increment the count in listAdd() instead. And I've tried debug print statements before posting here — none of them ever printed. Commented Oct 14, 2015 at 4:46
  • @Sleepless - Nope, but you need to allocate memory to store each word in your node (not just a pointer) or else they will all point to the last word entered since you they are getting overwritten each time readWord() is called. Commented Oct 14, 2015 at 4:49

2 Answers 2

8

Your code contains a couple of mistakes. First you are allocating your Node ptr twice:

Node* listAdd(char* word, bool toEnd) {
  // .. 

  Node *ptr = malloc(sizeof(Node));
  return ptr;
}

Remove the last one, right before the return statement.

You will also need to allocate memory to hold each read word. Right now you are overwriting the buffer each time you call readWord(). You would then do something like:

Node* listAdd(char* word, bool toEnd) {
  // allocate memory for node
  Node *ptr = malloc(sizeof(Node));
  // initialize count to 0
  ptr->count = 0;
  // allocate memory to hold word
  ptr->word = malloc(strlen(word) + 1);
  // copy the current word
  strcpy(ptr->word, word);

Your printList() function need look something like this:

void printList() {
  Node* ptr = head;
  while(ptr) {
    printf("Word: %s %d\n", ptr->word, ptr->count);
    ptr = ptr->next;
  }
}

Since you never check if the entered word already exists in your list each word will always be reported as having 1 occurance. This could be fixed like this:

// check if the word alreay exists in the list and then increment its count by 1
// this code should go at the top (before allocating ptr) in listAdd()
Node* tmp = head;
while(tmp) {
   if(strcmp(tmp->word, word) == 0) {
     tmp->count++;
     return tmp;
   }
   tmp = tmp->next;
}

Of course you should also free the allocated memory before exiting your application:

void freeList() {
  Node* ptr = head;
  Node* tmp = 0;
  while(ptr) {
    tmp = ptr->next;
    free(ptr->word);
    free(ptr);
    ptr = tmp;
  }
Sign up to request clarification or add additional context in comments.

6 Comments

I've updated OP to as you suggested but I'm still getting the same outcome. Is it because I'm not initializing count?
@Sleepless - Yes, that might be the problem. Look at the above code, I'm initializing count to 0.
Yeah I saw your edit and tried it on my machine first (and edited OP rather late!), yet still no luck. Also while we're on this note, should I initialize count to 0 in my if (head == NULL) block instead, and then proceed to increment it after the block?
@Sleepless - Changing the code as above works fine for me?
Thanks a lot for the assistance Cyclone — it's been a good learning experience!
|
1

You need to use malloc and strcpy to store words, and strcmp to compare them. What you're doing is saving repeated references to the buffer array that you're reading the words into.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.