Exercise 1-10 in K&R2

J

Josh Zenker

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
 
I

Ian Collins

Josh said:
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.
 
J

Josh Zenker

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.
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
 
I

Ian Collins

Josh said:
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.




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 != ' '.
 
S

Spiros Bousbouras

Josh said:
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.
 
C

CBFalconer

Josh said:
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 */
 
S

suresh

Josh said:
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 said:
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;
}
 
A

Ancient_Hacker

Josh said:
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.
 
T

Tak-Shing Chan

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
 
C

CBFalconer

Tak-Shing Chan said:
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:
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
 
J

Joe Wright

CBFalconer said:
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;
}
 
J

Joe Wright

Josh said:
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?
 
C

CBFalconer

Richard said:
CBFalconer said:
Tak-Shing Chan said:
On Thu, 21 Sep 2006, CBFalconer wrote:

[snip]

I like:

#include stdio.h
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:
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
 
S

Spiros Bousbouras

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.
 
M

Michal Nazarewicz

Spiros Bousbouras said:
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-
 
J

jaysome

Richard said:
CBFalconer said:
Tak-Shing Chan wrote:
On Thu, 21 Sep 2006, CBFalconer wrote:

[snip]

I like:

#include stdio.h
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top