3
\$\begingroup\$

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;
}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ @greybeard I'll add that in now! Thank you. \$\endgroup\$
    – 0ffset
    May 4, 2020 at 14:58
  • \$\begingroup\$ Welcome to CodeReview@SE. \$\endgroup\$
    – greybeard
    May 4, 2020 at 15:38

2 Answers 2

2
\$\begingroup\$

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.

\$\endgroup\$
3
\$\begingroup\$

A few points to consider.

  1. C99 added an actual Boolean type, named _Bool, with constants name _True and _False. By including <stdboolh.h>, you get aliases for those spelled bool, true and false. So unless you need to continue using C89, you might consider using these instead of defining your own names and such.

  2. 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's false, I'd prefer to use if (!previous_space).

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

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.