I am working through Kernighan & Ritchie and have got to exercise 1.9. In fact I wrote some code which appears to solve the exercise, and I have tested it on Windows (with Git Bash and gcc) and Termux (with clang) by piping in a line with a variable number of spaces e.g. echo " one two three", and the expected output comes out i.e. one two three.
I got to the solution by trial and error, though it is the same as the solution provided by Lvictor on the clc wiki.
The code I wrote myself is:
#include <stdio.h>
/* Write a program to copy its input to its output, replacing each string of one or more blanks by a single blank. */
int main () {
int c;
while ((c = getchar()) != EOF) {
if (c == ' ') {
while ((c = getchar()) == ' ' ) {
}
putchar (' ');
}
putchar (c);
}
}
What I find perplexing is why I need the putchar (' '); line. I do not understand why the value of c is not ' ' after the program exits the if statement. Originally I did not have this line, but then the program removed all spaces from the input, to my surprise.
As I am a beginner C programmer, maybe there is something I don't understand about the scope of variable values, though it seems to me that if the value of c is ' ' when the if statement starts, and if it is ' ' in the second while loop, it should also be ' ' when both exit, but this does not appear to be the case.
I have Googled K&R exercise 1.9, which is how I found the wiki above, and looked at other quesions concerning this exercise on Stack Overflow.
The program enters the body of the
ifblock only in the event thatc == ' ', but inside that block, the innerwhileloop reads new values forc, one at a time, untilcis set to a value different from' '. Therefore, when control leaves that innerwhileloop,cis guaranteed to not contain a' '.You argue,
The problem with that logic is the "if it is ' ' in the second while loop". That's at best imprecise. What matters for this purpose is not the value of
cin the body of the loop (especially for your empty loop), but rather the value ofcafter the last time the loop's condition is evaluated -- which will be the first time that it evaluates to false.cis updated every time that expression is evaluated. This equivalent form for that loop would be clearer: