JBo
JBo

Reputation: 89

Counting words in a word count program from filename

I seem to be able to get the lines, characters and spaces correctly. However, I'm having a hard time figuring out how to count words. They don't have to be in dictionary form; for example, fdasf fdjsak fea would be three words.

This is what I have:

#include <stdio.h>

int main(int argc, char* argv[]) {
  int ccount = 0;
  int wcount = 1;
  int lcount = 0;
  int scount = 0;

  char* filename = argv[1];
  printf("filename is: %s\n", filename);

  FILE* infile;
  infile = fopen(filename, "r");

  if (infile == NULL) {
    printf("%s: is not a valid file\n", filename);
    return -1;
  }

  char c;
  while ((c = fgetc(infile)) != EOF) {
    if (c == ' ') {
      wcount++;
    }
    if (c == '\n') {
      lcount++;
    }
    if (c != ' ' || c != '\n') {
      ccount++;
    }
    if (c == ' ') {
      scount ++;
    }
  }

  printf("total number of lines: %d\n", lcount);
  printf("total number of characters: %d \n", ccount);
  printf("total number of non-whitespace characters: %d \n", scount );
  printf("total number of words: %d \n", wcount);

  return 0;
}

Upvotes: 0

Views: 397

Answers (1)

David C. Rankin
David C. Rankin

Reputation: 84642

While there are a number of ways to do this, here is a short concise example that reads from stdin, you can simply change stdin to infile for your purposes (after opening infile). This does not count an empty-string ('\n' alone) as a word. You can rework this to fit your needs. It contains comments explaining the logic. Let me know if you have questions:

#include <stdio.h>

int main (void) {

    char *line = NULL;  /* pointer to use with getline ()  */
    char *p = NULL;     /* pointer to parse getline return */
    ssize_t read = 0;   /* actual chars read per-line      */
    size_t n = 0;       /* max chars to read (0 - no limit)*/
    int spaces = 0;     /* counter for spaces and newlines */
    int total = 0;      /* counter for total words read    */

    printf ("\nEnter a line of text (or ctrl+d to quit)\n");

    while (printf ("\n input: ") && (read = getline (&line, &n, stdin)) != -1) 
    {
        /* strip trailing '\n' or '\r' */
        while (line[read-1] == '\n' || line[read-1] == '\r')
            line[--read] = 0;

        spaces = 0;
        p = line;

        if (read > 0) {        /* read = 0 covers '\n' case (blank line with [enter])  */
            while (*p) {                            /* for each character in line      */
                if (*p == '\t' || *p == ' ') {      /* if space,       */
                    while (*p == '\t' || *p == ' ') /* read all spaces */
                        p++;
                    spaces += 1;                    /* consider sequence of spaces 1   */
                } else
                    p++;                            /* if not space, increment pointer */
            }
            total += spaces + 1;                    /* words per-line = spaces + 1     */
        }

        printf (" chars read: %2zd,  spaces: %2d,  words: %2d,  total: %3d   | '%s'\n",
                read, spaces, (spaces > 0) ? spaces+1 : 0, 
                total, (read > 1) ? line : "[enter]");
    }

    printf ("\n\n  Total words read: %d\n\n", total);

    return 0;

}

output:

$ ./bin/countwords

Enter a line of text (or ctrl+d to quit)

 input: my dog has fleas
 chars read: 16,  spaces:  3,  words:  4,  total:   4   | 'my dog has fleas'

 input:
 chars read:  0,  spaces:  0,  words:  0,  total:   4   | '[enter]'

 input: fee fi fo fum
 chars read: 13,  spaces:  3,  words:  4,  total:   8   | 'fee fi fo fum'

 input:

  Total words read: 8

Note: to expand the whitespace characters recognized, you can include the ctype.h header and make use of the isspace() function instead of simply checking for spaces and tabs as is done above. The omission is by intent to limit the required header files to stdio.h.

Upvotes: 1

Related Questions