airismything
airismything

Reputation: 57

I don't understand how how this code works

I'm doing Exercise 1-9 in the K&R Book, while trying to find solutions I came across this code:

int main()
{
    int c;
    while ((c = getchar()) != EOF) {
        if (c == ' ') {
            while ((c = getchar()) == ' ');
            putchar(' ');
            if (c == EOF) break;
        }
        putchar(c);
    }
}

Why does the first if statement work if even if I input a letter. From my understanding it will only execute if the character I input is a blank space? Btw the exercise is making a program replace multiple consecutive blank spaces to a single one.

Upvotes: 1

Views: 179

Answers (4)

Luis Colorado
Luis Colorado

Reputation: 12645

int main()
{
    int c;
    while ((c = getchar()) != EOF) {

For each character of input...

        if (c == ' ') {

...if the character is a space...

            while ((c = getchar()) == ' ');

... this loop skips all spaces that come after the first... See the semicolon in the right, that makes it read the character, check that it is a space, and does nothing with it. It is a very tricky thing to write it as such, as it is quite common to think that the loop body will be the next statement below, while it has no body at all. After a while loop, you can assume that the condition that let you enter the loop is false, so we have some true assertion: in c there's for sure no space stored (it can still be EOF, which is not a character, so we need to test for it before printing, and we do it next, after the next statement)

            putchar(' ');

... after the loop, only a single space is output, corresponding to the one tested in the first if statement you mentioned in your question. Think that c is not a space character (so we cannot putchar(c);), as we skip all spaces until none remained. Still it can be an EOF indicator, that is checked below.

            if (c == EOF) break;

if the character was not a space, it could only be an EOF indicator. In that case, we need to get out of the loop so we don't print it, in the next statement...

        }
        putchar(c);

... as we have been reading characters in c until we got a non space (nor an EOF indicator, as we got out of the loop above in that case) we need to print that char anyway. This putchar(c); statement will always print a non-space character. It is out of the if statement, as it must be done for all the characters that were initially nonspaces and the characters that followed a sequence of spaces.

    }

...As above, we can assume the test condition of the loop is false, so here we can ensure that c has got EOF (but only because the break statement inside the loop also happens when c == EOF).

}

Et voila!!!

Note

while trying to find solutions I came across this code:

A final note, it is better for you if you post your attempt at programming a solution, instead of finding already made solutions by searching. You'll learn more on programming and less on googling, which IMHO is not your primary interest.

Upvotes: 0

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186668

I've formatted out and comented the code. Hope that'll help. The code actually covert all sequence of spaces within stdin into one space:

 "123    456 a  b c  " -> "123 456 a b c "

Code:


int main() {
    int c;
 
    /* we read stdin character after character */
    while ((c = getchar()) != EOF) {
        /* if we have read space */   
        if (c == ' ') {
            /* we skip ALL spaces */
            while ((c = getchar()) == ' ')
                ; /* skipping ALL spaces: we do nothing */

            /* and then we print just ONE space instead of many skipped */
            putchar(' ');

            /* if we at the end of stdin, we have nothing more to print */
            if (c == EOF) 
                break;
        }

        /* we print every non space character */
        putchar(c);
    }
}

Upvotes: 1

Vlad from Moscow
Vlad from Moscow

Reputation: 310920

This program prints any entered character except the blank character ' ' until the user will interrupt the input.

In this while loop

while ((c = getchar()) == ' ');

each blank character is read but not outputted. And after the loop only one blank character is outputted

putchar(' ');

That is the program removes adjacent blank characters leaving only one blank character in the input sequence of characters entered by the user.

Upvotes: 4

Marcus Ilgner
Marcus Ilgner

Reputation: 7211

It loops as long as the input stream doesn't end (EOF = End Of File).

If the entered character is a space, it will ignore any follow-up spaces and only print one space afterwards.

Otherwise it will output the entered character.

Upvotes: 0

Related Questions