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.)