Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Exercise from Kernagan and Richie

7 views
Skip to first unread message

Phil Bradby

unread,
Apr 8, 2010, 4:43:33 PM4/8/10
to
Hi

I am using K&R to teach a course in C and I'm puzzled by Exercise 2-2,
"write a loop equivalent to the for loop above without using && or ||".

Here is my answer:

for(i=0; i<lim-1?(c=getchar())!='\n'?c!=EOF:0:0; i++) s[i]=c;

These are my questions.

1) Is my answer right? I think so but it makes my head ache to think
about it!

2) Is it what they had in mind? It wasn't really obvious to me what
solution they were thinking of and I don't think many of my students will
come up with the answer above.

3) What's the point of the question? I can't think of any circumstances
where && and || wouldn't be available - why would you want to tie your
hands by avoiding a language feature that does exactly what's needed?

Cheers,
PB

Pillsy

unread,
Apr 8, 2010, 5:06:54 PM4/8/10
to
On Apr 8, 4:43 pm, Phil Bradby <nos...@nospam.com> wrote:
[...]

> I am using K&R to teach a course in C and I'm puzzled by Exercise 2-2,
> "write a loop equivalent to the for loop above without using && or ||".

> Here is my answer:

> for(i=0; i<lim-1?(c=getchar())!='\n'?c!=EOF:0:0; i++) s[i]=c;

> These are my questions.

> 1) Is my answer right? I think so but it makes my head ache to think
> about it!

It would be much easier to be sure you're right if you added some
judiciously placed parentheses.

> 2) Is it what they had in mind?

This exercise is on p. 42 in my copy, and the conditional operator is
introduced on p. 51, so I doubt it.

> It wasn't really obvious to me what solution they were
> thinking of and I don't think many of my students will
> come up with the answer above.

My solution involved a status variable, a `while` loop, and many `if`
statements.

> 3) What's the point of the question?

I think it's to show you how convenient the short-circuiting behavior
of `&&` and `||` is, and how much more cumbersome things would be
without it.

Cheers,
Pillsy

ImpalerCore

unread,
Apr 8, 2010, 5:07:31 PM4/8/10
to
On Apr 8, 4:43 pm, Phil Bradby <nos...@nospam.com> wrote:

You might find what you need here, maintained by Heathfield.

http://users.powernet.co.uk/eton/kandr2/index.html

Also found here.

http://clc-wiki.net/wiki/K&R2_solutions

Hope this helps,
John D.

Message has been deleted

Phil Carmody

unread,
Apr 8, 2010, 6:04:06 PM4/8/10
to
Phil Bradby <nos...@nospam.com> writes:
> I am using K&R to teach a course in C and I'm puzzled by Exercise 2-2,
> "write a loop equivalent to the for loop above without using && or ||".
>
> Here is my answer:
>
> for(i=0; i<lim-1?(c=getchar())!='\n'?c!=EOF:0:0; i++) s[i]=c;
>
> These are my questions.
>
> 1) Is my answer right? I think so but it makes my head ache to think
> about it!

If the original was something like the following, then yes:

for(i=0; i<lim-1 && (c=getchar())!='\n' && c!=EOF; i++) s[i]=c;

> 2) Is it what they had in mind? It wasn't really obvious to me what
> solution they were thinking of and I don't think many of my students will
> come up with the answer above.

If I've got the problem right, then I'd answer exactly the same as you.

> 3) What's the point of the question? I can't think of any circumstances
> where && and || wouldn't be available - why would you want to tie your
> hands by avoiding a language feature that does exactly what's needed?

Perhaps it's an exercise in avoiding wrong answers. For example this
might be suggested by some as the condition, but would be badly wrong
((i<lim-1) + ((c=getchar())!='\n') + (c!=EOF)) == 3
as it loses both the shortcircuit operation, but more importantly
can evaluate c=getchar() and c!=EOF in either order, and therefore
invokes undefined behaviour.

Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1

James Harris

unread,
Apr 8, 2010, 8:46:48 PM4/8/10
to
On 8 Apr, 21:43, Phil Bradby <nos...@nospam.com> wrote:
> Hi
>
> I am using K&R to teach a course in C and I'm puzzled by Exercise 2-2,
> "write a loop equivalent to the for loop above without using && or ||".
>
> Here is my answer:
>
> for(i=0; i<lim-1?(c=getchar())!='\n'?c!=EOF:0:0; i++) s[i]=c;
>
> These are my questions.
>
> 1) Is my answer right? I think so but it makes my head ache to think
> about it!

As a rule (especially as you are teaching) I'd say always strive for
simplicity and clarity. So I'd have a go at this:

for (i = 0; i < lim - 1; i++) {
c = getchar();
if (c == '\n') break;
if (c == EOF) break;
s[i] = c;
}

It's intended to show the structure of the computation:

1. keeps the main loop control together as a unit in the for statement
(incrementing i),

2. shows sequential statements as sequential.

I would say this is easier to understand and easier to maintain (and
hence less likely to cause a headache!) and so is a better solution -
but others may disagree.

> 2) Is it what they had in mind? It wasn't really obvious to me what


> solution they were thinking of and I don't think many of my students will
> come up with the answer above.

Since both ?: which you used and break which I used are covered later
I suspect they intended students to write something horrendous.

AIUI you can use the bitwise & and | to get ands and ors with bit
patterns which, if used in a test evaluate as 0 => false, anything
else => true - but they also are not introduced until later.

> 3) What's the point of the question? I can't think of any circumstances
> where && and || wouldn't be available - why would you want to tie your
> hands by avoiding a language feature that does exactly what's needed?

For the point of the question: I have no idea. For why write some code
without a specific feature: this could be nothing more than a
challenge to test understanding.

Actually I've just had a thought that you could modify i to end the
loop which allows the following which I think only uses features
introduced to where Ex 2-2 is found (page 42 in my edition of K&R2).

for (i = 0; i < lim - 1; i++) {
c = getchar();
if (c == '\n')
i = lim - 2;
else if (c == EOF)
i = lim - 2;
else s[i] = c;
}

It sets i to lim - 2 because the i++ will execute at the end of the
loop and hence i will be lim - 1 when tested. This is both the limit
condition of the loop and known to be in the range of i's type.

If I had the choice I'd use the version with break, above, as it is
clearer.

James

Uno

unread,
Apr 9, 2010, 4:12:49 AM4/9/10
to
Stefan Ram wrote:

> Phil Bradby <nos...@nospam.com> writes:
>> 1) Is my answer right? I think so but it makes my head ache to think
>> about it!
>
> The loop from the question seems to be:
>
> for(i=0; i<lim-1 && (c=getchar()) != '\n' && c != EOF; ++i)
> s[i] = c;
>
> One answer that comes to my mind after only some seconds is:
>
> for( i = 0;; ++i )
> { if( i < lim - 1 )
> if(( c = getchar() )!= '\n' )
> if( c != EOF )
> { s[ i ]= c; continue; }
> break; }
>
> But I have not tested it.

>
>> 2) Is it what they had in mind?
>
> This is programming, not mind reading.
>

Who said anything about mind reading? One measures the authors' intent
by the words on the page.
--
Uno

Phil Bradby

unread,
Apr 9, 2010, 2:18:45 PM4/9/10
to
James Harris wrote:
> for (i = 0; i < lim - 1; i++) {
> c = getchar();
> if (c == '\n') break;
> if (c == EOF) break;
> s[i] = c;
> }
>
> for (i = 0; i < lim - 1; i++) {
> c = getchar();
> if (c == '\n')
> i = lim - 2;
> else if (c == EOF)
> i = lim - 2;
> else s[i] = c;
> }

Interesting. I'd read the question as requiring the same loop body, with
only a change in the stopping condition to rewrite it without && or ||.

Cheers,
PB

0 new messages