I'm currently trying to learn C from the K&R book, reading through and attempting the exercises. I came across exercise 1-12 yesterday and was a little stumped but managed to complete it. I was wondering if someone on here would help me improve it, and also guide me on how to approach testing something like this too.
The exercise is to write a program which "prints input one word per line".
#include <stdio.h>
#define TRUE 1
#define FALSE 0
int main(){
int c, previous_space;
previous_space = FALSE;
while ( (c = getchar()) != EOF ){
if ( c == ' ' || c == '\n' || c == '\t' ){
if ( previous_space == FALSE ){
putchar('\n');
}
previous_space = TRUE;
}
else{
putchar(c);
previous_space = FALSE;
}
}
return 0;
}
-
1\$\begingroup\$ @greybeard I'll add that in now! Thank you. \$\endgroup\$0ffset– 0ffset2020年05月04日 14:58:44 +00:00Commented May 4, 2020 at 14:58
-
\$\begingroup\$ Welcome to CodeReview@SE. \$\endgroup\$greybeard– greybeard2020年05月04日 15:38:09 +00:00Commented May 4, 2020 at 15:38
2 Answers 2
Algorithmic flaw: Input begins with space
Input that begins with ' '
prints a new-line. No point in that.
// int previous_space;
// previous_space = FALSE;
int previous_space = TRUE;
Or better with bool
bool previous_space = true;
Input might not end with a '\n'
A line in C:
each line consisting of zero or more characters plus a terminating new-line character. Whether the last line requires a terminating new-line character is implementation-defined
If code wants to handle the case where input does not end with white-space before the EOF
, post-loop code is needed.
Other white-spaces
Aside from OP's 3 listed, there are other white-space characters (carriage return, form-feed, vertical tab, ...), all discernible with isspace()
.
(See similar idea in @Jerry Coffin)
int c
Good use of an int
instead of char
to save the return value from gethar()
. Avoided that rookie mistake.
Alternative
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
int main(void) {
bool previous_space = true;
int c;
while ((c = getchar()) != EOF) {
if (isspace(c)) {
if (!previous_space) {
putchar('\n');
}
previous_space = true;
} else {
putchar(c);
previous_space = false;
}
}
if (!previous_space) {
putchar('\n');
}
return 0;
}
Conceptual simplification
Use the inverse flag like bool need_line_feed = false;
to reduce !
use in the if()
s.
A few points to consider.
C99 added an actual Boolean type, named
_Bool
, with constants name_True
and_False
. By including<stdboolh.h>
, you get aliases for those spelledbool
,true
andfalse
. So unless you need to continue using C89, you might consider using these instead of defining your own names and such.When you have a value that's conceptually Boolean in nature (e.g., your
previous_space
) I'd treat it as a Boolean, so to test if it'sfalse
, I'd prefer to useif (!previous_space)
.Rather than explicitly checking for every possible white-space character in-line, I'd prefer to move that check into a separately little function of its own. Only this is such a common requirement that the standard library already provides
isspace
, so (at least in real code) it's generally preferred to#include <ctype.h>
, and us that (but the book probably hasn't introduced this yet, so I wouldn't worry about it a whole lot just yet).