0

I'm working through K&R's The C Programming Language. I'm working through an exercise here that says to "Write a program that copies all of its input to its output, replacing each string of one or more blanks by a single blank."

I believe I have solved it. Somewhat. When first running the program with a.out, I can type in a number with multiple spaces and will get it returned with just one space. But, when I go to the next line and try again, it will return the numbers with no spaces at all. Also, if I type in a string of letters like "33 33 33" it will only leave one space for the entire line. It becomes "33 3333".

I know that I could just Google the answer to the exercise itself but I don't think that that would help me learn why my code is behaving the way it is. Any help would be much appreciated.

main()
{
    int c, nl, upper;
    nl = 0;
    upper = 2;
    while( ( c = getchar() ) != EOF )
    {
        if( c == ' ' )
        { 
            ++nl;
            if( nl >= upper )
            {
                --c;
                --nl;
            }
        }
        putchar(c);
    }
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Bearz42
  • 3
  • 2
  • 1
    K&R's *The C Programming Language* is a very outdated book which is now obsolete as modern C has evolved significantly since then. The last edition was published in 1988 - but since then we've had C89, C90, C11 and many compiler-specific variations. My advice is to put the book away and loan a far more recent tome from your library instead, especially one that focuses on C11 (and one that advises against the many *unsafe* features of the original C standard library, like `gets`: https://stackoverflow.com/questions/4588581 ) – Dai Jun 07 '17 at 01:46
  • It works for me. I you using the standard include files? – Rob Jun 07 '17 at 01:51
  • Yes I believe that I'm using the standard include files. I'm using . For me, it only does it on the first "double space." "hello__cold__World" where each _ is a blank, comes back "hello_coldWorld" and I cannot figure out why. – Bearz42 Jun 07 '17 at 01:52
  • What is the purpose of `c -= ' '`? This is equivalent to `c = c - 32`. – Dai Jun 07 '17 at 01:53
  • dai, I have actually changed it, and will edit it in my main post to be `--c`, yet the problem still arises – Bearz42 Jun 07 '17 at 01:56
  • If you're getting more than one character of output then your title is quite misleading. Obviously the loop executes more than once. – Retired Ninja Jun 07 '17 at 01:57
  • My apologies ninja, this is my first post here. I did not know a better way to phrase the question. – Bearz42 Jun 07 '17 at 02:02

3 Answers3

0
int main()
{
    int c, nl;
    nl = 0;
    while ((c = getchar()) != EOF)
    {
        if (c == ' ')
        {
            nl ++;
        }
        else
        {
            nl = 0;
        }

        if (nl <= 1)
        {
            putchar(c);
        }
    }
    return 0;
}
Jimmy
  • 223
  • 1
  • 11
0

Nice try. But you have made some mistakes.

You didn't set counter to the initial value when character other then the space is encountered. So if your input have multiple white spaces in between non white space character like 33 33 33 then the first white space will be printed & others are skipped. So the output would be 33 3333

you have to understand that the char data type only store single character & in ASCII encoding. When you apply arithmetic operations on char, it just change the character Value. So when you decrease the char variable it refers to a another character. So ultimately it prints garbage value.

Try this one.

while ((c = getchar()) != EOF){
    if (c == ' '){
        ++nl;
        if (nl >= upper){
            continue;
        }
    }
    else{
        nl=0;
    }
    putchar(c);
}

Logic is simple...
If there is multiple spaces, put the first space & skip others.

Neel Patel
  • 358
  • 2
  • 13
  • Ah okay that makes so much sense and really helps to answer my question with the whole thing. Thank you. – Bearz42 Jun 07 '17 at 02:43
  • @Bearz42 if your question answered correctly then close the question by accepting the answer or raise the query so other can try to solve it. That's how the stack overflow works. – Neel Patel Jun 07 '17 at 03:06
0

The solution you've posted is more complicated than it needs to be - your also performs some operations that seem meaningless to me, such as c -= ' '.

I think you should practice on devising algorithms and problem-solving in general, outside of programming in any specific language. Think about how you would do it yourself given nothing more than input strings and piece of square-lined paper and a pencil.

In pseudo-code, the minimal solution is as-follows:

1. Read character C from input (if there is no input, end program)
2. If character is a space character:
    2.1. Was the last printed character a space character too? If so, don't print anything and loop back to step 1.
3. Else, print character C and loop back to step 1.

In C, this can be written minimally (in C11) as:

int main( void )
{
    bool last_char_was_space = false;
    int c;
    while( ( c = getchar() ) != EOF )
    {
        if( last_char_was_space )
        {
            if( c == ' ' ) continue; // don't print anything
            else
            {
                putchar( c );
                last_char_was_space = false;
            }
        }
        else
        {
            putchar( c );
            if( c == ' ' )
            {
                last_char_was_space = true;
            }
        }
    }

    return 0;
}

This program is a simple example of a "finite-state machine", which is an example of a stateful algorithm and the foundational building-block of things like Regular Expressions and other types of parsers. It's an essential technique to familiarise yourself with if you want to write a program that can quickly process data with maximum performance and minimal memory usage.

Dai
  • 141,631
  • 28
  • 261
  • 374
  • Thanks for your feedback dai. I commented and edited my post to change the `c -= ' '` to `--c` But I am a little confused as to why you say that it is meaningless. When removed, the program does not erase the extra spaces at all. – Bearz42 Jun 07 '17 at 02:00
  • @Bearz42 your program shouldn't "erase" previous output - think about old-school computer printer output (C predates computer displays!) - you couldn't erase anything in those days - instead think about what you should be outputting next (in a "forward-only" manner) based on the input you've already processed instead - this is how Regular Expressions work, for example. – Dai Jun 07 '17 at 02:05
  • Oh that makes sense. Thanks so much for the help! – Bearz42 Jun 07 '17 at 02:45