Showing posts with label arithmatic. Show all posts
Showing posts with label arithmatic. Show all posts

Tuesday, September 21, 2010

Nested switch Statements

You can have a switch as part of the statement sequence of an outer switch. Even if the
case constants of the inner and outer switch contain common values, no conflicts arise.
For example, the following code fragment is perfectly acceptable:
switch(x) {
case 1:
switch(y) {
case 0: printf("Divide by zero error.\n");
break;
case 1: process(x,y);
}
break;
case 2:
.
.
.

Selection Statements if and switch

C/C++ supports two types of selection statements: if and switch. In addition, the ?
operator is an alternative to if in certain circumstances.
if
The general form of the if statement is
if (expression) statement;
else statement;
where a statement may consist of a single statement, a block of statements, or nothing
(in the case of empty statements). The else clause is optional.
If expression evaluates to true (anything other than 0), the statement or block that
forms the target of if is executed; otherwise, the statement or block that is the target of
else will be executed, if it exists. Remember, only the code associated with if or the
code associated with else executes, never both.
In C, the conditional statement controlling if must produce a scalar result. A scalar
is either an integer, character, pointer, or floating-point type. In C++, it may also be of
type bool. It is rare to use a floating-point number to control a conditional statement
because this slows execution time considerably. (It takes several instructions to perform
a floating-point operation. It takes relatively few instructions to perform an integer or
character operation.)
The following program contains an example of if. The program plays a very simple
version of the "guess the magic number" game. It prints the message ** Right ** when
the player guesses the magic number. It generates the magic number using the
standard random number generator rand() , which returns an arbitrary number
between 0 and RAND_MAX (which defines an integer value that is 32,767 or larger).
rand() requires the header file stdlib.h. (A C++ program may also use the new-style
header <cstdlib>.)
/* Magic number program #1. */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int magic; /* magic number */
int guess; /* user's guess */
magic = rand(); /* generate the magic number */
printf("Guess the magic number: ");
scanf("%d", &guess);
if(guess == magic) printf("** Right **");
return 0;
}
Taking the magic number program further, the next version illustrates the use of
the else statement to print a message in response to the wrong number.
/* Magic number program #2. */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int magic; /* magic number */
int guess; /* user's guess */
magic = rand(); /* generate the magic number */
printf("Guess the magic number: ");
scanf("%d", &guess);
if(guess == magic) printf("** Right **");
else printf("Wrong");
return 0;
}

Nested ifs
A nested if is an if that is the target of another if or else. Nested ifs are very common
in programming. In a nested if, an else statement always refers to the nearest if
statement that is within the same block as the else and that is not already associated
with an else. For example,

if(i)
{
if(j) statement 1;
if(k) statement 2; /* this if */
else statement 3; /* is associated with this else */
}
else statement 4; /* associated with if(i) */
As noted, the final else is not associated with if(j) because it is not in the same block.
Rather, the final else is associated with if(i). Also, the inner else is associated with if(k),
which is the nearest if.
Standard C specifies that at least 15 levels of nesting must be supported. In practice,
most compilers allow substantially more. More importantly, Standard C++ suggests
that at least 256 levels of nested ifs be allowed in a C++ program. However, nesting
beyond a few levels is seldom necessary, and excessive nesting can quickly confuse the
meaning of an algorithm.
You can use a nested if to further improve the magic number program by
providing the player with feedback about a wrong guess.
/* Magic number program #3. */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int magic; /* magic number */
int guess; /* user's guess */
magic = rand(); /* get a random number */
printf("Guess the magic number: ");
scanf("%d", &guess);
if (guess == magic) {
printf("** Right **");
printf(" %d is the magic number\n", magic);
}
else {
printf("Wrong, ");
if(guess > magic) printf("too high\n");
else printf("too low\n");
}
return 0;
}
The if-else-if Ladder
A common programming construct is the if-else-if ladder, sometimes called the if-else-if
staircase because of its appearance. Its general form is
if (expression) statement;
else
if (expression) statement;
else
if (expression) statement;
..
.
else statement;
The conditions are evaluated from the top downward. As soon as a true condition is
found, the statement associated with it is executed and the rest of the ladder is
bypassed. If none of the conditions are true, the final else is executed. That is, if all
other conditional tests fail, the last else statement is performed. If the final else is not
present, no action takes place if all other conditions are false.
Although the indentation of the preceding if-else-if ladder is technically correct, it
can lead to overly deep indentation. For this reason, the if-else-if ladder is generally
indented like this:
if (expression)
statement;
else if (expression)
statement;
else if (expression)
statement;
.
..
else
statement;
Using an if-else-if ladder, the magic number program becomes
/* Magic number program #4. */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int magic; /* magic number */
int guess; /* user's guess */
magic = rand(); /* generate the magic number */
printf("Guess the magic number: ");
scanf("%d", &guess);
if(guess == magic) {
printf("** Right ** ");
printf("%d is the magic number", magic);
}
else if(guess > magic)
printf("Wrong, too high");
else printf("Wrong, too low");
return 0;
}
The ? Alternative
You can use the ? operator to replace if-else statements of the general form:
if(condition) expression;
else expression;
However, the target of both if and else must be a single expression—not another
statement.
The ? is called a ternary operator because it requires three operands. It takes the
general form
Exp1 ? Exp2 : Exp3
where Exp1, Exp2, and Exp3 are expressions. Notice the use and placement of the colon.
The value of a ? expression is determined as follows: Exp1 is evaluated. If it is true,
Exp2 is evaluated and becomes the value of the entire ? expression. If Exp1 is false, then
Exp3 is evaluated and its value becomes the value of the expression. For example,
consider x = 10;
y = x>9 ? 100 : 200;
In this example, y is assigned the value 100. If x had been less than 9, y would have
received the value 200. The same code written with the if-else statement would be
x = 10;
if(x>9) y = 100;
else y = 200;
The following program uses the ? operator to square an integer value entered by
the user. However, this program preserves the sign (10 squared is 100 and −10 squared
is −100).
#include <stdio.h>
int main(void)
{
int isqrd, i;
printf("Enter a number: ");
scanf("%d", &i);
isqrd = i>0 ? i*i : -(i*i);
printf("%d squared is %d", i, isqrd);
return 0;
}
The use of the ? operator to replace if-else statements is not restricted to
assignments only. Remember, all functions (except those declared as void) may return
a value. Thus, you can use one or more function calls in a ? expression. When the
function's name is encountered, the function is executed so that its return value may be
determined. Therefore, you can execute one or more function calls using the ? operator
by placing the calls in the expressions that form the ?'s operands. Here is an example.
#include <stdio.h>
int f1(int n);
int f2(void);
int main(void)
{
int t;
printf("Enter a number: ");
scanf("%d", &t);
/* print proper message */
t ? f1(t) + f2() : printf("zero entered.\n");
return 0;
}
int f1(int n)
{
printf("%d ", n);
return 0;
}
int f2(void)
{
printf("entered.\n");
return 0;
}
Entering a 0 in this example calls the printf() function and displays the message zero
entered. If you enter any other number, both f1() and f2() execute. Note that the value
of the ? expression is discarded in this example. You don't need to assign it to anything.
A word of warning: Some C++ compilers rearrange the order of evaluation of an
expression in an attempt to optimize the object code. This could cause functions that
form the operands of the ? operator to execute in an unintended sequence.
Using the ? operator, you can rewrite the magic number program yet again.
/* Magic number program #5. */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int magic;
int guess;
magic = rand(); /* generate the magic number */
printf("Guess the magic number: ");
scanf("%d", &guess);
if(guess == magic) {
printf("** Right ** ");
printf("%d is the magic number", magic);
}
else
guess > magic ? printf("High") : printf("Low");
return 0;
}
Here, the ? operator displays the proper message based on the outcome of the test
guess > magic.

Shorthand Assignments

There is a variation on the assignment statement, sometimes referred to as a shorthand
assignment, that simplifies the coding of a certain type of assignment operation. For
example,
x = x+10;
can be written as
x += 10;
The operator += tells the compiler to assign to x the value of x plus 10.
This shorthand works for all the binary operators (those that require two
operands). In general, statements like:
var = var operator expression
can be rewritten as
var operator = expression
For another example,
x = x-100;
is the same as
x -= 100;
Shorthand notation is widely used in professionally written C/C++ programs; you
should become familiar with it.

Type Casts in C C++

You can force an expression to be of a specific type by using a cast. The general form of
a cast is
(type) expression
where type is a valid data type. For example, to make sure that the expression x/2
evaluates to type float, write
(float) x/2
Casts are technically operators. As an operator, a cast is unary and has the same
precedence as any other unary operator.
Although casts are not usually used a great deal in programming, they can be very
useful when needed. For example, suppose you wish to use an integer for loop control,
yet to perform computation on it requires a fractional part, as in the following
program:
#include <stdio.h>
int main(void) /* print i and i/2 with fractions */
{
int i;
for(i=1; i<=100; ++i)
printf("%d / 2 is: %f\n", i, (float) i /2);
return 0;
}
Without the cast (float), only an integer division would have been performed. The cast
ensures that the fractional part of the answer is displayed.

Expressions in C C++

Operators, constants, and variables are the constituents of expressions. An expression in
C/C++ is any valid combination of these elements. Because most expressions tend to
follow the general rules of algebra, they are often taken for granted. However, a few
aspects of expressions relate specifically to C and C++.

Order of Evaluation
Neither C nor C++ specifies the order in which the subexpressions of an expression are
evaluated. This leaves the compiler free to rearrange an expression to produce more
optimal code. However, it also means that your code should never rely upon the order
in which subexpressions are evaluated. For example, the expression
x = f1() + f2();
does not ensure that f1() will be called before f2() .

Type Conversion in Expressions
When constants and variables of different types are mixed in an expression, they are
all converted to the same type. The compiler converts all operands up to the type of
the largest operand, which is called type promotion. First, all char and short int values
are automatically elevated to int. (This process is called integral promotion.) Once this
step has been completed, all other conversions are done operation by operation, as
described in the following type conversion algorithm:
IF an operand is a long double
THEN the second is converted to long double
ELSE IF an operand is a double
THEN the second is converted to double
ELSE IF an operand is a float
THEN the second is converted to float
ELSE IF an operand is an unsigned long
THEN the second is converted to unsigned long
ELSE IF an operand is long
THEN the second is converted to long
ELSE IF an operand is unsigned int
THEN the second is converted to unsigned int

The [ ] and ( ) Operators

Parentheses are operators that increase the precedence of the operations inside them.
Square brackets perform array indexing (arrays are discussed fully in Chapter 4).
Given an array, the expression within square brackets provides an index into that
array. For example,
#include <stdio.h>
char s[80];
int main(void)
{
s[3] = 'X';
printf("%c", s[3]);
return 0;
}
first assigns the value 'X' to the fourth element (remember, all arrays begin at 0) of
array s, and then prints that element.

The Compile-Time Operator sizeof

sizeof is a unary compile-time operator that returns the length, in bytes, of the variable
or parenthesized type-specifier that it precedes. For example, assuming that integers
are 4 bytes and doubles are 8 bytes,
double f;
printf("%d ", sizeof f);
printf("%d", sizeof(int));
will display 8 4.
Remember, to compute the size of a type, you must enclose the type name in
parentheses. This is not necessary for variable names, although there is no harm done
if you do so.

C/C++ defines (using typedef) a special type called size_t, which corresponds
loosely to an unsigned integer. Technically, the value returned by sizeof is of type
size_t. For all practical purposes, however, you can think of it (and use it) as if it were
an unsigned integer value.
sizeof primarily helps to generate portable code that depends upon the size of the
built-in data types. For example, imagine a database program that needs to store six
integer values per record. If you want to port the database program to a variety of
computers, you must not assume the size of an integer, but must determine its actual
length using sizeof. This being the case, you could use the following routine to write a
record to a disk file:
/* Write 6 integers to a disk file. */
void put_rec(int rec[6], FILE *fp)
{
int len;
len = fwrite(rec, sizeof(int)*6, 1, fp);
if(len != 1) printf("Write Error");
}
Coded as shown, put_rec() compiles and runs correctly in any environment, including
those that use 16- and 32-bit integers.
One final point: sizeof is evaluated at compile time, and the value it produces is
treated as a constant within your program.

The & and * Pointer Operators

A pointer is the memory address of some object. A pointer variable is a variable that is
specifically declared to hold a pointer to an object of its specified type. Knowing a
variable's address can be of great help in certain types of routines. However, pointers
have three main functions in C/C++. They can provide a fast means of referencing
array elements. They allow functions to modify their calling parameters. Lastly,
they support linked lists and other dynamic data structures. Chapter 5 is devoted
exclusively to pointers. However, this chapter briefly covers the two operators that
are used to manipulate pointers.
The first pointer operator is &, a unary operator that returns the memory address of
its operand. (Remember, a unary operator only requires one operand.) For example,
m = &count;
places into m the memory address of the variable count. This address is the computer's
internal location of the variable. It has nothing to do with the value of count. You can
think of & as meaning "the address of." Therefore, the preceding assignment statement
means "m receives the address of count."
To better understand this assignment, assume that the variable count is at memory
location 2000. Also assume that count has a value of 100. Then, after the previous
assignment, m will have the value 2000.
The second pointer operator is *, which is the complement of &. The * is a unary
operator that returns the value of the variable located at the address that follows it. For
example, if m contains the memory address of the variable count,
q = *m;
places the value of count into q. Now q has the value 100 because 100 is stored at
location 2000, the memory address that was stored in m. Think of * as meaning
"at address." In this case, you could read the statement as "q receives the value at
address m."
Unfortunately, the multiplication symbol and the "at address" symbol are the
same, and the symbol for the bitwise AND and the "address of" symbol are the same.
These operators have no relationship to each other. Both & and * have a higher
precedence than all other arithmetic operators except the unary minus, with which
they share equal precedence.
Variables that will hold memory addresses (i.e., pointers), must be declared by
putting * in front of the variable name. This indicates to the compiler that it will hold a
pointer. For example, to declare ch as a pointer to a character, write
char *ch;
Here, ch is not a character but a pointer to a character—there is a big difference. The
type of data that a pointer points to, in this case char, is called the base type of the
pointer. However, the pointer variable itself is a variable that holds the address to an
object of the base type. Thus, a character pointer (or any pointer) is of sufficient size
to hold an address as defined by the architecture of the computer that it is running on.
However, remember that a pointer should only point to data that is of that pointer's
base type.
You can mix both pointer and nonpointer variables in the same declaration
statement. For example,
int x, *y, count;
declares x and count as integer types and y as a pointer to an integer type.
The following program uses * and & operators to put the value 10 into a variable
called target. As expected, this program displays the value 10 on the screen.
#include <stdio.h>
int main(void)
{
int target, source;
int *m;
source = 10;
m = &source;
target = *m;
printf("%d", target);
return 0;
}

The ? Operator Conditional or ternary operator

C/C++ contains a very powerful and convenient operator that replaces certain
statements of the if-then-else form. The ternary operator ? takes the general form
Exp1 ? Exp2 : Exp3;
where Exp1, Exp2, and Exp3 are expressions. Notice the use and placement of the colon.
The ? operator works like this: Exp1 is evaluated. If it is true, Exp2 is evaluated
and becomes the value of the expression. If Exp1 is false, Exp3 is evaluated and its
value becomes the value of the expression. For example, in
x = 10;
y = x>9 ? 100 : 200;
y is assigned the value 100. If x had been less than 9, y would have received the value
200. The same code written using the if-else statement is
x = 10;
if(x>9) y = 100;
else y = 200;
The ? operator will be discussed more fully in Chapter 3 in relationship to the other
conditional statements.

Arithmetic Operators

Table 2-4 lists C/C++'s arithmetic operators. The operators +, −, *, and / work as they
do in most other computer languages. You can apply them to almost any built-in data
type. When you apply / to an integer or character, any remainder will be truncated.
For example, 5/2 will equal 2 in integer division.
The modulus operator % also works in C/C++ as it does in other languages,
yielding the remainder of an integer division. However, you cannot use it on
floating-point types. The following code fragment illustrates %:
int x, y;
x = 5;
y = 2;
printf("%d ", x/y); /* will display 2 */
printf("%d ", x%y); /* will display 1, the remainder of
the integer division */
x = 1;
y = 2;
printf("%d %d", x/y, x%y); /* will display 0 1 */
The last line prints a 0 and a 1 because 1/2 in integer division is 0 with a remainder of 1.
The unary minus multiplies its operand by –1. That is, any number preceded by a
minus sign switches its sign.

Increment and Decrement
C/C++ includes two useful operators not generally found in other computer
languages. These are the increment and decrement operators, ++ and −−. The operator
++ adds 1 to its operand, and −− subtracts one. In other words:
x = x+1;
is the same as
++x;
and
x = x-1;
is the same as
x--;
Both the increment and decrement operators may either precede (prefix) or follow
(postfix) the operand. For example,
x = x+1;
can be written
++x;
or
x++;
There is, however, a difference between the prefix and postfix forms when you use
these operators in an expression. When an increment or decrement operator precedes
its operand, the increment or decrement operation is performed before obtaining the
value of the operand for use in the expression. If the operator follows its operand,
 
Operator                             Action
−                             Subtraction, also unary minus
+                                          Addition
*                                       Multiplication
/                                           Division
%                                        Modulus
– –                                     Decrement
++                                      Increment

Table 2-4. Arithmetic Operators

the value of the operand is obtained before incrementing or decrementing it. For
instance,
x = 10;
y = ++x;
sets y to 11. However, if you write the code as
x = 10;
y = x++;
y is set to 10. Either way, x is set to 11; the difference is in when it happens.
Most C/C++ compilers produce very fast, efficient object code for increment and
decrement operations—code that is better than that generated by using the equivalent
assignment statement. For this reason, you should use the increment and decrement
operators when you can.
Here is the precedence of the arithmetic operators:
highest ++ – –
– (unary minus)
* / %
lowest + –
Operators on the same level of precedence are evaluated by the compiler from left to
right. Of course, you can use parentheses to alter the order of evaluation. C/C++ treats
parentheses in the same way as virtually all other computer languages. Parentheses
force an operation, or set of operations, to have a higher level of precedence.

Relational and Logical Operators
In the term relational operator, relational refers to the relationships that values can
have with one another. In the term logical operator, logical refers to the ways these
relationships can be connected. Because the relational and logical operators often
work together, they are discussed together here.
The idea of true and false underlies the concepts of relational and logical operators.
In C, true is any value other than zero. False is zero. Expressions that use relational or
logical operators return 0 for false and 1 for true.
C++ fully supports the zero/non-zero concept of true and false. However, it also
defines the bool data type and the Boolean constants true and false. In C++, a 0 value
is automatically converted into false, and a non-zero value is automatically converted
into true. The reverse also applies: true converts to 1 and false converts to 0. In C++,

the outcome of a relational or logical operation is true or false. But since this
automatically converts into 1 or 0, the distinction between C and C++ on this issue is
mostly academic.
Table 2-5 shows the relational and logical operators. The truth table for the logical
operators is shown here using 1's and 0's.
p             q               p && q                 p || q               !p
0             0                    0                          0                 1
0             1                    0                          1                1
1             1                    1                          1                0
1             0                    0                          1                0
Both the relational and logical operators are lower in precedence than the
arithmetic operators. That is, an expression like 10 > 1+12 is evaluated as if it were
written 10 > (1+12). Of course, the result is false.
You can combine several operations together into one expression, as shown here:
10>5 && !(10<9) || 3<=4

Relational Operators
Operator                     Action
>                               Greater than
>=                        Greater than or equal
<                               Less than
<=                       Less than or equal
= =                               Equal
!=                                Not equal

Logical Operators
Operator                       Action
&&                                AND
||                                      OR
!                                     NOT

Table 2-5. Relational and Logical Operators

In this case, the result is true.
Although neither C nor C++ contain an exclusive OR (XOR) logical operator, you
can easily create a function that performs this task using the other logical operators.
The outcome of an XOR operation is true if and only if one operand (but not both) is
true. The following program contains the function xor() , which returns the outcome of
an exclusive OR operation performed on its two arguments:
#include <stdio.h>
int xor(int a, int b);
int main(void)
{
printf("%d", xor(1, 0));
printf("%d", xor(1, 1));
printf("%d", xor(0, 1));
printf("%d", xor(0, 0));
return 0;
}
/* Perform a logical XOR operation using the
two arguments. */
int xor(int a, int b)
{
return (a || b) && !(a && b);
}
The following table shows the relative precedence of the relational and logical
operators:
Highest
!
> >= < <=
== !=
&&
Lowest
  ||

As with arithmetic expressions, you can use parentheses to alter the natural order of
evaluation in a relational and/or logical expression. For example, 

!0&& 0 || 0
is false. However, when you add parentheses to the same expression, as shown here,
the result is true:
!(0 && 0) || 0
Remember, all relational and logical expressions produce either a true or false
result. Therefore, the following program fragment is not only correct, but will print
the number 1.
int x;
x = 100;
printf("%d", x>10);