tommie997
tommie997

Reputation: 129

The C Programming Language, confusion when comparing solution of Exercise 1-9 to 1-12

As a programming novice I have been trying to teach myself C to better understand computers using The C Programming Language (2nd Edition).

This site has been very helpful so far in troubleshooting problems but there is one problem I can't get my head around. It is my proposed solution to exercise 1-12 using my solution to 1-9 as a backdrop. I was wondering if anyone in this online community would kindly point out where I'm going wrong.

Exercise 1-9 asks you to "Write a program to copy its input to its output, replacing each string of one of more blanks by a single blank"

There are many ways to skin the proverbial cat here but the solution that reads most simply to me is this:

int c;

while((c = getchar()) != EOF)
  {
   if(c == ' ')
     {
        putchar(' ');
        while((c = getchar()) == ' ') // if there are subsequent blanks
        ; // do nothing
     }

   if(c != EOF)
    putchar(c);
  }

Now Exercise 1-12 is asking you to "Write a program that prints its input one word per line."

My first attempt was successful but an oversimplification of the problem.

int c;

while((c = getchar()) != EOF)
{  if(c == ' ')
     putchar('\n');

else
  putchar(c);
}

So I've tried to rectify this to accept a much wider range of inputs and here is the result

int c;

while((c = getchar()) != EOF)
 {
    if(c == ' ' || c == '\t' || c == '\n')
     {
      putchar('\n');
      while((c = getchar()) == ' ' || (c = getchar()) == '\t' || (c = getchar()) == '\n')
      ;
     }

    if(c != EOF)
     putchar(c);
 }

Now I know this is wrong when I run it and I have looked up online other very simple ways to solve the problem.

My issue here is that I don't understand why it doesn't work. To me if the solution to 1-9 works I don't understand why it fails when I take the same principle to 1-12. Anyone who could point this out would be appreciated!

Upvotes: 2

Views: 239

Answers (4)

What you did was almost correct, but getchar() consumes one character of input on every invocation.

You could have written

while ((c = getchar()) == ' ' || c == '\t' || c == '\n')

because the || operator is processed left-to-right with so called sequence point in between;

though clearer is to move the initialization of c out of the loop condition.

Finally, using isspace this would consume any whitespace characters, with much less typing:

#include <ctype.h>

int c;
do {
   c = getchar();
} while (isspace(c));

Upvotes: 2

Lundin
Lundin

Reputation: 213306

It might be worth mentioning a sane and readable way to write this code without "assignment inside conditions", "most operators on a single line wins a price" or other such bad and dangerous habits picked up from that old book:

#include <stdio.h>
#include <ctype.h>

int main (void)
{
  while(1)
  {
    int c = getchar();
    if (isspace(c))
    {
      putchar('\n');       // at first space found, print line feed
      do
        c = getchar();
      while(isspace(c));   // discard any additional spaces
    }

    if(c == EOF)           // here c will not be a space, but possibly EOF
    {
      break;
    }

    putchar(c);
  }
  
  return 0;
}

Upvotes: 2

Antonin GAVREL
Antonin GAVREL

Reputation: 11219

If your char is not a space then you will try to get another char from the user instead of analyzing the one that was entered.

correct your while to call it only once:

while ((c = getchar()) == ' ' || c == '\t' || c == '\n')

Upvotes: 1

ilkkachu
ilkkachu

Reputation: 6517

while((c = getchar()) == ' ' || (c = getchar()) == '\t' || (c = getchar()) == '\n')
           ^                         ^                          ^

You're calling getchar() three times. Those calls read three characters, and you compare the first against space, second against \t and third against \n. (The calls are separated by ||, so there should be no issues with undefined sequencing.)

Instead, use temp variable:

int c;
do {
    c = getchar();
} while (c == ' ' || c == '\t' || c == '\n');

Using isspace() from ctype.h would probably be better too.

Upvotes: 2

Related Questions