Jan Krejcar
Jan Krejcar

Reputation: 35

Why doesn't this eliminate double spaces in C? It's one of the getchar() exercises in K & R

This is a K&R exercise. It's supposed to substitute a single space for double or more. Instead it exactly mirrors input, spaces and all. Also, why do I have to use EOF (ctrl-d) in other exercises and RETURN (Enter) for this one? (I'm running it on Ubuntu but using ssh from a mac.)

 #include <stdio.h>

 main()
 {

   int c;

   c = getchar();

   while (c != EOF)
     {
       while (c != EOF | c != ' ')
         {
           putchar(c);
           c = getchar();
         }
       putchar(c);
       c = getchar();
         while (c == ' ' | c != EOF)
           c = getchar();
     }

Upvotes: 0

Views: 257

Answers (4)

Engineer
Engineer

Reputation: 914

That's a lot of gets and puts, and checking of values. Here's something cleaner that also takes care of tabs.

void main (void)
{
int F_space=F_tab=0;    // Flags for special chars
char ch;
do
    {
    ch = getchar();

    // test for special characters
    switch (ch)
        {
        case ' ':   // space
            F_space = 1;
            continue;

        case '\t':  // tab
            F_tab = 1;
            continue;

        default:    // anything else
            // output a space if necessary
            if (F_space || F_tab) {
                F_space = F_tab = 0;    // clear flags
                putchar (' ');
            }
            break;
        }

    // output the character
    putchar (ch);
    break;
    } 
while (ch != EOF);

Upvotes: 0

mjv
mjv

Reputation: 75305

The snippet shown has [at least] one logical error and an other error caused by the confusion between the logical boolean operators and bitwise boolean operators.

Logic error:

Your second test on c != EOF is OR-ed with the test on character not being a space (c != ' ')... Since you get to this OR-ed test when c is not EOF (this being the control condition of the while), the OR-ed test is always true!

   ...
   while (c != EOF)
     {
       // This test always true regardless of c being a space or not
       // Also it should be a logical OR, if at all.  The bitwise OR will produce
       // odd results if you are not sure of the bit patterns of the operands.
       while (c != EOF | c != ' ')  
         {
           putchar(c);
           c = getchar();
         }
     ...

Confusion of operator error: In this instance, you need to use the logical OR (or indeed the logical AND) operators, i.e. || and && respectively rather than the bitwise boolean operators (| and &).

You'll generally find that in C you use the logical operators quite frequently to express boolean conditions, whereby you only need the bitwise operators when you effectively need to mess with bit patterns of variables (e.g. to mask some bits or to force them to be set etc.)

Now, the above was addressing issues in the code "as is", merely explaining why the spaces were handled just like other characters... With regard to the K&R exercise's goal: that of substituting sequence of several spaces with just one space, the logic shown is positively wrong. I'd rather not give it away here, but a few hints:

  • introduce a "state" variable which indicates whether the previous character was a space
  • use a single while loop (while not EOF or whatever end condition you wish)
  • within the loop systematically output the character read, unless the state var is set
  • after conditionally outputting the current character, update the state character.

As a general hint, it is often (but not always) a "code smell" (i.e. an indication that the code/logic should be reworked) when you need to repeat end-of-loop condition(s) within a loop and/or introduce multiple spots where you read from some input (here multiple getchar())

Upvotes: 3

uba
uba

Reputation: 2031

Try this loop:

   while (c != EOF)
     {
       if (c == ' ')
         {
           putchar(c);
           while(c == ' ' && c != EOF)
             c = getchar();
         }
       else
         {
           if (c != EOF)
             putchar(c);
           c = getchar();
         }
     }

Upvotes: 1

Heath Hunnicutt
Heath Hunnicutt

Reputation: 19467

There are two problems with your code.

The first is that you are trying to use the logical-OR operator (||), but you are using the bit-wise-OR (|). The second is that you should be using logical-AND rather than logical-OR, anyway:

while (c != EOF && c != ' ')

Upvotes: 1

Related Questions