Exercise 1-12

Write a program that prints its input one word per line.

At first glance, the solution seems simple: copy all the non-blank characters and print a newline in place of any whitespace characters we come across.

    #include <stdio.h>
    
    main()
    {
        int c;
    
        while ((c = getchar()) != EOF) {
            if (c == ' ' || c == '\n' || c == '\t')
                putchar('\n');
            else
                putchar(c);
        }
    }

This works, for the most part. However, when the program comes across input like hello,   world, with a sequence of blanks, it outputs the following:

    hello,
    
    
    world

This makes sense since we are simply replacing the sequence of blanks with a sequence of newlines, but we do not want this behavior.

In order to solve this issue, we can reuse the idea of creating a state variable from the word count program for keeping track of whether we are "in" a word or not. We assign the symbolic constant OUT to state when we come across whitespace, and the symbolic constant IN when we read in a non-whitespace character. Now, instead of replacing every whitespace character with a newline, we can only replace whitespace when state is IN; any subsequent whitespace will get skipped.

    #include <stdio.h>
    
    #define IN 1    /* inside a word */
    #define OUT 0   /* outside a word */
    
    main()
    {
        int c, state;
    
        state = OUT;
        while ((c = getchar()) != EOF) {
            if ((c == ' ' || c == '\n' || c == '\t') && state == IN) {
                putchar('\n');
                state = OUT;
            } else {
                putchar(c);
                state = IN;
            }
        }
    }

Note: the condition (c == ' ' || c == '\n' || c == '\t') is wrapped in parantheses because && has a higher precedence than ||.