Alex
Alex

Reputation: 2076

Counting words occurrence in a string

I'm trying to count words occurrence in a string. For a string S, I need to show each word and how many times this word is present in the string.

Exemple:

string = ";! one two, tree foor one two !:;"

Result:

one: 2
two: 2
tree: 1
foor: 1

Here is my code but it's not returning the right count:

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

int count_word(char * mot, char * text) {
  int n = 0;
  char *p;

  p = strstr(text, mot);

  while (p != NULL) {
    n++;
    p = strstr(p + 1, mot);
  }  

  return n;
}

void show_all_words(char * text) {
    char * p = strtok(text, " .,;-!?");

    while (p != NULL) {
      printf ("%s : %d\n", p, count_word(p, text));
      p = strtok(NULL, " .,;-!?");
    }
}

int main(char *argv[]) {

    char text[] = ";! one two, tree foor one two !:;";
    show_all_words(&text);

    return (EXIT_SUCCESS);
};

it's returning:

one : 1
two : 0
tree : 0
foor : 0
one : 1
two : 0
: : 0

Upvotes: 3

Views: 5682

Answers (2)

anatolyg
anatolyg

Reputation: 28310

The function strtok changes its parameter. You can fix the problem by duplicating the string, calling strtok on one copy and count_word on the other.

Also, take a precaution not to output the count for the same word twice.

int count_word(char * mot, char * text, int offset) {
  int n = 0;
  char *p;

  p = strstr(text, mot);
  assert(p != NULL);
  if (p - text < offset)
      return -1; // if the word was found at an earlier offset, return an error code 

  while (p != NULL) {
    n++;
    p = strstr(p + 1, mot);
  }  

  return n;
}

void show_all_words(char * text) {
    char *text_rw = strdup(text); // make a read-write copy to use with strtok
    char * p = strtok(text_rw, " .,;-!?");

    while (p != NULL) {
      int offset = p - text; // offset of the word inside input text
      int count = count_word(p, text, offset);
      if (count != -1) // -1 is an error code that says "already looked at that word"
          printf ("%s : %d\n", p, count );
      p = strtok(NULL, " .,;-!?");
    }
    free(text_rw); // delete the copy
}

Upvotes: 3

Adrian Herea
Adrian Herea

Reputation: 658

You should change the approach. You could use an array to store the index of first appearance of each word and the count of appearance. Only one travel in string but more travels in auxiliary array to check if the current word was already counted.

I hope is useful for you.

Upvotes: 1

Related Questions