See reading notes for Chapter 1 for discussion of the purpose of these reading notes.
Chapter 4 contains eleven lessons (L4.1 through L4.11) covering if/else,
relational expressions, logical expressions and operators, the switch statement,
while loops, and for loops.
There are also eight Application Programs (AP4.1
through AP4.8) demonstrating these features in the context of complete working
programs that solve real mathematics or engineering problems.
We will cover all of the material in Chapter 4.
A few things you need to pay special attention to in this section:
= and == in C?== with double or float, and what you
should do instead.A couple of additional points:
= and == that
"you will cause serious errors in your programs". This is true,
but a bit more explanation may be helpful here.
if (x = 0)
printf("x is zero\n")
else
printf("a / x = %lf", a/x);
What will be the result of this code exactly? First, it is important to understand that there is no compiler error. The result of doing an if test on the expression (x = 0) is the following:
Clearly, the intent of the programmer was to prevent division by zero, but instead, he/she has ensured that division by zero is the only possible result!
if (x = 2)
printf("x is two; the expression cannot be evaluated\n")
else
printf("a / (2 - x) = %lf", a/(2 - x));
what will be the result exactly in this case?
Again, there is no compiler error. if test on the expression
(x
=
2)
is the following:
Clearly, the intent of the programmer was to prevent division by zero, and she/he surely accomplished that, but not in they manner he/she intended!
and
the C symbol != which is the relational operator for not-equals.
Be sure that when
you write out programs on exams or quizzes that you always use the != symbol,
and never the math symbol. Similarly, even for hand-written C code always
use <=
and >=,
never
or
(which
are fine for pseudocode, but never for C program code.)The following script session illustrates this:
> cat fabsTest.c
/* program to test compiling with fabs (floating pt absolute value ) */
/* P. Conrad, for CISC105, Fall 2004 */
#include <stdio.h>
int main (void)
{
double x = -1.23;
printf("fabs(x) = %lf\n", fabs(x));
return 0;
}
> cat fabsTest1.c
/* program to test compiling with fabs (floating pt absolute value ) */
/* P. Conrad, for CISC105, Fall 2004 */
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
double x = -1.23;
printf("fabs(x) = %lf\n", fabs(x));
return 0;
}
> cat fabsTest2.c
/* program to test compiling with fabs (floating pt absolute value ) */
/* P. Conrad, for CISC105, Fall 2004 */
#include <stdio.h>
#include <math.h>
int main (void)
{
double x = -1.23;
printf("fabs(x) = %lf\n", fabs(x));
return 0;
}
> cc fabsTest.c
Undefined first referenced
symbol in file
fabs fabsTest.o
ld: fatal: Symbol referencing errors. No output written to a.out
> cc fabsTest.c -lm
> ./a.out
fabs(x) = 1.230000
> gcc fabsTest.c
fabsTest.c: In function `main':
fabsTest.c:10: warning: type mismatch in implicit declaration for built-in function `fabs'
> gcc fabsTest1.c
fabsTest1.c: In function `main':
fabsTest1.c:11: warning: type mismatch in implicit declaration for built-in function `fabs'
> gcc fabsTest2.c
> ./a.out
fabs(x) = 1.230000
>
|
This section covers if/else, as well as the ternary operator. An important section to read. Just one comment: consider the statement on p. 178: "Note that, for the unevaluated expression [in the ternary operator], no side effects occur".
Let's call this the "no side effects" rule. Can you think of an example where the "no side effects" rule would apply? What do the authors mean by "side effects"? As an example, consider the output of the following program would be when the input is 1, and when the input is 2:
> cat ternarySideEffect.c
// ternarySideEffect.c P. Conrad for CISC105, Fall 2004
// A silly program that does nothing useful, but illustrates
// some rules of the C programming language.
#include <stdio.h>
int main(void)
{
int x;
int a = 10, b = 20;
int c;
printf("Enter 1 or 2 > ");
scanf("%d", &x);
c = (x < 2) ? a++ : b++;
printf("a=%d b=%d c=%d\n",a, b, c);
return 0;
}
> make ternarySideEffect
cc -o ternarySideEffect ternarySideEffect.c
> ./ternarySideEffect
Enter 1 or 2 > 1
a=11 b=20 c=10
> ./ternarySideEffect
Enter 1 or 2 > 2
a=10 b=21 c=20
>
|
Understanding how to next if/else control structures is important, so read this section carefully.
A comment: this section shows the proper indentation of if/else control structures. This is very important. If you get in the habit of properly indenting your if/else control structures, you will avoid many mistakes.
This lesson covers logical expressions. Be sure that you always use && and
|| to mean and and or, respectively. There is also a single & and
single | operator in C, however these mean "bit-wise-and" and "bitwise-or" which
are different. They may seem to work the same for many cases, but they do not
work the same in all cases.
The not operator (!) can frequently be overlooked by a programmer reading your code, and it is sometimes better to avoid it. DeMorgan's rules can be useful for eliminating the ! operator. In C they are expressed as follows:
!( x ||
y) is the same as (!x) && (!y)!(x && y) is the same as (!x) || (!y)For example, the expressions on the left are equal to the ones on the right. But which is easier to read?
!((x == 0) && (y == 0)) |
(x!=0) || (y!=0) |
!((x>0) || (y>0)) |
(x>=0) && (y>=0) |
This section covers operator precedence of logical operators, but it also covers treating variables as logical values (e.g. int a=4; ... if (a) printf(...)). Be sure you don't miss this important point!
This lesson introduces the switch statement as an alternative to the if/else construct.
One thing to be careful of in the switch statement is to be sure that every switch case ends in a break statement (unless you really want to fall through to the next case.) If you do want to fall through to the next case, you should definitely put in a comment indicating that you "meant" to do that.
Don't interpret my lack of detailed comments on these sections as a signal that these sections aren't important. On the contrary: they are very important, and very well written. Be sure you read over these sections carefully, and understand each of the forms of while loops and for loops (both simple and nested).
Actually, section 4.11 is the only one where I'm a little disappointed; I would like to have seen some coverage of using nested for loops to produce two dimensional tables such as the one on this web page: http://www.nws.noaa.gov/om/windchill/index.shtml
Here's an example program that produces a multiplication table such as the one that you might find in a 3rd or 4th grade classroom. Perhaps that can give you an idea of how a table like the one on the web site above might be produced using nested for loops:
> cat multTable.c
/* multTable.c Produce 2D multiplication table using nested loops */
/* P. Conrad for CISC105, Fall 2004 */
/* result should look like this:
+---++---+---+---+---+...
| x || 1| 2| 3| 4|
+===++===+===+===+===+...
| 1|| 1| 2| 3| 4|
+---++---+---+---+---+...
| 2|| 2| 4| 6| 8|
+---++---+---+---+---+...
| 3|| 3| 6| 9| 12|
... etc. */
#define LIMIT 10 /* Limit of how far the table goes up.
Could be changed to 12, for example */
#include <stdio.h>
void printLineAcross(void)
{
/* print a line like this one,
+---++---+---+---+---+...
with limit + 1 columns */
int i;
printf("+---++");
for (i=1; i<=LIMIT; i++)
printf("---+");
printf("\n");
return;
}
/* note: we could do better by creating one function printLineAcross,
and passing in the character to use, either '-' or '='. Please accept
this invitation to do that as an exercise */
void printDoubleLineAcross(void)
{
/* print a line like this one,
+===++===+===+===+===+...
with limit + 1 columns */
int i;
printf("+===++");
for (i=1; i<=LIMIT; i++)
printf("===+");
printf("\n");
return;
}
int main(void)
{
int i,j; /* loop indices */
/* print header row */
printLineAcross();
printf("| x ||");
for (i=1; i<=LIMIT; i++)
printf("%3d|", i);
printf("\n");
printDoubleLineAcross();
/* print the main table */
for (i=1; i<=LIMIT; i++)
{
/* print the first cell that labels the row */
printf("|%3d||", i);
/* fill in the row with the rest of the entries*/
for (j=1; j<=LIMIT; j++)
{
printf("%3d|", i * j); /* prints the actual multiplication entry */
}
printf("\n"); /* finish off the row */
printLineAcross();
}
/* Done! */
return 0;
}
> make multTable
cc -o multTable multTable.c
> ./multTable
+---++---+---+---+---+---+---+---+---+---+---+
| x || 1| 2| 3| 4| 5| 6| 7| 8| 9| 10|
+===++===+===+===+===+===+===+===+===+===+===+
| 1|| 1| 2| 3| 4| 5| 6| 7| 8| 9| 10|
+---++---+---+---+---+---+---+---+---+---+---+
| 2|| 2| 4| 6| 8| 10| 12| 14| 16| 18| 20|
+---++---+---+---+---+---+---+---+---+---+---+
| 3|| 3| 6| 9| 12| 15| 18| 21| 24| 27| 30|
+---++---+---+---+---+---+---+---+---+---+---+
| 4|| 4| 8| 12| 16| 20| 24| 28| 32| 36| 40|
+---++---+---+---+---+---+---+---+---+---+---+
| 5|| 5| 10| 15| 20| 25| 30| 35| 40| 45| 50|
+---++---+---+---+---+---+---+---+---+---+---+
| 6|| 6| 12| 18| 24| 30| 36| 42| 48| 54| 60|
+---++---+---+---+---+---+---+---+---+---+---+
| 7|| 7| 14| 21| 28| 35| 42| 49| 56| 63| 70|
+---++---+---+---+---+---+---+---+---+---+---+
| 8|| 8| 16| 24| 32| 40| 48| 56| 64| 72| 80|
+---++---+---+---+---+---+---+---+---+---+---+
| 9|| 9| 18| 27| 36| 45| 54| 63| 72| 81| 90|
+---++---+---+---+---+---+---+---+---+---+---+
| 10|| 10| 20| 30| 40| 50| 60| 70| 80| 90|100|
+---++---+---+---+---+---+---+---+---+---+---+
>
|
You might try changing the #define (constant macro) to make the table be a 12 by 12 table, or changing it so that the limit value is a variable entered by the user.
All of these are definitely worth looking over. I particularly want to recommend that you look at exercise 4.7, which solves quadratic equations (for both real and imaginary numbers).
The following exercises are definitely recommended, and are certainly fair game for exam questions:
All of the application exercises are good practice for you. A few of them may show up i your labs/projects. You are advised to look over the others, as they might make an appearance (in simplified form) as exam questions.
(end of reading notes for Chapter 4).
These reading notes are based on C Programming for Engineering and Computer Science, by H. H. Tan and T. B. D'Orazio, Copyright 1999 by WCB McGraw-Hill. The notes themselves are Copyright 2004, by Phillip T. Conrad, All Rights Reserved.
Prof. Conrad takes sole responsibility for any views or opinions expressed in these notes. Such view and opinions do necessarily reflect those of the University of Delaware, its Department of Computer and Information Sciences, or any other organization.