feedforward: learning C
Author Message
feedforward: learning C

Greetings,

I study C, on my own, at home. I recently got King's text-
book. I think it is great! However, studying at home,
I don't get any feedforward from an instructor or class.
So I'll show my progress here, and hopefully learn
something new. I'm up to chapter 5, already.

Exercise 5.1.4: (page 82, C Programming:A Modern Approach
K.N.King. W.W.Norton&Co., 1996
ISBN 0-393-96945-2)
Write a SINGLE EXPRESSION whose value is either -1, 0, or 1,
depending on whether i is less than, equal to, or greater
than j, respectively.

#include <stdio.h>
int
main(void)
{
int i, j;

printf("Enter values for i and j: ");
scanf("%d %d", &i, &j);

printf("%d\n",
(
(i < j)?(i = -1):(
(i == j)?(i = 0):(
(i > j)?(i = 1):i))
)
);

return (0);

Quote:
}

Comments? This is C, not C++. The brain-bender for me
was doing it in a single expression. So I used the
ternary operator and nested it. I couldn't see how to
do it using && or ||.

Yes, this IS my homework! However, I am not enrolled
in any University or College classes. I am studying
on my own. I have made an honest effort here, and am
looking for feedforward on other ways the problem may
be solved. It would help if the person(s) who reply,
are familiar with King's text, but I'll look at any
positive response! Thanks in advance!

--
Kenneth W. Melvin

http://www.*-*-*.com/
The best thing about Linux is the people who use it!!!

Fri, 07 Jan 2000 03:00:00 GMT
feedforward: learning C

[mega-snip]
hints:
What is the sign of the result when you subract i from j:
1.  When i > j ?
2.  When i < j ?
3.  When i == j ?

Considering the above, how could you use a single subraction and a single
test to produce the desired result?

Many text books will explain this sort of thing when discussing the
comparison function used by qsort().

Sat, 08 Jan 2000 03:00:00 GMT
feedforward: learning C

** none **   writes:

Quote:

>[mega-snip]
>hints:
>What is the sign of the result when you subract i from j:
>        1.  When i > j ?

It is negative *if* the subtraction doesn't overflow.

Quote:
>        2.  When i < j ?

It is positive *if* the subtraction doesn't overflow.

Quote:
>        3.  When i == j ?

The result is zero.

Unfortunately we're not told anything about the ranges of i and j so we
can't assume that a subtraction won't overflow, so it isn't appropriate
here.

Quote:
>Considering the above, how could you use a single subraction and a single
>test to produce the desired result?

Even if we assume that the subtraction doesn't overflow a test will only
produce 2 possible results (generally 0 or 1) whereas here we need 3 (-1, 0,
and 1) so this won't work.

Quote:
>Many text books will explain this sort of thing when discussing the
>comparison function used by qsort().

This can be useful for comparing chars (although C doesn't strictly require
ints to have a wider range than chars) and ints *if* you know enough about
the range of the values being held to guarantee that a subtraction won't
overflow. However typically when you are comparing characters you are
comparing a sequence of characters or a string in which case it is natural
to use strcmp(), strncmp() or memcmp(). A book that explains this sort of
thing should also explain the caveats.

--
-----------------------------------------

-----------------------------------------

Sat, 08 Jan 2000 03:00:00 GMT
feedforward: learning C

Quote:

> [mega-snip]
> hints:
> What is the sign of the result when you subract i from j:
>         1.  When i > j ?
>         2.  When i < j ?
>         3.  When i == j ?

> Considering the above, how could you use a single subraction and a single
> test to produce the desired result?

Interesting! I added a line to subtract j from i, and got the
proper signs:

Enter values for i and j: 11 22
-1
-11

Enter values for i and j: 22 11
1
11

Enter values for i and j: 11 11
0
0

Now I'm going to work on the test to get 1,0, or -1.

In the above, the top number is from my original
program, and the bottom number from subtracting j from i.

Thanks! I didn't even see the thing about simply
subtracting the two values!

Quote:

> Many text books will explain this sort of thing when discussing the
> comparison function used by qsort().

I'll keep that in mind as I continue my studies!
Thanks again for the feedforward!
--
Kenneth W. Melvin

http://www.geocities.com/SiliconValley/8823/index.html
The best thing about Linux is the people who use it!!!

Sat, 08 Jan 2000 03:00:00 GMT
feedforward: learning C

I haven't been expressing myself well lately.  I have been making far too
many implicit assumptions in my statements without spelling anything out.
For student exercises, I have been answering only part of the question, but
this is intentional.  But, just to show it can be done, here are some ways
to create a solution to the exercise.  They are still not complete, because
even compare1() currently requires several statements.  The original
requirement is:

"Write a SINGLE EXPRESSION whose value is either -1, 0, or 1,
depending on whether i is less than, equal to, or greater
than j, respectively."

#include <stdio.h>
#include <stdlib.h>

/* Using if. This is expanded for clarity, but can be made into a single */
/* compound statement in the C language. */
int compare0(int a, int b)
{
int retval;
long difference = (long) a - b; /* You can even use double if you like
*/

if (difference < 0)
retval = -1;
else /* OK, I cheated, but it is still just one if! */
retval = difference > 0 ? 1 : 0;
return retval;
}

/* I don't know if this is better or not, but it is certainly shorter... */
/* If compound statements are not allowed, the solution will */
/* probably need to take a form along these lines... */
int compare1(int a, int b)
{ /* You can even use double if you like */
long difference = (long) a - b; /* This can be done in-line w/o temp */
return (difference) > 0 ? 1 : (difference) < 0 ? -1 : 0;
}

int main()
{
char string[256];
int a,
b;

puts("Enter a number:");
fgets(string, sizeof string, stdin);
a = atoi(string);
puts("Enter a number:");
fgets(string, sizeof string, stdin);
b = atoi(string);
printf("value of comparision for (%d, %d) was %d and %d\n",
a, b, compare0(a, b), compare1(a, b));
return 0;
}

Quote:

>             ** none **   writes:

> >[mega-snip]
> >hints:
> >What is the sign of the result when you subract i from j:
> >        1.  When i > j ?

> It is negative *if* the subtraction doesn't overflow.

Of course, I made no requirement about the data type for the subtraction.

Quote:
> >        2.  When i < j ?

> It is positive *if* the subtraction doesn't overflow.

Of course, I made no requirement about the data type for the subtraction.

Quote:
> >        3.  When i == j ?

> The result is zero.

> Unfortunately we're not told anything about the ranges of i and j so we
> can't assume that a subtraction won't overflow, so it isn't appropriate
> here.

It is if we use a data type for the subtraction that will hold the result.

Quote:
> >Considering the above, how could you use a single subraction and a
single
> >test to produce the desired result?

> Even if we assume that the subtraction doesn't overflow a test will only
> produce 2 possible results (generally 0 or 1) whereas here we need 3 (-1,
0,
> and 1) so this won't work.

That's true.  But it can still be done.  I said "How can it be done?" which
requires additional effort on the part of the student.

Quote:
> >Many text books will explain this sort of thing when discussing the
> >comparison function used by qsort().

> This can be useful for comparing chars (although C doesn't strictly
require
> ints to have a wider range than chars) and ints *if* you know enough
> the range of the values being held to guarantee that a subtraction won't
> overflow. However typically when you are comparing characters you are
> comparing a sequence of characters or a string in which case it is
natural
> to use strcmp(), strncmp() or memcmp(). A book that explains this sort of
> thing should also explain the caveats.

I suppose that I should have put a lot more effort into my answer.  It was
supposed to be just something to get them started.

Sat, 08 Jan 2000 03:00:00 GMT
feedforward: learning C

[posted and mailed]

To summarize, when you're writing a function which is supposed to
compare two numbers and return negative, zero, or positive, such
as a qsort comparison function, in general you do *not* want to
write

return a - b;

You *do* want to write something like

if(a < b)
return -1;
else if(a > b)
return 1;
else    return 0;

even though this is a bit more work to type, and looks like it
might be less efficient.  The two-comparison method, however,
is correct and guaranteed to work, while the subtraction method
may overflow with unpredictable results.  (As an exercise, try
comparing the numbers -30000 and 30000 on a 16-bit machine, or
-2000000000 and 2000000000 on a 32-bit machine.)

If you're teaching, either don't teach the subtraction trick
at all, or present it only surrounded by heavy caveats and
disclaimers.  If you're learning, and you've been asked in an
exercise to discover the subtraction trick for yourself, either
forget it again after you've satisfied your instructors, or maybe
complain to your instructors that they're helping to spread the
kind of programming practices that lead to unreliable code.

Steve Summit

Sat, 08 Jan 2000 03:00:00 GMT
feedforward: learning C

And yet we have the exact same problem with the following:
int a, b, c;

/* Somewhere later */
a = b+c; /* Why doesn't anybody panic over this one? */
/* What if both b and c are INT_MAX?  INT_MIN? */

If you don't know the range of the data, the assignment is dangerous.  The
assumption is that you have analyzed carefully, and do know that a is able
to contain the results of b+c.  If this is incorrect, then the design phase
went wrong.
--

Anonymous ftp sites for C-FAQ:
ftp://ftp.eskimo.com ftp://rtfm.mit.edu ftp://ftp.uu.net
Hypertext C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-FAQ Book: ISBN 0-201-84519-9.
Looking for something?  Software?  Algorithms?  Publications?
http://www.altavista.digital.com or http://www.infoseek.com

Quote:
> [posted and mailed]

> To summarize, when you're writing a function which is supposed to
> compare two numbers and return negative, zero, or positive, such
> as a qsort comparison function, in general you do *not* want to
> write

>    return a - b;

> You *do* want to write something like

>    if(a < b)
>            return -1;
>    else if(a > b)
>            return 1;
>    else    return 0;

> even though this is a bit more work to type, and looks like it
> might be less efficient.  The two-comparison method, however,
> is correct and guaranteed to work, while the subtraction method
> may overflow with unpredictable results.  (As an exercise, try
> comparing the numbers -30000 and 30000 on a 16-bit machine, or
> -2000000000 and 2000000000 on a 32-bit machine.)

> If you're teaching, either don't teach the subtraction trick
> at all, or present it only surrounded by heavy caveats and
> disclaimers.  If you're learning, and you've been asked in an
> exercise to discover the subtraction trick for yourself, either
> forget it again after you've satisfied your instructors, or maybe
> complain to your instructors that they're helping to spread the
> kind of programming practices that lead to unreliable code.

>                                    Steve Summit

Sat, 08 Jan 2000 03:00:00 GMT
feedforward: learning C

** none **   writes:

Quote:
>And yet we have the exact same problem with the following:
>int a, b, c;

>/* Somewhere later */
>a = b+c; /* Why doesn't anybody panic over this one? */

Good question, maybe they should! :-)

Generally when you write something like that you have some idea of what
the ranges are, or perhaps more subtly you have an idea of what the sum
represents. If it represents a quantity that by its very nature won't
overflow the type you've put it in then you can lay your worries to rest.

In the case of the difference calculation suggested in this thread you
don't know anything about it that suggests a useful bound on the result.
Indeed the difference (or at least its magnitude) doesn't represent
anything here.

Quote:
>/* What if both b and c are INT_MAX?  INT_MIN? */

If that is a possibility then you would have to reconsider the calculation.

Quote:
>If you don't know the range of the data, the assignment is dangerous.  The
>assumption is that you have analyzed carefully, and do know that a is able
>to contain the results of b+c.  If this is incorrect, then the design phase
>went wrong.

The problem is when this is presented as a general method of comparing
integers, typically in a qsort() or bsearch() comparison function. You can
use it if you are careful but you have to be aware of the pitfalls. One
of the pitfalls is maintenance. If the range of integers being tested is
changed you might not think of checking whether, say, a comparison function
for sorting is still valid.

--
-----------------------------------------

-----------------------------------------

Sat, 08 Jan 2000 03:00:00 GMT
feedforward: learning C

** none **   writes:

Quote:
>I haven't been expressing myself well lately.  I have been making far too
>many implicit assumptions in my statements without spelling anything out.
>For student exercises, I have been answering only part of the question, but
>this is intentional.  But, just to show it can be done, here are some ways
>to create a solution to the exercise.  They are still not complete, because
>even compare1() currently requires several statements.  The original
>requirement is:

>"Write a SINGLE EXPRESSION whose value is either -1, 0, or 1,
>depending on whether i is less than, equal to, or greater
>than j, respectively."

>#include <stdio.h>
>#include <stdlib.h>

>/* Using if. This is expanded for clarity, but can be made into a single */
>/* compound statement in the C language. */
>int compare0(int a, int b)
>    {
>    int retval;
>    long difference = (long) a - b; /* You can even use double if you like
>*/

There's no guarantee that long has a wider range than int, so this may still
fail for some values of a and b on some platforms.

With double the problem is more subtle. Imagine a platform where int and
double are both 64 bits. The problem here is that a double can't uniquely
represent all the values in an int. In that case the difference of
2 different (but close) int values might result in 0.0

Quote:
>    if (difference < 0)
>        retval = -1;
>    else /* OK, I cheated, but it is still just one if! */
>        retval = difference > 0 ? 1 : 0;
>    return retval;

Is this really any better than:

if (a < b)
retval = -1;
else
retval = a>b ? 1 : 0;

retval = a<b ? -1 : a>b;

(No? Well I liked it, it has a certain symmetry ;-) )

--
-----------------------------------------

-----------------------------------------

Sat, 08 Jan 2000 03:00:00 GMT
feedforward: learning C

[snip]

Quote:
> There's no guarantee that long has a wider range than int, so this may
still
> fail for some values of a and b on some platforms.

This one I was aware of but...

Quote:
> With double the problem is more subtle. Imagine a platform where int and
> double are both 64 bits. The problem here is that a double can't uniquely
> represent all the values in an int. In that case the difference of
> 2 different (but close) int values might result in 0.0

I hadn't thought of that!  I guess that the technique was far more
dangerous than I was aware of.  I have (a few times) used this technique by
simply promoting to the next higher type.  64 bit ints makes this a bad
idea.

Quote:
> >    if (difference < 0)
> >        retval = -1;
> >    else /* OK, I cheated, but it is still just one if! */
> >        retval = difference > 0 ? 1 : 0;
> >    return retval;

> Is this really any better than:

>      if (a < b)
>          retval = -1;
>      else
>          retval = a>b ? 1 : 0;

I'd say a good deal inferior.

Quote:
> Or how about:

>      retval = a<b ? -1 : a>b;

Now this one is really beautiful.  As nice as an unexpected checkmate or a
clever spam haiku.

Quote:
> (No? Well I liked it, it has a certain symmetry ;-) )

I do hereby accept my spanking from Steve and Lawrence as well deserved...
totally generated by extreme ignorance on my part.  I do hereby vow never
again to use subtraction to generate sign values for compares.
--
Anonymous ftp sites for C-FAQ:
ftp://ftp.eskimo.com ftp://rtfm.mit.edu ftp://ftp.uu.net
Hypertext C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-FAQ Book: ISBN 0-201-84519-9.
Looking for something?  Software?  Algorithms?  Publications?
http://www.altavista.digital.com or http://www.infoseek.com

Sat, 08 Jan 2000 03:00:00 GMT
feedforward: learning C

Quote:

> Greetings,

> I study C, on my own, at home. I recently got King's text-
> book. I think it is great! However, studying at home,
> I don't get any feedforward from an instructor or class.
> So I'll show my progress here, and hopefully learn
> something new. I'm up to chapter 5, already.
[SNIP]
> Write a SINGLE EXPRESSION whose value is either -1, 0, or 1,
> depending on whether i is less than, equal to, or greater
> than j, respectively.

Hi Kenneth W. Melvin,

Self studying is hard and without a tutor it's even harder. I appreciate
that you make the effort. For good C advice and invaluable information
about the language you should read the comp.lang.c FAQ. It also contains
a list of online C tutorials on the net, there is even an online C class
maintained by Steven Summit, the author of the FAQ and a really great
and knowledgable guy.

Quote:
> #include <stdio.h>

very good :-)

Quote:
> int
> main(void)

even better :-)

Quote:
> {
>    int i, j;

>    printf("Enter values for i and j: ");
>    scanf("%d %d", &i, &j);

Not really a good choice, but acceptable for a test program where the
input itself is not the point. For more information you might read:
12.20:  Why does everyone say not to use scanf()?  What should I use
in the FAQ.

Quote:
>    printf("%d\n",
>       (
>          (i < j)?(i = -1):(
>          (i == j)?(i = 0):(
>          (i > j)?(i = 1):i))
>       )
>    );

I would not consider this to be a correct solution. The assignment said
that the expression should *yield* -1, 0, 1 it did not mention modifying
the variable "i". When comparing two values in some way it's not a good
idea to modify one of the two values.

Now the specific solution might not be correct, but your *idea* is
good and correct :-) If you modify it slightly to yield only the
values, the result will be 100% correct. Maybe you want to try it for
yourself, so I#ll post only part of the solution:
result = (i < j) ? -1 : 0;
will yield -1 for (i<j) and 0 for (i>=j). Now if you nest this by
replacing the 0 in a similar way to what you've done in your solution,
you will get the correct expression

Quote:
> I am studying
> on my own. I have made an honest effort here, and am
> looking for feedforward on other ways the problem may
> be solved.

Making an honest effort is the important thing. Ii shows that you're
*not* one of the lazy "I don't want to do it myself" type of guys.

You can get the FAQ at http://www.eskimo.com/~scs/C-faq/top.html or
at ftp://rtfm.mit.edu/pub/usenet/comp.lang.c/C-FAQ-list and it gets
posted to this newsgroup and to news.answers regularly (at the
beginning of each month).

Stephan
(initiator of the campaign against grumpiness in c.l.c)

Sat, 08 Jan 2000 03:00:00 GMT
feedforward: learning C

Quote:
> Exercise 5.1.4: (page 82, C Programming:A Modern Approach
>                  K.N.King. W.W.Norton&Co., 1996
>                  ISBN 0-393-96945-2)
> Write a SINGLE EXPRESSION whose value is either -1, 0, or 1,
> depending on whether i is less than, equal to, or greater
> than j, respectively.
...
>       (
>          (i < j)?(i = -1):(
>          (i == j)?(i = 0):(
>          (i > j)?(i = 1):i))
>       )
...
> Comments? This is C, not C++. The brain-bender for me
> was doing it in a single expression. So I used the
> ternary operator and nested it. I couldn't see how to
> do it using && or ||.

As has been pointed out by others, you don't want to modify the value of i
if you don't have to, so this would reduce to

(
(i < j) ? -1 : (
(i == j) ? 0 : (
(i > j) ? 1 : i))
)

and unless you're using some radically different arithmetic from the rest
of the world, the last ternary operator is totally unnecessary, since if i
is not less than j and not equal to j, it MUST be greater than j, so this
reduces further, to

(
(i < j) ? -1 : (
(i == j) ? 0 : 1)
)

But I find nested ternary operators unpleasant to read, even when there's
only one level of nesting.  That's just personal preference, not advice.
But I would be tempted to write the expression as

((i < j) ? -1 : (i > j))

The reason why this works is left as an exercise, but if you have trouble
understanding it, you might want to refer to the recent overly-long-running
thread on ways of #defining TRUE and FALSE.

Mon, 10 Jan 2000 03:00:00 GMT
feedforward: learning C

Quote:

>Exercise 5.1.4: (page 82, C Programming:A Modern Approach
>                 K.N.King. W.W.Norton&Co., 1996
>                 ISBN 0-393-96945-2)
>Write a SINGLE EXPRESSION whose value is either -1, 0, or 1,
>depending on whether i is less than, equal to, or greater
>than j, respectively.

>#include <stdio.h>
>int
>main(void)
>{
>   int i, j;

>   printf("Enter values for i and j: ");
>   scanf("%d %d", &i, &j);

>   printf("%d\n",
>      (
>         (i < j)?(i = -1):(
>         (i == j)?(i = 0):(
>         (i > j)?(i = 1):i))
>      )
>   );

>   return (0);
>}
>Comments? This is C, not C++. The brain-bender for me
>was doing it in a single expression. So I used the
>ternary operator and nested it. I couldn't see how to
>do it using && or ||.

I think it's a bit more complex than it needs to be.  Try
(i < j) ? -1 :
(i > j) ? 1 :
0;
Note that this is fairly similar to yours, except that you keep
using "i = -1" when you don't need to change i at all.

Quote:
>Yes, this IS my homework! However, I am not enrolled
>in any University or College classes. I am studying
>on my own. I have made an honest effort here, and am
>looking for feedforward on other ways the problem may
>be solved. It would help if the person(s) who reply,
>are familiar with King's text, but I'll look at any
>positive response! Thanks in advance!

What, you won't look at negative responses?

BTW, I'm glad to see that a newbie is finding King's text
as accessible as I thought it would be.  It's a really
great book; I think that, once a few typos are cleaned
up, it'll be on level ground with K&R, and possibly a bit
better as a beginner's book.

-s
--
Copyright 1997 Peter Seebach - seebs at solon.com - C/Unix Wizard

The *other* C FAQ, the hacker FAQ, et al.  http://www.solon.com/~seebs
Unsolicited email (junk mail and ads) is unwelcome, and will be billed for.

Mon, 10 Jan 2000 03:00:00 GMT
feedforward: learning C

Quote:

> I think it's a bit more complex than it needs to be.  Try
>         (i < j) ? -1 :
>                 (i > j) ? 1 :
>                         0;
> Note that this is fairly similar to yours, except that you keep
> using "i = -1" when you don't need to change i at all.

Thanks. I don't know how long it will take for me to
get to the point in my programming where I am not
making everything I do, so complex. The only thing
I can think of is to keep practicing, and trying to
read other programmers solutions. The answer to that
particular problem was so simple! I am still making
mountains out of mole-hills.

Quote:

> What, you won't look at negative responses?

Well, so far, I have been able to find something
positive in all the responses I've seen.

Quote:

> BTW, I'm glad to see that a newbie is finding King's text
> as accessible as I thought it would be.  It's a really
> great book; I think that, once a few typos are cleaned
> up, it'll be on level ground with K&R, and possibly a bit
> better as a beginner's book.

Thanks for your reply. It was on the recommendation of
several people in this newsgroup that I looked into
obtaining King's textbook. Indeed, it is excellent!
I also have two other college-level C textbooks:

Problem Solving And Program Design in C. 2e.
Hanly & Koffman.
ISBN 0-201-59063-8

This text seems to be for students
that are right out of high school
with very little computer experience,
if any at all. The authors seem to
have more experience with teaching
Pascal as a first language.

C : How To Program. 2e.
Deitel & Deitel.
Prentice Hall, 1996.
ISBN 0-13-226119-7

This text seems to be a little more
advanced than the Hanly text. I like
the projects. Here again, the authors
have a background teaching Pascal.

King's textbook has an errata page on the
Internet, plus, he is accessible by email,
not hiding behind a publisher. I noticed
that several of the errata were attributed
to you, Mr. Seebach. I find King's textbook
to be much better than either of the other
two I mentioned. He is really treating the
C language very thoroughly.

Now, if I can simplify...
KISS = Keep It Small and Simple.

--
Kenneth W. Melvin

http://www.geocities.com/SiliconValley/8823/index.html
The best thing about Linux is the people who use it!!!

Tue, 11 Jan 2000 03:00:00 GMT
feedforward: learning C

Quote:
>(
> (i < j) ? -1 : (
> (i == j) ? 0 : 1)
>)

>But I find nested ternary operators unpleasant to read, even when there's
>only one level of nesting.  That's just personal preference, not advice.

That depends partly on how you write them. I find something of the form:

(i < j)
? -1
: (i == j)
? 0
: 1

roughly follows the form of nested ifs and quickly becomes easy to follow.
This example is a bit straggly because the individual subexpressions are
so small but it shows the general form. Another grouping which shows nesting
better is:

(i >= j)
? (i == j)
? 0
: 1
: -1

--
-----------------------------------------

-----------------------------------------

Wed, 12 Jan 2000 03:00:00 GMT

 Page 1 of 2 [ 17 post ] Go to page: [1] [2]

Relevant Pages