Reputation: 129
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
Reputation: 133849
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
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
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
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