Search code examples
ceofgetchar

Word count program - stdin


For below question,

Write a program to read English text to end-of-data (type control-D to indicate end of data at a terminal, see below for detecting it), and print a count of word lengths, i.e. the total number of words of length 1 which occurred, the number of length 2, and so on.

Define a word to be a sequence of alphabetic characters. You should allow for word lengths up to 25 letters.

Typical output should be like this:

        length 1 : 10 occurrences
        length 2 : 19 occurrences
  length 3 : 127 occurrences
     length 4 : 0 occurrences
        length 5 : 18 occurrences
        ....

To read characters to end of data see above question.


Here is my working solution,

#include<stdio.h>
int main(void){
  char ch;
  short wordCount[20] = {0};
  int count = 0;
  while(ch = getchar(), ch >= 0){
    if(ch == ' ' || ch == ',' || ch == ';'|| ch == ':'|| ch == '.'|| ch == '/'){
      wordCount[count]++;
      count=0;
    }else{
      count++;
    }
  }
  wordCount[count]++; // Incrementing here looks weird to me

  for(short i=1; i< sizeof(wordCount)/sizeof(short); i++){
    printf("\nlength %d : %d occurences",i, wordCount[i]);
  }
}

Question:

1)

From code elegance aspect, Can I avoid incrementing(++) wordCount outside while loop?

2)

Can I make wordCount array size more dynamic based on word size, rather than constant size 20?

Note: Learnt about struct but am yet to learn dynamic structures like Linkedlist


Solution

  • For the dynamic allocations you can start with space for 20 shorts (although the problem statement appears to ask for you to allow for words up to 25 characters):

    short maxWord = 20;
    short *wordCount = malloc(sizeof(*wordCount) * maxWord);
    

    Then, when you increment count you can allocate more space if the current word is longer than can be counted in your dynamic array:

    } else {
        count++;
        if (count >= maxWord) {
            maxWord++;
            wordCount = realloc(sizeof(*wordCount) * maxWord);
        }
    }
    

    Don't forget to free(wordCount) when you are done.

    Since you don't need to count zero-length words, you might consider modifying your code so that wordCount[0] stores the number of words of length 1, and so on.