home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_200
/
252_01
/
chap04.txt
< prev
next >
Wrap
Text File
|
1990-02-14
|
32KB
|
764 lines
Chapter 4
ASSIGNMENT & LOGICAL COMPARES
Throughout this chapter, references are given to various
ranges of variables. Your compiler may use a different range
for some of the variables since the ANSI standard does not
define specific limits for all data types. Consult the
documentation for your compiler for the exact range for each
of the variable types.
INTEGER ASSIGNMENT STATEMENTS
____________________________________________________________
Load the file INTASIGN.C and display it for ==============
an example of assignment statements. Three INTASIGN.C
variables are defined for use in the program ==============
and the rest of the program is merely a
series of illustrations of various
assignments. The first two lines of the assignment statements
assign numerical values to the variables named a and b, and
the next five lines illustrate the five basic arithmetic
functions and how to use them. The fifth is the modulo
operator and gives the remainder if the two variables were
divided. It can only be applied to int or char type
variables. Following these, there are two lines illustrating
how to combine some of the variables in some complex math
expressions. All of the above examples should require no
comment except to say that none of the equations are meant to
be particularly useful except as illustrations. The char type
variable will be defined in the description of the next
example program.
The expressions in lines 17 and 18 are perfectly acceptable
as given, but we will see later in this chapter that there is
another way to write these for more compact code.
VERY STRANGE LOOKING CODE
____________________________________________________________
This leaves us with the last two lines which may appear to you
as being very strange. The C compiler scans the assignment
statement from right to left, (which may seem a bit odd since
we do not read that way), resulting in a very useful
construct, namely the one given here. The compiler finds the
value 20, assigns it to c, then continues to the left finding
that the latest result of a calculation should be assigned to
b. Thinking that the latest calculation resulted in a 20, it
assigns it to b also, and continues the leftward scan
assigning the value 20 to a also. This is a very useful
construct when you are initializing a group of variables. The
last statement illustrates that it is possible to actually do
Page 4-1
Chapter 4 - Assignments and Logical Compares
some calculations to arrive at the value which will be
assigned to all three variables. In fact, the rightmost
expression can contain variables, even a, b, & c.
The program has no output, so compiling and executing this
program will be very uninteresting. Since you have already
learned how to display some integer results using the printf()
function, it would be to your advantage to add some output
statements to this program to see if the various statements
do what you think they should do.
DEFINITIONS FIRST THEN EXECUTABLE STATEMENTS
____________________________________________________________
This would be a good time for a preliminary definition of a
rule to be followed in C. The variable definitions are always
given before any executable statements in any program block.
This is why the variables are defined first in this program
and in every C program. If you try to define a new variable
after executing some statements, your compiler will issue an
error.
ADDITIONAL DATA TYPES
____________________________________________________________
Loading and editing MORTYPES.C will ===============
illustrate how some additional data types can MORETYPES.C
be used. Once again we have defined a few ===============
integer type variables which you should be
fairly familiar with by now, but we have
added two new types, the char, and the float.
The char type of data is nearly the same as the integer except
that it can only be assigned numerical values between -128 to
127 on most implementations of C, since it is stored in only
one byte of memory. The char type of data is usually used for
ASCII data, more commonly known as text. The text you are
reading was originally written on a computer with a word
processor that stored the words in the computer one character
per byte. In contrast, the integer data type is stored in two
bytes of computer memory on nearly all microcomputers.
DATA TYPE MIXING
____________________________________________________________
It would be profitable at this time to discuss the way C
handles the two types char and int. Most functions in C that
are designed to operate with integer type variables will work
equally well with character type variables because they are
a form of an integer variable. Those functions, when called
on to use a char type variable, will actually promote the char
Page 4-2
Chapter 4 - Assignments and Logical Compares
data into integer data before using it. For this reason, it
is possible to mix char and int type variables in nearly any
way you desire. The compiler will not get confused, but you
might. It is good not to rely on this too much, but to
carefully use only the proper types of data where they should
be used.
The second new data type is the float type of data, commonly
called floating point data. This is a data type which usually
has a very large range, a large number of significant digits,
and a large number of computer words are required to store it.
The float data type has a decimal point associated with it and
has an allowable range of from 3.4E-38 to 3.4E+38 when using
most C compilers on microcomputers, and is composed of about
7 significant digits.
HOW TO USE THE NEW DATA TYPES
____________________________________________________________
The first three lines of the program assign values to all nine
of the defined variables so we can manipulate some of the data
between the different types.
Since, as mentioned above, a char data type is in reality an
integer data type, no special considerations need be taken to
promote a char to an int, and a char type data field can be
assigned to an int variable. When going the other way, there
is no standard, so you may simply get garbage if the value of
the integer variable is outside the range of the char type
variable. Most C compilers simply truncate the most
significant bits and use the 8 least significant bits. It
will translate correctly if the value is within the range of
-128 to 127.
The third line illustrates the simplicity of translating an
integer into a float, simply assign it the new value and the
system will do the proper conversion. When going the other
way however, there is an added complication. Since there may
be a fractional part of the floating point number, the system
must decide what to do with it. By definition, it will
truncate it.
This program produces no output, and we haven't covered a way
to print out char and float type variables, so you can't
really get in to this program and play with the results, but
the next program will cover this for you.
Be sure to compile and run this program after you are sure you
understand it completely.
Page 4-3
Chapter 4 - Assignments and Logical Compares
LOTS OF VARIABLE TYPES
____________________________________________________________
Load the file LOTTYPES.C and display it on ==============
your screen. This file contains nearly every LOTTYPES.C
standard simple data type available in the ==============
programming language C. There are other
types, but they are the compound types (ie -
arrays and structures) that we will cover in due time.
Observe the file. First we define a simple int, followed by
a long int which has a range of -2147483648 to 2147483647 with
most C compilers, and a short int which has a range that is
identical to that for the int variable, namely -32768 to
32767. The unsigned is next and is defined as the same size
as the int but with no sign. The unsigned then will cover a
range of 0 to 65535. It should be pointed out that when the
long, short, or unsigned is desired, the int is optional and
is left out by most experienced programmers. We have already
covered the char and the float, which leaves only the double.
The double is a floating point number but covers a greater
range than the float and has more significant digits for more
precise calculations. It also requires more memory to store
a value than the simple float. The double in most C compilers
covers a range of 1.7E-308 to 1.7E+308.
Note that other compounding of types can be done such as long
unsigned int, unsigned char, etc. Check your documentation
for a complete list of variable types.
Another diversion is in order at this point. Your compiler
may have no provision for floating point math, only double
floating point math. It will promote a float to a double
before doing calculations and therefore only one math library
will be needed. Of course, this is transparent to you, so you
don't need to worry about it. Because of this, you may think
that it would be best to simply define every floating point
variable as double, since they are promoted before use in any
calculations, but that may not be a good idea. A float
variable requires 4 bytes of storage and a double requires 8
bytes of storage, so if you have a large volume of floating
point data to store, the double will obviously require much
more memory.
After defining the data types in the program under
consideration, a numerical value is assigned to each of the
defined variables in order to demonstrate the means of
outputting each to the monitor.
Page 4-4
Chapter 4 - Assignments and Logical Compares
SOME LATE ADDITIONS
____________________________________________________________
As any programming language evolves, additional constructs are
added to fill some previously overlooked need. Two new
keywords have been added to C recently, and since they may not
be a part of your compiler, they are not illustrated in
example programs, but they will be discussed here. The two
new keywords are const and volatile and are used to tell the
compiler that variables of these types will need special
consideration. A constant is declared with the const keyword
and declares a value that will never be changed by either the
program or the system itself. If volatile is used, it
declares a value that may be changed by the program but it may
also be changed by some outside influence such as a clock
update pulse incrementing the stored value. Since constants
can never have a value assigned to them in the executable part
of the program, they should always be initialized.
Examples of use in declaring constants of these two types are
given as;
const int index1 = 2;
const index2 = 6;
volatile const int index3 = 12;
volatile index4;
As mentioned earlier in this chapter, the keyword int is
optional when used with these constant definitions
THE CONVERSION CHARACTERS
____________________________________________________________
Following is a list of some of the conversion characters and
the way they are used in the printf() statement. A complete
list of all of the conversion characters should be included
with the documentation for your compiler.
d decimal notation
i decimal notation (new ANSI standard extension)
o octal notation
x hexadecimal notation
u unsigned notation
c character notation
s string notation
f floating point notation
Page 4-5
Chapter 4 - Assignments and Logical Compares
Each of these is used following a percent sign to indicate the
type of output conversion, and between those two characters,
the following fields may be added.
- left justification in its field
(n) a number specifying minimum field width
. to separate n from m
(m) significant fractional digits for a float
l to indicate a long
These are all used in the examples which are included in the
program LOTTYPES.C, with the exception of the string notation
which will be covered later in this tutorial. Note especially
the variable field width specification demonstrated in lines
33 to 36. This is not part of the original definition of C,
but it is included in the ANSI standard and has become part
of the C language. Compile and run this program to see what
effect the various fields have on the output.
You now have the ability to display any of the data fields in
the previous programs and it would be to your advantage to go
back and see if you can display some of the fields anyway you
desire.
COMBINING THE VARIOUS TYPES
____________________________________________________________
Examine the file named COMBINE.C for =============
examples of combining variables of the COMBINE.C
various types in a program. Many times it =============
is necessary to multiply an int type
variable times a float type variable and C
allows this by giving a strict set of rules it will follow in
order to do such combinations.
Five variables of three different types are declared in lines
4 through 6, and three of them are initialized so we have some
data to work with. Line 8 gives an example of adding an int
variable to a float variable and assigning the result to a
char type variable. The cast is used to control the type
addition and is indicated by putting the desired type in front
of the variable as shown. This forces each of the two
variables to the character type prior to doing the addition.
In some cases, when the cast is used, the actual bit patterns
must be modified internally in order to do the type coercion.
Lines 9 through 11 perform the same operation by using
different kinds of type casting to achieve the final result.
Lines 13 through 15 illustrate the use of the cast to multiply
two float variables. In two of the cases the intermediate
results are cast to the int type, with the result being cast
back to the float type. The observant student will notice
Page 4-6
Chapter 4 - Assignments and Logical Compares
that all three lines will not necessarily produce the same
result.
Be sure to compile and execute this program.
LOGICAL COMPARES
____________________________________________________________
Load and view the file named COMPARES.C for ==============
many examples of compare statements in C. We COMPARES.C
begin by defining and initializing nine ==============
variables to use in the following compare
statements. This initialization is new to
you and can be used to initialize variables when they are
defined.
The first group of compare statements represents the simplest
kinds of compares since they simply compare two variables.
Either variable could be replaced with a constant and still
be a valid compare, but two variables is the general case.
The first compare checks to see if the value of x is equal to
the value of y and it uses the double equal sign for the
comparison. A single equal sign could be used here but it
would have a different meaning as we will see shortly. The
second comparison checks to see if the value of x is greater
than the value of z.
The third compare introduces the not operator, the
exclamation, which can be used to invert the result of any
logical compare. The fourth checks for the value of b less
than or equal to the value of c, and the last checks for the
value of r not equal to the value of s. As we learned in the
last chapter, if the result of the compare is true, the
statement following the if clause will be executed and the
results are given in the comments.
Note that "less than" and "greater than or equal to" are also
available, but are not illustrated here.
It would be well to mention the different format used for the
if statement in this example program. A carriage return is
not required as a statement separator and by putting the
conditional clause on the same line as the if, it adds to the
readability of the overall program in this case.
MORE COMPARES
____________________________________________________________
The compares in the second group are a bit more involved.
Starting with the first compare, we find a rather strange
looking set of conditions in the parentheses. To understand
this we must understand just what a true or false is in the
Page 4-7
Chapter 4 - Assignments and Logical Compares
C language. A false is defined as a value of zero, and true
is defined as a non-zero value. Any integer or character type
of variable can be used for the result of a true/false test,
or the result can be an implied integer or character.
Look at the first compare of the second group of compare
statements. The expression "r != s" will evaluate as a true
since the value of r was set to 0.0 in line 13, so the result
will be a non-zero value. With most C compilers, it would
always be set to a 1, but you could get in trouble if you
wrote a program that depended on it being 1 in all cases.
Good programming practice would be to not use the resulting
1 in any calculations. Even though the two variables that are
compared are float variables, the result will be of type
integer. There is no explicit variable to which it will be
assigned so the result of the compare is an implied integer.
Finally the resulting number, probably 1 in this case, is
assigned to the integer variable x. If double equal signs
were used, the phantom value, namely 1, would be compared to
the value of x, but since the single equal sign is used, the
value 1 is simply assigned to the variable named x, as though
the statement were not in parentheses. Finally, since the
result of the assignment in the parentheses was non-zero, the
entire expression is evaluated as true, and z is assigned the
value of 1000. Thus we accomplished two things in this
statement, we assigned x a new value, probably 1, and we
assigned z the value of 1000. We covered a lot in this
statement so you may wish to review it before going on. The
important things to remember are the values that define true
and false, and the fact that several things can be assigned
in a conditional statement. The value assigned to the
variable x was probably a 1, but remember that the only
requirement is that it is nonzero.
The example in line 20 should help clear up some of the above
in your mind. In this example, x is assigned the value of y,
and since the result is 11, the condition is non-zero, which
is true, and the variable z is assigned 222.
The third example of the second group in line 21, compares the
value of x to zero. If the result is true, meaning that if
x is not zero, then z is assigned the value of 333, which it
will be. The last example in this group illustrates the same
concept, since the result will be true if x is non-zero. The
compare to zero in line 21 is not actually needed and the
result of the compare is true. The third and fourth examples
of this group are therefore identical.
ADDITIONAL COMPARE CONCEPTS
____________________________________________________________
The third group of compares will introduce some additional
concepts, namely the logical and and the logical or operators.
Page 4-8
Chapter 4 - Assignments and Logical Compares
We assign the value of 77 to the three integer variables
simply to get started again with some defined values. The
first compare of the third group contains the new control &&,
which is the logical and which results in a true if both sides
of the and are true. The entire statement reads, if x equals
y and if x equals 77 then the result is true. Since this is
true, the variable z is set equal to 333.
The next compare in this group introduces the || operator
which is the logical or operator which results in a true if
either side of the or is true. The statement reads, if x is
greater than y or if z is greater than 12 then the result is
true. Since z is greater than 12, it doesn't matter if x is
greater than y or not, because only one of the two conditions
must be true for the result to be true. The result is true,
so therefore z will be assigned the value of 22.
LOGICAL EVALUATION (SHORT CIRCUIT)
____________________________________________________________
When a compound expression is evaluated, the evaluation
proceeds from left to right and as soon as the result of the
outcome is assured, evaluation stops. Namely, in the case of
an "and" evaluation, when one of the terms evaluates to false,
evaluation is discontinued because additional true terms
cannot make the result ever become true. In the case of an
"or" evaluation, if any of the terms is found to be true,
evaluation stops because it will be impossible for additional
terms to cause the result to be false. In the case of
additionally nested terms, the above rules will be applied to
each of the nested levels. This is called short-circuit
evaluation since the remaining terms are not evaluated.
PRECEDENCE OF OPERATORS
____________________________________________________________
The question will come up concerning the precedence of
operators. Which operators are evaluated first and which
last? There are many rules about this topic, but I would
suggest that you don't worry about it at this point. Instead,
use lots of parentheses to group variables, constants, and
operators in a way meaningful to you. Parentheses always have
the highest priority and will remove any question of which
operations will be done first in any particular statements.
Going on to the next example in group three in line 29, we
find three simple variables used in the conditional part of
the compare. Since all three are non-zero, all three are
true, and therefore the and of the three variables are true,
leading to the result being true, and z being assigned the
value of 11. Note that since the variables, r, s, and t are
float type variables, they could not be used this way, but
Page 4-9
Chapter 4 - Assignments and Logical Compares
they could each be compared to zero and the same type of
expression could be used.
Continuing on to line 30 we find three assignment statements
in the compare part of the if statement. If you understood
the above discussion, you should have no difficulty
understanding that the three variables are assigned their
respective new values, and the result of all three are
non-zero, leading to a resulting value of true.
THIS IS A TRICK, BE CAREFUL
____________________________________________________________
The last example of the third group contains a bit of a trick,
but since we have covered it above, it is nothing new to you.
Notice that the first part of the compare evaluates to false.
The remaining parts of the compare are not evaluated, because
it is a logical and so it will definitely be resolved as a
false because the first term is false. If the program was
dependent on the value of y being set to 3 in the next part
of the compare, it will fail because evaluation will cease
following the false found in the first term. Likewise, the
variable named z will not be set to 4, and the variable r will
not be changed.
POTENTIAL PROBLEM AREAS
____________________________________________________________
The last group of compares illustrate three possibilities for
getting into a bit of trouble. All three have the common
result that the variable z will not get set to the desired
value, but for different reasons. In line 37, the compare
evaluates as true, but the semicolon following the second
parentheses terminates the if clause, and the assignment
statement involving z is always executed as the next
statement. The if therefore has no effect because of the
misplaced semicolon. This is actually a null statement and
is legal in C.
The statement in line 38 is much more straightforward because
the variable x will always be equal to itself, therefore the
inequality will never be true, and the entire statement will
never do a thing, but is wasted effort. The statement in line
39 will always assign 0 to x and the compare will therefore
always be false, never executing the conditional part of the
if statement.
The conditional statement is extremely important and must be
thoroughly understood to write efficient C programs. If any
part of this discussion is unclear in your mind, restudy it
until you are confident that you understand it thoroughly
Page 4-10
Chapter 4 - Assignments and Logical Compares
before proceeding onward. Compile and run this program. Add
some printout to see the results of some of the operations.
THE CRYPTIC PART OF C
____________________________________________________________
There are three constructs used in C that =============
make no sense at all when first encountered CRYPTIC.C
because they are not intuitive, but they =============
greatly increase the efficiency of the
compiled code and are used extensively by
experienced C programmers. You should therefore be exposed
to them and learn to use them because they will appear in
most, if not all, of the programs you see in the publications.
Load and examine the file named CRYPTIC.C for examples of the
three new constructs.
In this program, some variables are defined and initialized
in the same statements for use later. The statement in line
8 simply adds 1 to the value of x, and should come as no
surprise to you. The next two statements also add one to the
value of x, but it is not intuitive that this is what happens.
It is simply by definition that this is true. Therefore, by
definition of the C language, a double plus sign either before
or after a variable increments that variable by 1.
Additionally, if the plus signs are before the variable, the
variable is incremented before it is used, and if the plus
signs are after the variable, the variable is used, then
incremented. In line 11, the value of y is assigned to the
variable z, then y is incremented because the plus signs are
after the variable y. In the last statement of the
incrementing group of example statements, line 12, the value
of y is incremented then its value is assigned to the variable
z.
The next group of statements illustrate decrementing a
variable by one. The definition works exactly the same way
for decrementing as it does for incrementing. If the minus
signs are before the variable, the variable is decremented,
then used, and if the minus signs are after the variable, the
variable is used, then decremented.
THE CRYPTIC ARITHMETIC OPERATOR
____________________________________________________________
Another useful but cryptic operator is the arithmetic
operator. This operator is used to modify any variable by
some constant value. The statement in line 23 simply adds 12
to the value of the variable a. The statement in line 24 does
the same, but once again, it is not intuitive that they are
the same. Any of the four basic functions of arithmetic, +,
-, *, or /, can be handled in this way, by putting the
Page 4-11
Chapter 4 - Assignments and Logical Compares
function desired in front of the equal sign and eliminating
the second reference to the variable name. It should be noted
that the expression on the right side of the arithmetic
operator can be any valid expression, the examples are kept
simple for your introduction to this new operator.
Just like the incrementing and decrementing operators, the
arithmetic operator is used extensively by experienced C
programmers and it would pay you well to understand it.
THE CONDITIONAL EXPRESSION
____________________________________________________________
The conditional expression is just as cryptic as the last two,
but once again it can be very useful so it would pay you to
understand it. It consists of three expressions within
parentheses separated by a question mark and a colon. The
expression prior to the question mark is evaluated to
determine if it is true or false. If it is true, the
expression between the question mark and the colon is
evaluated, and if it is not true, the expression following the
colon is evaluated. The result of the evaluation is used for
the assignment as illustrated in line 30. The final result
is identical to that of an if statement with an else clause.
This is illustrated by the example in lines 32 through 35 of
this group of statements. The conditional expression has the
added advantage of more compact code that will compile to
fewer machine instructions in the final program.
Lines 37 and 38 of this example program are given to
illustrate a very compact way to assign the greater of the two
variables a or b to c, and to assign the lessor of the same
two variables to c. Notice how efficient the code is in these
two examples.
TO BE CRYPTIC OR NOT TO BE CRYPTIC
____________________________________________________________
Several students of C have stated that they didn't like these
three cryptic constructs and that they would simply never use
them. This will be fine if they never have to read anybody
else's program, or use any other programs within their own.
I have found many functions that I wished to use within a
program but needed a small modification to use it, requiring
me to understand another person's code. It would therefore
be to your advantage to learn these new constructs, and use
them. They will be used in the remainder of this tutorial, so
you will be constantly exposed to them.
This has been a long chapter but it contained important
material to get you started in using C. In the next chapter,
we will go on to the building blocks of C, the functions. At
Page 4-12
Chapter 4 - Assignments and Logical Compares
that point, you will have enough of the basic materials to
allow you to begin writing meaningful programs.
PROGRAMMING EXERCISES
____________________________________________________________
1. Write a program that will count from 1 to 12 and print
the count, and its square, for each count.
1 1
2 4
3 9 etc.
2. Write a program that counts from 1 to 12 and prints the
count and its inversion to 5 decimal places for each
count. This will require a floating point number.
1 1.00000
2 .50000
3 .33333
4 .25000
etc.
3. Write a program that will count from 1 to 100 and print
only those values between 32 and 39, one to a line.
Page 4-13