Exercise 1-10 in K&R2

Discussion in 'C Programming' started by Josh Zenker, Sep 21, 2006.

  1. Josh Zenker

    Josh Zenker Guest

    This is my attempt at exercise 1-10 in K&R2. The code looks sloppy to
    me. Is there a more elegant way to do this?

    #include <stdio.h>

    /* copies input to output, printing */
    /* series of blanks as a single one */
    int main() {
    int c;

    while ((c = getchar()) != EOF) {
    putchar(c);
    if (c == ' ') {
    while ((c = getchar()) == ' ')
    ; /* null statement */
    putchar(c);
    }
    }

    return 0;
    }

    It produces the expected output when compiled with gcc-3.4.6 on a
    Gentoo box. So I'm assuming the code is at least correct, though not
    necessarily optimal.

    JZ
     
    Josh Zenker, Sep 21, 2006
    #1
    1. Advertising

  2. Josh Zenker

    Ian Collins Guest

    Josh Zenker wrote:
    > This is my attempt at exercise 1-10 in K&R2. The code looks sloppy to
    > me. Is there a more elegant way to do this?
    >
    > #include <stdio.h>
    >
    > /* copies input to output, printing */
    > /* series of blanks as a single one */
    > int main() {
    > int c;
    >
    > while ((c = getchar()) != EOF) {
    > putchar(c);
    > if (c == ' ') {
    > while ((c = getchar()) == ' ')
    > ; /* null statement */
    > putchar(c);


    Doesn't this print an extra space? You printed the character before the if.

    --
    Ian Collins.
     
    Ian Collins, Sep 21, 2006
    #2
    1. Advertising

  3. Josh Zenker

    Josh Zenker Guest

    Ian Collins wrote:
    > Josh Zenker wrote:
    > > This is my attempt at exercise 1-10 in K&R2.


    Oops, I meant exercise 1-9. I also realized after I posted this that
    there's probably a ton of code out there for this exact exercise. I'll
    search the group archives.

    > > The code looks sloppy to
    > > me. Is there a more elegant way to do this?
    > >
    > > #include <stdio.h>
    > >
    > > /* copies input to output, printing */
    > > /* series of blanks as a single one */
    > > int main() {
    > > int c;
    > >
    > > while ((c = getchar()) != EOF) {
    > > putchar(c);
    > > if (c == ' ') {
    > > while ((c = getchar()) == ' ')
    > > ; /* null statement */
    > > putchar(c);

    >
    > Doesn't this print an extra space? You printed the character before the if.


    I tested it on several different inputs, and it seems to produce the
    desired output. For example, input "argle bargle" produces output
    "argle bargle".

    JZ
     
    Josh Zenker, Sep 21, 2006
    #3
  4. Josh Zenker

    Ian Collins Guest

    Josh Zenker wrote:
    > Ian Collins wrote:
    >
    >>Josh Zenker wrote:
    >>
    >>>This is my attempt at exercise 1-10 in K&R2.

    >
    >
    > Oops, I meant exercise 1-9. I also realized after I posted this that
    > there's probably a ton of code out there for this exact exercise. I'll
    > search the group archives.
    >
    >
    >>>The code looks sloppy to
    >>>me. Is there a more elegant way to do this?
    >>>
    >>>#include <stdio.h>
    >>>
    >>>/* copies input to output, printing */
    >>>/* series of blanks as a single one */
    >>>int main() {
    >>> int c;
    >>>
    >>> while ((c = getchar()) != EOF) {
    >>> putchar(c);
    >>> if (c == ' ') {
    >>> while ((c = getchar()) == ' ')
    >>> ; /* null statement */
    >>> putchar(c);

    >>
    >>Doesn't this print an extra space? You printed the character before the if.

    >
    >
    > I tested it on several different inputs, and it seems to produce the
    > desired output. For example, input "argle bargle" produces output
    > "argle bargle".
    >

    Silly me, I didn't spot the while terminating with c != ' '.

    --
    Ian Collins.
     
    Ian Collins, Sep 21, 2006
    #4
  5. Josh Zenker wrote:

    > This is my attempt at exercise 1-10 in K&R2. The code looks sloppy to
    > me. Is there a more elegant way to do this?
    >
    > #include <stdio.h>
    >
    > /* copies input to output, printing */
    > /* series of blanks as a single one */
    > int main() {
    > int c;
    >
    > while ((c = getchar()) != EOF) {
    > putchar(c);
    > if (c == ' ') {
    > while ((c = getchar()) == ' ')


    You need to check for EOF here.

    > ; /* null statement */
    > putchar(c);
    > }
    > }
    >
    > return 0;
    > }
    >
    > It produces the expected output when compiled with gcc-3.4.6 on a
    > Gentoo box. So I'm assuming the code is at least correct, though not
    > necessarily optimal.


    If you make the above correction then it's fine.
     
    Spiros Bousbouras, Sep 21, 2006
    #5
  6. Josh Zenker

    CBFalconer Guest

    Josh Zenker wrote:
    >
    > This is my attempt at exercise 1-10 in K&R2. The code looks
    > sloppy to me. Is there a more elegant way to do this?
    >
    > #include <stdio.h>
    >
    > /* copies input to output, printing */
    > /* series of blanks as a single one */
    > int main() {
    > int c;
    >
    > while ((c = getchar()) != EOF) {
    > putchar(c);
    > if (c == ' ') {
    > while ((c = getchar()) == ' ')
    > ; /* null statement */
    > putchar(c);
    > }
    > }
    >
    > return 0;
    > }
    >
    > It produces the expected output when compiled with gcc-3.4.6 on a
    > Gentoo box. So I'm assuming the code is at least correct, though
    > not necessarily optimal.


    I like:

    #include stdio.h

    int main(void) {
    int ch, lastch = EOF;

    while (EOF != (ch = getchar())) {
    if ((' ' != ch) && (' ' != lastch)) putchar(ch);
    lastch = ch;
    }
    return 0;
    } /* untested */

    --
    "The most amazing achievement of the computer software industry
    is its continuing cancellation of the steady and staggering
    gains made by the computer hardware industry..." - Petroski


    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Sep 21, 2006
    #6
  7. Josh Zenker

    suresh Guest

    Josh Zenker wrote:

    > This is my attempt at exercise 1-10 in K&R2. The code looks sloppy to
    > me. Is there a more elegant way to do this?
    >
    > #include <stdio.h>
    >
    > /* copies input to output, printing */
    > /* series of blanks as a single one */
    > int main() {
    > int c;
    >
    > while ((c = getchar()) != EOF) {
    > putchar(c);
    > if (c == ' ') {
    > while ((c = getchar()) == ' ')

    Josh Zenker wrote:

    > This is my attempt at exercise 1-10 in K&R2. The code looks sloppy to
    > me. Is there a more elegant way to do this?
    >
    > #include <stdio.h>
    >
    > /* copies input to output, printing */
    > /* series of blanks as a single one */
    > int main() {
    > int c;
    >
    > while ((c = getchar()) != EOF) {
    > putchar(c);
    > if (c == ' ') {
    > while ((c = getchar()) == ' ')


    You have missed the EOF check here (as somebody has pointed out
    already).
    That is why it is a good idea to have one point input for any text
    processing. Consider the following.

    #include <stdio.h>

    int main(void)
    {
    int c;
    int blank = 0;
    while((c = getchar()) != EOF)
    {
    if(c == ' ')
    {
    if(!blank)
    {
    blank = 1;
    putchar(c);
    }
    }
    else
    {
    blank = 0;
    putchar(c);
    }
    }
    return 0;
    }
     
    suresh, Sep 21, 2006
    #7
  8. Josh Zenker wrote:
    > This is my attempt at exercise 1-10 in K&R2. The code looks sloppy to
    > me. Is there a more elegant way to do this?


    You can do this two general ways

    (1) Note the state of "multiple spaces" by using a variable.

    (2) Note it by your place in the code.

    The main drawback to (2) is duplicated loops, which increases the
    likelyhood you forget to do every check that is needed in every loop.
    Hey! That happened, you're not checking for EOF while getting blanks!
    You'll end up printing EOF as a character!

    So I'd recommend method (1). Then you'll have just one place to do a
    getchar, check for EOF, do a putchar. Hey! there's a problem there
    too! You're not checking for error on putchar(). Don't feel bad, not
    checking for errors has become rife. See any Microsoft example code.
     
    Ancient_Hacker, Sep 21, 2006
    #8
  9. On Thu, 21 Sep 2006, CBFalconer wrote:

    [snip]

    > I like:
    >
    > #include stdio.h
    >
    > int main(void) {
    > int ch, lastch = EOF;
    >
    > while (EOF != (ch = getchar())) {
    > if ((' ' != ch) && (' ' != lastch)) putchar(ch);
    > lastch = ch;
    > }
    > return 0;
    > } /* untested */


    I assume that your '<' and '>' keys are broken today. :)

    Tak-Shing
     
    Tak-Shing Chan, Sep 21, 2006
    #9
  10. Josh Zenker

    CBFalconer Guest

    Tak-Shing Chan wrote:
    > On Thu, 21 Sep 2006, CBFalconer wrote:
    >
    > [snip]
    >
    >> I like:
    >>
    >> #include stdio.h
    >>
    >> int main(void) {
    >> int ch, lastch = EOF;
    >>
    >> while (EOF != (ch = getchar())) {
    >> if ((' ' != ch) && (' ' != lastch)) putchar(ch);
    >> lastch = ch;
    >> }
    >> return 0;
    >> } /* untested */

    >
    > I assume that your '<' and '>' keys are broken today. :)


    Huh? I don't understand.

    --
    Some informative links:
    news:news.announce.newusers
    http://www.geocities.com/nnqweb/
    http://www.catb.org/~esr/faqs/smart-questions.html
    http://www.caliburn.nl/topposting.html
    http://www.netmeister.org/news/learn2quote.html



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Sep 21, 2006
    #10
  11. CBFalconer said:

    > Tak-Shing Chan wrote:
    >> On Thu, 21 Sep 2006, CBFalconer wrote:
    >>
    >> [snip]
    >>
    >>> I like:
    >>>
    >>> #include stdio.h
    >>>

    <SNIP>
    >>
    >> I assume that your '<' and '>' keys are broken today. :)

    >
    > Huh? I don't understand.


    How about now? :)

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
     
    Richard Heathfield, Sep 21, 2006
    #11
  12. Josh Zenker

    Joe Wright Guest

    CBFalconer wrote:
    > Josh Zenker wrote:
    >> This is my attempt at exercise 1-10 in K&R2. The code looks
    >> sloppy to me. Is there a more elegant way to do this?
    >>
    >> #include <stdio.h>
    >>
    >> /* copies input to output, printing */
    >> /* series of blanks as a single one */
    >> int main() {
    >> int c;
    >>
    >> while ((c = getchar()) != EOF) {
    >> putchar(c);
    >> if (c == ' ') {
    >> while ((c = getchar()) == ' ')
    >> ; /* null statement */
    >> putchar(c);
    >> }
    >> }
    >>
    >> return 0;
    >> }
    >>
    >> It produces the expected output when compiled with gcc-3.4.6 on a
    >> Gentoo box. So I'm assuming the code is at least correct, though
    >> not necessarily optimal.

    >
    > I like:
    >
    > #include stdio.h
    >
    > int main(void) {
    > int ch, lastch = EOF;
    >
    > while (EOF != (ch = getchar())) {
    > if ((' ' != ch) && (' ' != lastch)) putchar(ch);
    > lastch = ch;
    > }
    > return 0;
    > } /* untested */
    >

    Testing is good. How about..

    #include <stdio.h>

    int main(void) {
    int ch, last = 0;
    while ((ch = getchar()) != EOF) {
    if (!(last == ' ' && ch == ' '))
    putchar(ch);
    last = ch;
    }
    return 0;
    }
    ...or..

    #include <stdio.h>

    int main(void) {
    int ch, last = 0;
    while ((ch = getchar()) != EOF) {
    if (last != ' ' || ch != ' ')
    putchar(ch);
    last = ch;
    }
    return 0;
    }


    --
    Joe Wright
    "Everything should be made as simple as possible, but not simpler."
    --- Albert Einstein ---
     
    Joe Wright, Sep 21, 2006
    #12
  13. Josh Zenker

    Joe Wright Guest

    Josh Zenker wrote:
    > This is my attempt at exercise 1-10 in K&R2. The code looks sloppy to
    > me. Is there a more elegant way to do this?
    >
    > #include <stdio.h>
    >
    > /* copies input to output, printing */
    > /* series of blanks as a single one */
    > int main() {
    > int c;
    >
    > while ((c = getchar()) != EOF) {
    > putchar(c);
    > if (c == ' ') {
    > while ((c = getchar()) == ' ')
    > ; /* null statement */
    > putchar(c);
    > }
    > }
    >
    > return 0;
    > }
    >
    > It produces the expected output when compiled with gcc-3.4.6 on a
    > Gentoo box. So I'm assuming the code is at least correct, though not
    > necessarily optimal.
    >
    > JZ
    >

    Hi Josh. That's Exercise 1-9 in my book, on page 20.

    #include <stdio.h>

    int main(void) {
    int ch, last = 0;
    while ((ch = getchar()) != EOF) {
    if (last != ' ' || ch != ' ')
    putchar(ch);
    last = ch;
    }
    return 0;
    }

    Elegance?

    --
    Joe Wright
    "Everything should be made as simple as possible, but not simpler."
    --- Albert Einstein ---
     
    Joe Wright, Sep 21, 2006
    #13
  14. Josh Zenker

    CBFalconer Guest

    Richard Heathfield wrote:
    > CBFalconer said:
    >> Tak-Shing Chan wrote:
    >>> On Thu, 21 Sep 2006, CBFalconer wrote:
    >>>
    >>> [snip]
    >>>
    >>>> I like:
    >>>>
    >>>> #include stdio.h
    >>>>

    > <SNIP>
    >>>
    >>> I assume that your '<' and '>' keys are broken today. :)

    >>
    >> Huh? I don't understand.

    >
    > How about now? :)


    AHA ! :) Good thing I put in the 'untested' comment.

    --
    Some informative links:
    news:news.announce.newusers
    http://www.geocities.com/nnqweb/
    http://www.catb.org/~esr/faqs/smart-questions.html
    http://www.caliburn.nl/topposting.html
    http://www.netmeister.org/news/learn2quote.html


    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Sep 22, 2006
    #14
  15. So far we've had 3 versions of code performing the
    task which is exercise 1-10 in K&R2:

    VERSION 1

    #include <stdio.h>

    /* copies input to output, printing */
    /* series of blanks as a single one */
    int main() {
    int c;

    while ((c = getchar()) != EOF) {
    putchar(c);
    if (c == ' ') {
    while ((c = getchar()) == ' ')
    if (c == EOF) return 0 ;
    putchar(c);
    }
    }
    return 0;
    }

    VERSION 2

    #include <stdio.h>

    int main(void)
    {
    int c;
    int blank = 0;
    while((c = getchar()) != EOF)
    {
    if(c == ' ')
    {
    if(!blank)
    {
    blank = 1;
    putchar(c);
    }
    }
    else
    {
    blank = 0;
    putchar(c);
    }
    }
    return 0;
    }

    VERSION 3

    #include <stdio.h>

    int main(void) {
    int ch, last = 0;
    while ((ch = getchar()) != EOF) {
    if (last != ' ' || ch != ' ')
    putchar(ch);
    last = ch;
    }
    return 0;
    }

    Judging from some of the statements made here some
    people consider versions 2 and 3 preferable on the
    basis that they are less prone to bugs than version
    1 which did have a bug in its original inception.

    Personally I prefer version 1 because versions 2 and
    3 have an extra assignment at every iteration of the
    loop. On some platforms this *will* make a difference
    in performance. Even if it won't or the difference in
    performance turns out to be miniscule (and that will almost
    certainly turn out to be the case on every realistic
    input) it still does not agree at all with my sense of
    aesthetics to introduce extra instructions in such a
    blatant manner.

    Apart from that I actually consider version 3 the
    harder to write and verify.
     
    Spiros Bousbouras, Sep 22, 2006
    #15
  16. "Spiros Bousbouras" <> writes:

    > So far we've had 3 versions of code performing the
    > task which is exercise 1-10 in K&R2:


    > VERSION 1
    > int main() {
    > int c;
    > while ((c = getchar()) != EOF) {
    > putchar(c);
    > if (c == ' ') {
    > while ((c = getchar()) == ' ') if (c == EOF) return 0;
    > putchar(c);
    > }
    > }
    > return 0;
    > }


    > VERSION 2
    > int main(void) {
    > int c, blank = 0;
    > while((c = getchar()) != EOF) {
    > if(c == ' ') {
    > if(!blank) {
    > blank = 1;
    > putchar(c);
    > }
    > } else {
    > blank = 0;
    > putchar(c);
    > }
    > }
    > return 0;
    > }


    > VERSION 3
    > int main(void) {
    > int ch, last = 0;
    > while ((ch = getchar()) != EOF) {
    > if (last != ' ' || ch != ' ')
    > putchar(ch);
    > last = ch;
    > }
    > return 0;
    > }


    [cut]

    > Personally I prefer version 1 because versions 2 and
    > 3 have an extra assignment at every iteration of the
    > loop. On some platforms this *will* make a difference
    > in performance.


    There are only two integers which both will probably be stored in
    registers so a single "mov reg, reg" instruction won't make a big
    difference IMO.

    > Even if it won't or the difference in
    > performance turns out to be miniscule (and that will almost
    > certainly turn out to be the case on every realistic
    > input) it still does not agree at all with my sense of
    > aesthetics to introduce extra instructions in such a
    > blatant manner.
    >
    > Apart from that I actually consider version 3 the
    > harder to write and verify.


    IMO the 3rd version is the easiest to write and understand. It's
    straightforward, ie. the exercise is about printing all characters
    unless it is a space and the previous character was a space, so if the
    previous character (last != ' ') was not a space or this character is
    not a space (ch != ' ') we shall print the character.

    Moreover, there is only one way the loop may stop (ie. the loop
    condition) and the first version involves return statement to stop the
    loop which some prefer to avoid (just like break statement).

    Only I would do:

    #v+
    #include <stdio.h>
    int main(void) {
    int ch, last = 0;
    while ((ch = getchar()) != EOF) {
    if (last != ' ' || ch != ' ') {
    putchar(last = ch);
    }
    }
    return 0;
    }
    #v-


    --
    Best regards, _ _
    .o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
    ..o | Computer Science, Michal "mina86" Nazarewicz (o o)
    ooo +--<mina86*tlen.pl>--<jid:mina86*jabber.org>--ooO--(_)--Ooo--
     
    Michal Nazarewicz, Sep 22, 2006
    #16
  17. Josh Zenker

    jaysome Guest

    On Thu, 21 Sep 2006 20:48:18 -0400, CBFalconer <>
    wrote:

    >Richard Heathfield wrote:
    >> CBFalconer said:
    >>> Tak-Shing Chan wrote:
    >>>> On Thu, 21 Sep 2006, CBFalconer wrote:
    >>>>
    >>>> [snip]
    >>>>
    >>>>> I like:
    >>>>>
    >>>>> #include stdio.h
    >>>>>

    >> <SNIP>
    >>>>
    >>>> I assume that your '<' and '>' keys are broken today. :)
    >>>
    >>> Huh? I don't understand.

    >>
    >> How about now? :)

    >
    >AHA ! :) Good thing I put in the 'untested' comment.


    Perhaps in the future you should change "untested" to "uncompiled" or
    "uncompiled and untested" in your comments. Not compiling
    code--without errors--is akin to and arguably worse than top-posting.

    --
    jay
     
    jaysome, Sep 23, 2006
    #17
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kevin Spencer
    Replies:
    2
    Views:
    473
    John Saunders
    Aug 6, 2003
  2. lonelyplanet999

    Exercise needed for java 2 programmer test

    lonelyplanet999, Sep 30, 2003, in forum: Java
    Replies:
    1
    Views:
    4,202
    VisionSet
    Sep 30, 2003
  3. Xah Lee
    Replies:
    12
    Views:
    619
    Duncan Booth
    Jun 22, 2005
  4. Bruce .J Sam
    Replies:
    0
    Views:
    1,972
    Bruce .J Sam
    Jun 16, 2005
  5. Aries
    Replies:
    7
    Views:
    418
    Aries
    May 3, 2006
Loading...

Share This Page