Home > database >  Why does this code work but the other version does not?
Why does this code work but the other version does not?

Time:09-16

Specifically, the code is a solution to Exercise 1-9 in K&R C Programming Language 2nd Edition. I already solved it, but I have a question.

Write a program to copy its input to its output, replacing each string of one or more blanks by a single blank.

This code works and returns the desired output

int ch, last;

for (last = 0; (ch = getchar()) != EOF; last = ch)
    if (ch == ' ' && last == ' ')
        ;
    else
        putchar(ch);

This version of the code doesn't work and instead prints literally the same input with excess spaces included.

int ch, last;
last = 0;

while ((ch = getchar()) != EOF)
    if (ch == ' ' && last == ' ')
        ;
    else
        putchar(ch);
    
    last = ch;

Could somebody tell me the difference between these two versions of code and why the latter version doesn't work?

CodePudding user response:

last = ch; is not inside the loop, so you're not setting it until after you've read the entire file. So you're comparing with 0 every time.

If you want to have multiple statements in a loop, you have to put {} around them.

while ((ch = getchar()) != EOF) {
    if (ch == ' ' && last == ' ') {
    } else {
        putchar(ch);
    }
    last = ch;
}

This is a perfect example of Why is it considered a bad practice to omit curly braces?

CodePudding user response:

In the 2nd version you need place the body of the while loop in a {} as it consist of two statements (if and last= assignment). Otherwise only the first statement is executed in the loop, and the 2nd after the loop terminates.

int ch, last;
last = 0;

while ((ch = getchar()) != EOF) {
    if (ch == ' ' && last == ' ')
        ;
    else
        putchar(ch);
    
    last = ch;
}

I would invert the condition:

    if (ch != ' ' || last != ' ')
        putchar(ch);

CodePudding user response:

The answers about curly braces are correct.

There is, however, another way to transform the for() expression into a while() loop without an abundance of filigree in the code.

Below traversing a string stands in for getting characters from stdin.

#include <stdio.h>

int main() {
    char *str = " Once upon   a   time  in a land   far  away    ";

    int i = 0, ch, last = 0;
    while( (ch = str[i  ]) != '\0' )
        if ( ch != ' ' || last != ' ' )
            putchar( last = ch ); // NB: copy value

    return 0;
}

Output

" Once upon a time in a land far away " // quotes added to show SPs

(Shameless duplication of @Alan Wind's observation about boolean logic.)

  • Related