1. Trang chủ
  2. » Công Nghệ Thông Tin

c for engineers and scientists introduction to programming with ansi c phần 9 pdf

67 938 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề The And Operator
Trường học Standard University
Chuyên ngành Computer Science
Thể loại Bài báo
Năm xuất bản 2023
Thành phố City Name
Định dạng
Số trang 67
Dung lượng 2,72 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

For example, the statement enum day a,b,c; declares the variables a, b,and c to be of type day,and is consistent with thedeclaration of variables using standard C data types such as char

Trang 1

13.1 The AND Operator

Program 13-2 uses this masking property to convert lowercase letters in ~

word into their its uppercase form, assuming the letters are stored using the

ASCII code The algorithm for converting letters is based on the fact that the

binary codes for lowercase and uppercase letters in ASCIIare the same except for

bit 6, which is 1 for lowercase letters and 0 for uppercase letters For example, the

binary code for the letter a is 01100001 (hex 61), while the binary code for the

letter A is 01000001 (hex 41) Similarly, the binary code for the letter z is

01111 010 (hex 7A), while the binary code for the letter Z is 01011 010 (hex SA),

(See Appendix F for the hexadecimal values of the uppercase and lowercase let~

ters.) Thus, a lowercase letter can be converted into its uppercase form by forcing

the sixth bit to zero This is accomplished in Program 13-2by masking the letter's

code with the binary value 11011111, which has the hexadecimal value OF

}Ol, Program 13-2

#include <stdio.h>

main( )

{

char word[81]; /* enough storage for a complete line */

void upper(char *); /* function prototype */

*word++ &= OXDF;

A sample run using Program 13-2follows:

Enter a string of both upper and lowercase letters:

Trang 2

Notice that the lowercase letters are converted to uppercase form, whileuppercase letters are unaltered This is because bit 6 of all uppercase letters iszero to begin with, so that forcing this bit to zero using the mask has no effect.Only when bit 6 is a one, as it is for lowercase letters, is the input characteraltered.

13.2 The Inclusive OR Operator

The inclusive OR operator, I, performs a bit-by-bit comparison of its twooperands in a fashion similar to the bit-by-bit AND The result of the OR compar-ison, however, is determined by the following rule:

The result of the comparison is 1 if either bit being compared is a 1, wise the result is a O

other-Figure 13-2 illustrates an OR operation As shown in the figure, when either

of the two bits being compared is a 1, the result is a 1, otherwise the result is a O

As with all bit operations, the result of each comparison is, of course, dent of any other comparison

indepen-Program 13-3 illustrates an OR operation, using the octal values of theoperands illustrated in Figure 13-2

Jql, Program 13-3

#include <stdio.h>

main( )

{

int op1 = 0325, op2 = 0263;

printf("%o ORed with %0 is %0",op1, op2, op1 I op2);

Program 13-3 produces the following output:

325 ORed with 263 is 367The result of ORing the octal numbers 325 and 263 is the octal number 367.The binary equivalent of 367 is 1 1 1 1 0 1 1 1, which is the result of the ORoperation illustrated in Figure 13-2

Inclusive OR operations are extremely useful in forcing selected bits to take

on a 1 value or for passing through other bit values unchanged This is a directresult of the fact that ORing any bit (l or0)with a 1 forces the resulting bit to be a

1, while ORing any bit (l or 0) with a a leaves the original bit unchanged For

Trang 3

13.2 The Inclusive OR Operator

1 0 1 1 0 0 1 1

1 1 0 1 0 101

111 1 0 1 1 1

FIGURE 13-2 A Sample OR Operation

example, assume that the variable opl has the arbitrary bit pattern x x x x x

x x x, where each x can be either 1 or 0, independent of any other x in the

num-ber The result of ORing this binary number with the binary number 1 1 1 1 0

As can be seen from this example, the ones in op2 force the resulting bits to 1,

while the zeros in op2 filter, or pass, the respective bits in opl through with no

change in their values Thus, using an OR operation a masking operation similar;

to an AND operation can be produced, except the masked bits are set to ones

rather than cleared to zeros Another way of looking at this is to say that ORing

with a zero has the same effect as ANDing with a one

Program 13-4 uses this masking property to convert uppercase letters in a

Trang 4

word into their respective lowercase form, assuming the letters are stored usingthe ASCII code The algorithm for converting letters is similar to that used inProgram 13-2 It converts uppercase letters into their lowercase form by forcingthe sixth bit in each letter to a one This is accomplished in Program 13-4 bymasking the letter's code with the binary value 00100000, which has the hex-adecimal value 20.

A sample run using Program 13-4 follows:

Enter a string of both upper and lowercase letters: abcdefgHIJKLMNOPqrstuvwxyz

The string of letters just entered is:

abcdefgHIJKLMNOPqrstuvwxyz This string in lowercase letters is:

abcdefghijklrnnopqrstuvwxyzNotice that the uppercase letters are converted to lowercase form, while low-ercase letters are unaltered This is because bit 6 of all lowercase letters is one tobegin with, so that forcing this bit to one using the mask has no effect Onlywhen bit 6 is a zero, as it is for uppercase letters, is the input character altered

13.3 The Exclusive OR Operator

The exclusive OR operator, A, performs a bit-by-bit comparison of its twooperands The result of the comparison is determined by the following rule:The result of the comparison is 1 if one and only one of the bits being com-pared is a I, otherwise the result is O

Figure 13-3 illustrates an exclusive OR operation As shown in the figure,when both bits being compared are the same value (both 1 or both 0), the result is

a zero Only when both bits have different values (one bit a 1 and the other a 0) isthe result a 1 Again, each pair or bit comparison is independent of any other bitcomparison

An exclusive OR operation can be used to create the opposite value, or plement, of any individual bit in a variable This is a direct result of the fact thatexclusive ORing any bit (1 or 0) with a 1 forces the resulting bit to be of the oppo-site value of its original state, while exclusive ORing any bit (1 or 0) with a a

com-leaves the original bit unchanged For example, assume that the variable op1has

FIGURE 13-3 A Sample Exclusive OR Operation

1 0 1 1 0 0 1 1

~ 1 1 0 1 0 1 0 1

o 1 1 0 0 110

Trang 5

13.3 The Exclusive OR Operator

the arbitrary bit pattern x x x x x x x x, where each x can be either 1 or 0,

independent of any other x in the number Using the notation that x is the com~

plement (opposite) value of x, the result of exclusive ORing this binary numbe~

523

oplop2Result

x x x x x x x x

o 1 0 1 010 1-

x x x x x x x x

As can be seen from this example, the ones in op2 force the resulting bits to

be the complement of their original bit values, while the zeros in op2 filter, or

pass, the respective bits in opl through with no change in their values

Many encryption methods use the exclusive OR operation to code data For

example, the string Hello there world! initially used in Program 1-1 can be

encrypted by exclusive ORing each character in the string with a mask value of

52 The choice of the mask value, which is referred to as the encryption key, is

arbitrary Any key value can be used

Program 13-5uses an encryption key of 52 to code a user-entered message

void encrypt (char *);

/* enough storage for a complete ltne *//* function prototype*/

Trang 6

-The sentence just entered is:

Good morning The encrypted version of this sentence is:

s[[P Y[FZ]ZS

Note that the encrypted version appears to have fewer characters This is due

to the non-printable codes contained within the encrypted version Decoding anencrypted message requires exclusive GRing the coded message using the origi-nal encryption key, which is left as a homework exercise

13.4 The Complement Operator

The complement operator, -, is a unary operator that changes each 1 bit in itsoperand to a and each a bit to 1 For example, if the variable op1 contains thebinary number 11001010, -op1.replaces this binary number with the number

0011 0101 The complement operator is used to force any bit in an operand tozero, independent of the actual number of bits used to store the number Forexample, the statement

op1 op1 & -07;

or its shorter form,

op1 &= -07;

both set the last three bits of op1 to zero, regardless of how op1 is stored withinthe computer Either of these two statements can, of course, be replaced byANDing the last three bits of op1 with zeros, if the number of bits used to storeop1 is known In a computer that uses 16 bits to store integers, the appropriateAND operation is:

op1 = op1 & 0177770;

For a computer that uses 32 bits to store integers, the above AND sets the most or higher order 16 bits to zero also, which is an unintended result The cor-rect statement for 32 bits is:

left-op1 = op1 & 037777777770;

Using the complement operator in this situation frees the programmer fromhaving to determine the storage size of the operand and, more importantly,makes the program portable between machines using different integer storagesizes

Trang 7

13.5 Different Size Data Items

13.5 Different-Size Data Items

When the bit operators &, I, and" are used with operands of different sizes, the

shorter operand is always increased in bit size to match the size of the larger

operand Figure 13-4 illustrates the extension of a 16-bit unsigned integer into a

As the figure shows, the additional bits are added to the left of the original

number and filled with zeros This is the equivalent of adding leading zeros to

the number, which has no effect on the number's value

When extending signed numbers, the original leftmost bit is reproduced in

the additional bits that are added to the number As illustrated in Figure 13-5, if

FIGURE 13-4 Extending 16-Bit Unsigned Data to 32 Bits

16 bits

A.

r - -,

A sign bit of 0 OXXXXXXXXXXXXXXX either 1 or 0

16 zeros The original 16 bits

Trang 8

the original leftmost bit is 0, corresponding to a positive number, 0 is placed ineach of the additional bit positions If the leftmost bit is 1, which corresponds to anegative number, 1 is placed in the additional bit positions In either case, theresulting binary number has the same sign and magnitude as the original number.

13.6 The Shift Operators

The left shift operator, «, causes the bits in an operand to be shifted to the left

by a given amount For example, the statement

op1 = op1 « 4;

causes the bits in op1 to be shifted four bits to the left, filling any vacated bitswith a zero Figure 13-6 illustrates the effect of shifting the binary number

1111100010101011 to the left by four bit positions

For unsigned integers, each left shift corresponds to multiplication by 2 This isalso true for signed numbers using two's complement representation, as long asthe leftmost bit does not switch values Since a change in the leftmost bit of a two'scomplement number represents a change in both the sign and magnitude repre-sented by the bit, such a shift does not represent a simple multiplication by 2.The right shift operator, », causes the bits in an operand to be shifted to theright by a given amount For example, the statement

For unsigned numbers, the leftmost bit is not used as a sign bit For this type

of number, the vacated leftmost bits are always filled with zeros This is the casethat is illustrated in Figure 13-7a

For signed numbers, what is filled in the vacated bits depends on the

comput-er Most computers reproduce the original sign bit of the numbcomput-er Figure 13-7b

FIGURE 13-{j An Example of a Left Shift

Each bit is shifted to the leftbythe designated number of places

VVacated bit positionsare filledwithzeros

Trang 9

13.6 The Shift Operators

•• Each bit is shifted to the right by

the designated number of places

••

527

Vacated bit positions

are filled with zeros

FIGURE 13-7a An Unsigned Arithmetic Right Shift

The sign bit is a 1

+

••

v

Vacated bit positions

are filled with 1s

Each bit is shifted to the right by the designated number of places

••

FIGURE 13-7b The Right Shift of a Negative Binary Number

The sign bit is a zero

+

••

V

Vacated bit positions

are filled with Os

Each bit is shifted to the right by the designated number of places

••

FIGURE 13-7c The Right Shift of a Positive Binary Number

Trang 10

illustrates the right shift of a negative binary number by four bit positions, wherethe sign bit is reproduced in the vacated bits Figure 13-7c illustrates the equiva-lent right shift of a positive signed binary number.

The type of fill illustrated in Figures 13-7b and c, where the sign bit is duced in vacated bit positions, is called an arithmetic right shift In an arithmeticright shift, each single shift to the right corresponds to a division by 2

repro-Instead of reproducing the sign bit in right-shifted signed numbers, somecomputers automatically fill the vacated bits with zeros This type of shift iscalled a logical shift For positive signed numbers, where the leftmost bit is zero,both arithmetic and logical right shifts produce the same result The results ofthese two shifts are different only when negative numbers are involved

Exercises for Chapter 13

1 Determine the results of the following operations:

a. 11001010 b. 11001010 c 11001010

& 10100101 I 10100101 A 10100101

2 Write the octal representations of the binary numbers given in Exercise 1.

3 Determine the octal results of the following operations, assuming unsigned numbers:

a the octal number 0157 shifted left by one bit position

b the octal number 0701 shifted left by two bit positions

c the octal number 0673 shifted right by two bit positions

d the octal number 067 shifted right by three bit positions

4 Repeat Exercise 3 assuming that the numbers are treated as signed values.

5a Assume that the arbitrary bit pattern xxxxxxxx, where each x can represent either 1

or 0, is stored in the integer variable flag Determine the octal value of a mask that can

be ANDed with the bit pattern to reproduce the third and fourth bits of flag and set all other bits to zero The rightmost bit in flag is considered bit zero.

b Determine the octal value of a mask that can be inclusively ORed with the bit pattern

in flag to reproduce the third and fourth bits of flag and set all other bits to one Again, consider the rightmost bit in flag to be bit zero.

c Determine the octal value of a mask that can be used to complement the values of the

third and fourth bits of flag and leave all other bits unchanged Determine the bit operation that should be used with the mask value to produce the desired result.

6a Write the two's complement form of the decimal number -1, using eight bits (Hint:

Refer to Section 1.7 for a review of two's complement numbers.)

b. Repeat Exercise 6a using 16 bits to represent the decimal number -1 and compare your answer to your previous answer Could the 16-bit version have been obtained by sign-extending the 8-bit version?

7 As was noted in the text, Program 13-2 has no effect on uppercase letters Using the ASCII codes listed in Appendix F, determine what other characters would be unaffected

by Program 13-2.

8 Modify Program 13-2 so that a complete sentence can be read in and converted to

lowercase values (Hint: When a space is masked by Program 13-2, the resulting character

is \0, which terminates the output.)

9 Modify Program 13-4 to allow a complete sentence to be input and converted to uppercase letters Make sure that your program does not alter any other characters or symbols entered.

Trang 11

13.7 Chapter Summary

10 Modify Program 13-5 to permit the encryption key to be a user-entered input value.

'11 Modify Program 13-5 to have its output written to a file named coded.dat.

12 Write a C program that reads the encrypted file produced by the program written for

Exercise 10, decodes the file, and prints the decoded values.

13 Write a C program that displays the first eight bits of each character value input into a

variable named ch (Hint:Assuming each character is stored using eight bits, start by

using the hexadecimal mask 80, which corresponds to the binary number 10000000 If

the result of the masking operation is a zero, display a zero; else display a one Then shift

the mask one place to the right to examine the next bit, and so on until all bits in the

variable ch have been processed.)

14 Write a C program that reverses the bits in an integer variable named okay and stores

the reversed bits in the variable named rev_okay For example, if the bit pattern

11100101, corresponding to the octal number 0345, is assigned to okay, the bit pattern

10100111, corresponding to the octal number 0247, should be produced and stored in

rev_okay.

1 Individual bits of character and integer variables and constants can be

manipulated using C's bit operators These are the AND, inclusive OR,

exclusive OR, one's complement, left shift, and right shift operators

2 The AND and inclusive OR operators are useful in creating masks These

masks can be used to pass or eliminate individual bits from the selected

operand The exclusive OR operator is useful in complementing an operand's

bits

'3 When the AND and OR operators are used with operands of different sizes,

the shorter operand is always increased in bit size to match the size of the

larger operand

4 The shift operators produce different results depending on whether the

operand is a signed or an unsigned value

529

Trang 12

Command Line ArgumentsThe goto StatementChapter Summary

Chapter Fourteen

Trang 13

14.1 Expressions Revisited

Previous chapters presented C's basic capabilities and structure The variations

on these capabilities, which are almost endless, are a source of delight to many

programmers who continuously find new possibilities of expression using

varia-tions of the basic language building blocks This chapter presents some of these

additional capabilities

14.1 Expressions Revisited

One of the most common pitfalls in C results from misunderstanding the full

implications of an expression Recall that an expression is any combination of

operands and operators that yields a result This definition is extremely broad

and more encompassing than is initially apparent For example, all of the

follow-ing are valid C expressions:

a + 5

a = b

a == b

a = b = c = 6flag = a == bAssuming that the variables are suitably declared, each of the above expres-

sions yields a result Program 14-1 uses the printf ( )function to display the

value of the first three expressions for specific initial values of the variables a

printf("\nThe value of the first expression is %d", a + 5);

printf("\nThe value of the second expression is %d", a == b); printf("\nThe value of the third expression is %d", a = b );

The display produced by Program 14-1 is:

The value of the first expression is 12

The value of the second expression is 0

The value of the third expression is 10

As the output of Program 14-1 illustrates, each expression, by itself, has a

value associated with it The value of the first expression is the sum of the

vari-531

Trang 14

able a plus 5, which is 12 The value of the second expression is zero, since a isnot equal to b, and a false condition is represented in C with a value of zero Ifthe values in a and b had been the same, the conditional expression a = = bwould be true and would have a value of 1 The value of the third expression is

10, which is also assigned to the variable a

In this section we will review the rules for evaluating expressions with ple operators and "mixed" operands of different data types We will also intro-duce a new expression type and C operator

multi-Expressions containing multiple operators are always evaluated by the

priori-ty, or precedence, of each operator Table E-l in Appendix E lists the relative ority of each C operator and its associativity

pri-Even when the order of evaluation is known, expressions with multiple ators can still produce unusual and undesired results, remaining a potential trapfor the unwary For example, consider the statement

oper-flag = a == bi

Consulting Table E-l we see that the == operator has a higher precedencethan the = operator Therefore, a is first compared to b If a is equal to b, theresult of the expression a == b is 1, otherwise it is O.The value of this expres-sion is then assigned to flag. Thus, the variable flag will have either a value of

1 or a value of 0 after the statement is executed A problem arises if the sion is inadvertently typed as flag = a = b Here, the value of b is firstassigned to a,which is then assigned to flag. Because of the mistake of typing

expres-an equal operator instead of the comparison operator, flag is assigned the value

of b, rather than the 1 or 0 that was intended

The real problem with the statement flag = a == bi is that it has beenused in place of the more obvious and complete statement

if (a b) flag 1i

else flag ai

Although the same error can be made in substituting an equal operator forthe comparison operator in this statement, the error can be detected more easilythan in the more obscure expression flag = a == b

Because of the generality of C expressions and the fact that most sequences ofoperands connected by operators can be evaluated to produce a result (including

an unintended one), it is extremely important to be careful in creating' sions To avoid undesired results and to make program checking, testing, anddebugging easier, keep expressions as simple and as uncomplicated as possible.Generally expressions using arithmetic operators (+, -, *, /, %,etc.) should not bemixed with expressions using relational and logical operators (==, <, >, &&, I I,etc.), which, in turn, should not be mixed with expressions using bit operators(&, I,etc.)

expres-Finally, although Table E-l appears to be all-inclusive, it is not In particular,the order of evaluations for operands is not specified, as it is not specified inmost computer languages For example, in the expression a + b it is not knownwhich operand is accessed first Generally this is not a problem because the order

of operand access doesn't affect the result of the expression However, in sions such as:

Trang 15

expres-14.1 Expressions Revisited

(val[i]) + (i++)

the order of access is important Here the subscript may be either the old or the

new value of i, depending on which operand is accessed first

Similarly, the order of evaluation of function arguments is not specified in C

Thus, the function call

printf("%d %d", i, i++);

may result in the same number being printed twice if the second argument is

evaluated before the first argument

Expressions that depend on the order of operand access should always be

avoided, because they can produce different results on different computers Such

expressions can always be replaced with temporary variables that explicitly

define the desired evaluation order For example, the statements

n = ++i;

printf("%d %d", i, n);

clearly indicate the values that are passed to the print f ( ) function

Conditional Expressions

In addition to expressions formed with the arithmetic, relational, logical, and bit

operators, C provides a conditional expression A conditional expression uses the

conditional operator, ? : It provides an alternate way of expressing a simple

The general form of a conditional expression is:

expressionl ? expression2 : expression3

If the value of expressionl is nonzero (true), expression2 is evaluated,

otherwise expression3 is evaluated The value for the complete conditional

expression is the value of either expression2 or expression3, depending on

which expression was evaluated As always, the value of the expression may be

Conditional expressions are most useful in replacing simple if - e 1s e

state-ments For example, the if-else statement

if ( hours> 40)rate 045;

Trang 16

operator, ?:, has a higher precedence than the assignment operator Within theconditional expression, the expression hours > 40 is evaluated first If thisexpression has a nonzero value, which is equivalent to a logical true value, thevalue of the complete conditional expression is set to .045; otherwise the condi-tional expression has a value of 02 Finally, the value of the conditional expres-sion, either .045 or.02,is assigned to the variable rate.

The conditional operator, ?:, is unique in C in that it is a ternary operator.This means that the operator connects three operands The first operand isalways evaluated first It is usually a conditional expression that uses the logicaloperators The next two operands are any other valid expressions, which can besingle constants, variables, or more general expressions The complete condition-

al expression consists of all three operands connected by the conditional operatorsymbols, ?and :

Conditional expressions are only useful in replacing if - e 1s e statementswhen the expressions in the equivalent if-else statements are not long or com-plicated For example, the statement

max_val = a > b ? a : b;

is a one-line statement that assigns the maximum value of the variables a and b

to max_val A longer, equivalent form of this statement is:

if (a > b)max_val a;

elsemax_val b;

Because of the length of the expressions involved, a conditional expressionwould not be useful in replacing the following if - e 1s e statement:

if (amoun t > 2 0000 )taxes 025(amount - 20000) + 400;

elsetaxes 02 * amount;

Exercises 14.1

1 Evaluate the following expressions Assume that all variables are integers and that a has a value of 2, b has a yalue of 3, c has a value of 4, and d has a value of 5 before each expression is evaluated.

Trang 17

14.2 User Specified Data types

2 Whichof the expressionsin Exercise1 should not be included in a program?Why?

3 Rewritethe statement a = b = c = amount * rate; as a seriesof three individual

assignmentstatements

4 Rewritethe followingstatementsas if-else statements:

a. flag = a >= b;

b. flag = a == b I I c == d;

5 Rewritethe statementsin Exercise4 using conditionalexpressions

6 Rewriteeach of the followingif-else statementsusing a conditionalexpression:

14.2 User-Specified Data Types

In this section we present two user-specified data types The first permits a user

to create new data types Since the creation of a data type requires the

program-mer to specifically list or enuprogram-merate the values appropriate to the data type, these

data types are referred to as enumerated data types The second capability allows

the programmer to create new names for existing data types

Enumerated Data Types

An enumerated data type is a user-created data type in which the values

appro-priate to the data type are specified in a user-defined list Such data types are

identified by the reserved word enum followed by an optional, user-selected

name for the data type and a listing of acceptable values for the data type

Consider the following user-specified data types:

enum flag {true, false};

enum time {am, pm};

enum day {man, tue, wed, thr, fri, sat, sun};

enum color {red, green, yellow};

535

Trang 18

The first user-specified data type is the type flag.Any variable subsequentlydeclared to be of this type can take on only a value of true or false The secondstatement creates a data type named time.Any variable subsequently declared

to be of type time can take on only a value ofam orpm.Similarly, the third andfourth statements create the data types day and color,respectively, and list thevalid values for variables of these two types For example, the statement

enum day a,b,c;

declares the variables a, b,and c to be of type day,and is consistent with thedeclaration of variables using standard C data types such as char, int, float,

ordouble.Once variables have been declared as enumerated types, they may beassigned values or compared to variables or values appropriate to their type.This again is consistent with standard variable operations For example, for thevariables a, b, and cdeclared above, the following statements are valid:

a = red;

b = a;

if (c == yellow) printf("\nThe color is yellow");

Internally, the acceptable values for each enumerated data type are orderedand assigned sequential integer values beginning with O For example, for thevalues of the user-defined type color, the correspondences created by the Ccompiler are that red is equivalent to 0,green is equivalent to I, and yellow isequivalent to 2 The equivalent numbers are required when inputting valuesusing scanf ( )or printing values using printf ( ).Program 14-2 illustrates auser-defined data type

Jql, Program 14-2

#include <stdio.h>

main( )

{

enum color {red,green,yellow};

enum color crayon = red; /* crayon is declared to be of type */

/* color and initialized to red */ printf ("\nThe color is %d", crayon);

printf("\nEnter in a value: ");

scanf("%d", &crayon);

if (crayon == red)

printf("The crayon is red.");

else if (crayon == green)

printf("The crayon is green.");

else if (crayon == yellow)

printf ("The crayon is"'yellow ") ;

else

printf("The color is not defined.");

Trang 19

14.2 User Specified Data types

A sample run of Program 14-2produced the following output:

The color is 0Enter a value: 2The crayon is yellow

As illustrated in Program 14-2, expressions containing variables declared as

user-defined data types must be consistent with the values specifically listed for

the type Although a switch statement would be more appropriate in Program

14-2, the expressions in the if-else statement better highlight the use of

enu-merated values Program 14-2 also shows that the initialization of a

user-speci-fied data type variable is identical to the initialization of standard data type

vari-ables For input and output purposes, however, the equivlent integer value

assigned by the C compiler to each enumerated value must be used in place of

the actual data type value This is also seen in the program

In order to assign equivalent integers to each user-specified value, the C

compiler retains the order of the values as they are listed in the enumeration

A side effect of this ordering is that expressions can be constructed using

rela-tional and logical operators For example, for the data type color created in

Program 14-2, expressions such as crayon < yellow and red < green are

both valid

The numerical value assigned by the compiler to enumerated values can be

altered by direct assignment when a data type is created For example, the

defini-tion

enum color (red,green = 7, yellow);

causes the compiler to associate the value red with the integer () and the value

green with the integer 7 Altering the integer associated with the value green

causes all subsequent integer assignments to be altered too; thus, the value

yel-low is associated with the integer 8 If any other values were listed after yelyel-low,

they would be associated with the integers 9, 10, II, and so on, unless another

alteration was made

Naming a user-defined data type is similar to naming a template for

struc-tures Just as a template name can be omitted when defining a structure by

declaring the structure directly, the same can be done with user-defined data

types For example, the declaration enum {red, green, yellow} crayon;

defines crayon to be an enumerated variable with the valid values of red,

green, and yellow

Scope rules applicable to the standard C data types also apply to

enumer-ated data types For example, placing the statement enum color {red,

green', yellow}; before the main ( ) function in Program 14-2 would make

the data type named color global and available for any other function in the

file

Finally, since there is a one-to-one correspondence between integers and

user-defined data types, the cast operator can either coerce integers into a

user-speci-fied data value or coerce a user-speciuser-speci-fied value into its equivalent integer

Assuming that val is an integer variable with a value of I, and color has been

declared as in Program 14-2,the expression (enum color) val has a value of

green and the expression (int) yellow has a value of2. The compiler will

not warn you, however, if a cast to a nonexistent value is attempted

537

Trang 20

Thetypedef Statement

In addition to creating new data types, C allows both standard and user-defineddata types to be renamed using typedef statements The statement

typedef float REAL;

makes the name REALa synonym for float The name REALcan now be used inplace of the term float anywhere in the program after the synonym has beendeclared For example, the definition

typedef float REAL;

actually specifies that REALis a placeholder that will be replaced with anothervariable name A subsequent declaration such as

REAL val;

has the effect of substituting the variable named val for the placeholder namedREALin the terms following the word typedef Substituting val for REALinthe typedef statement and retaining all terms after the reserved word typedefresults in the equivalent declaration float val;

Once the mechanics of the replacement are understood, more useful lences can be constructed Consider the statement

equiva-typedef int ARRAY[lOO];

Here, the name ARRAYis actually a placeholder for any subsequently definedvariables Thus, a statement such as ARRAY first, second; is equivalent tothe two definitions

int first[lOO];

int second[lOO];

Trang 21

14.3 Defining Macros

Each of these definitions is obtained by replacing the name ARRAY with the

variable names first and second in the terms following the reserved word

typedef

As another example, consider the following statement:

typedef struct

char name[20Jiint id_numi

EMP_RECi

Here EMP _REC is a convenient placeholder for any subsequent variable For

example, the declaration EMP _REC employee [75Ji is equivalent to the

decla-ration

structchar name[20Jiint id_numiemployee [75Ji

This last declaration is obtained by directly substituting the term

emplo:0-ee [75Jin place of the word EMP_REC in the terms following the word typed~f

in the original typedef statement

14.3 Defining Macros

In its simplest form, the #define preprocessor is used to equate constants and

operators to symbolic names For example, the statement

#define SALESTAX 05equates the symbolic name SALESTAX to the number 05.When SALESTAX is

used in any subsequent statement or expression the equivalent value of 05 is

substituted for the symbolic name The substitutions are made by the C

prepro-cessor just prior to program compilation

C places no restrictions on the equivalences that can be established with the

#define statement The symbolic name following the #define designation can

be equated to any text and can even include arguments For example, all of the

following are valid equivalences:

3.1416

*

"The answer is if"

The use of these equivalence statements is illustrated in Program 14-3

Trang 22

float circum, radius = 6.3;

circum EQUALS2.0 TIMES PI TIMES radius;

printf(FORMAT,circum);

Before Program 14-3 is compiled, the preprocessor directly substitutes theequivalent operator, constant, variable, or text in place of each subsequent occur-rence of the symbolic name

In addition to using #define preprocessor statements for simple lences, as in Program 14-3, these statements can also be used to equate symbolicnames to either partial or complete expressions When the equivalent text con-sists of more than a single value, operator, or variable, the symbolic name isreferred to as amacro, and the substitution of the text in place of the symbolicname is called amacro expansion or macro substitution. The word macro refers tothe direct, in-line expansion of one word into many words For example, theequivalence established by the statement

equiva-#define CONVERTenables us to write the statement

2.0 * 3.1416

circum = CONVERT* radius;

When this statement is encountered by the preprocessor, the symbolic nameCONVERTis replaced by the equivalent text 2.0 * 3.1416 The compiler alwaysreceives the expanded version after the text has been inserted in place of the sym-bolic name by the preprocessor This direct substitution of the text for CONVERToccurs in every place that CONVERTis encountered after it has been defined Thisallows a previously defined symbolic name to be used in subsequent symbolicdefinitions For example, the definition for CONVERTcould have been establishedusing the following set of #define statements:

#define PI

#define CONVERT

3.14162.0 * PISince PI is made equivalent to the constant 3.1416 in the first #definestatement, it can be used legitimately in any following #de fine statements

Trang 23

of making SQUARE (x) a macro rather than a function.

Take care when defining macros with arguments For example, in the tion ofSQUARE (x) , there must be no space between the symbolic name SQUAREand the left parenthesis used to enclose the argument There can, however, bespaces within the parentheses if more than one argument is used

defini-Additionally, since the expansion of a macro involves direct text substitution,unintended results may occur if you do not use macros carefully For example,the assignment statement

val = SQUARE(numl + numl);

does not assign the value of (numl + num2)2to val Rather, the expansion ofSQUARE (numl + num2) results in the equivalent statement

val = numl + num2 * numl + num2;

This statement results from the direct text substitution of the term numl +

num2 for the argument x in the expression x * x that is produced by the pre- ,

Trang 24

is expanded to produce the desired assignment:

val = (numl + num2) * (numl + num2);

Macros are extremely useful when the calculations or expressions they tain are relatively simple and can be kept to one or at most two lines Largermacro definitions tend to become cumbersome and confusing; they are betterwritten as functions If necessary, a macro definition can be continued on a newline by typing a backslash character, \, before the RETURN or ENTER key ispressed The backslash acts as an escape character that causes the preprocessor totreat the RETURN literally and not include it in any subsequent text substitu-tions

con-The advantage of using a macro instead of a function is an increase in tion speed Since the macro is directly expanded and included in every expres-sion or statement using it, there is no execution time loss due to the call andreturn procedures required by a function The disadvantage is the increase inrequired program memory space when a macro is used repeatedly Each time amacro is used the complete macro text is reproduced and stored as an integralpart of the program Thus, if the same macro is used in ten places, the final codeincludes ten copies of the expanded text version of the macro A function, how-ever, is stored in memory only once No matter how many times the function iscalled, the same code is used The memory space required for one copy of a func-tion used extensively throughout a program can be considerably less than thememory required for storing multiple copies of the same code defined as amacro

execu-Exercises 14.3

1 a Define a macro named NEGATE (x) that produces the negative of its argument.

b Include theNEGATE (x) macro defined in Exercise 1a in a complete C program and run the program to confirm proper operation of the macro for various cases.

2 a Define a macro named ABS_ VAL (x) that produces the absolute value of its

radius, where 1t equals 3.1416.

b. Include the CIRCUM (x) macro defined in Exercise 3a in a complete C program and run the program to confirm proper operation of the macro for various cases.

4 a Define a macro named MIN (x, y) that determines the minimum value of its two arguments.

b. Include the MIN (x, y) macro defined in Exercise 4a in a complete C program and run the program to confirm proper operation of the macro for various cases.

5 a Define a macro named MAX (x, y) that determines the maximum value of its two arguments.

b Include theMAX (x, y) macro defined in Exercise Sa in a complete C program and run the program to confirm proper operation of the macro for various cases.

Trang 25

14.4 CommandLineArguments 543

Arguments can be passed to any function in a program, including the main ( )

function In this section we describe the procedures for passing arguments to

main ( ) when a program is initially invoked and having main ( ) correctly

receive and store the arguments passed to it Both the sending and receiving

sides of the transaction must be considered Fortunately, the interface for

trans-mitting arguments to a main ( ) function has been standardized in C, so both

sending and receiving arguments can be done almost mechanically

All the programs that have been run ,so far have been invoked by typing the

name of the executable version of the program after the operating system prompt

is displayed The command line for these programs consists of a single word,

which is the name of the program For computers that use the UNIX@Operating

System the prompt is usually the $ symbol and the executable name of the

gram is a out For these systems, the simple command line $a out begins

pro-gram execution of the last compiled source propro-gram currently residing in a out

If you are using a C compiler on an IBM PC, the equivalent operating system

prompt is either A> or C>, and the name of the executable program is typically

the same name as the source program with an exe extension rather than a c

extension Assuming that you are using an IBM PC with the A> operating system

prompt, the complete command line for running an executable program named

showad exe is A> showa~ As illustrated in Figure 14-1, this command line

causes the showad program to begin execution with its main ( ) function, but no

arguments are passed to main ( )

Now assume that we want to pass the three separate string arguments three

blind mice directly into showad's main function Sending arguments into a

main ( ) function is extremely easy It is accomplished by including the

ments on the command line used to begin program execution Because the

argu-ments are typed on the command line they are, naturally, called command line

arguments To pass the arguments three blind mice directly into the main ( )

function of the showad program, we only need to add the desired words after

the program name on the command line:

A> showad thFee blind mlce

FIGURE 14-1 Invoking the showad Program

Executableversion

of showadmain(){

A>showad -1" Invokesthe program -.t

startingat main ( ),but

no argumentsare passed

Trang 26

FIGURE 14-2 TheCommandLineStoredin Memory

Upon encountering the command line showad three blind mice, theoperating system stores it as a sequence of four strings Figure 14-2 illustrates thestorage of this command line, assuming that each character uses one byte of stor-age As shown in the figure, each string terminates with the standard C null char-acter \ O

Sending command line arguments to main ( ) is always this simple Thearguments are typed on the command line and the operating system nicely storesthem as a sequence of separate strings We must now handle the receiving side ofthe transaction and let main ( ) know that arguments are being passed to it.Arguments passed to main ( ), like all function arguments, must be declared

as part of the function's definition To standardize argument passing to a main ( )function, only two items are allowed: a number and an array The number is aninteger variable, which must be named argc (short for argument counter), andthe array is a one-dimensional list, which must be named argv (short for argu-ment values) Figure 14-3 illustrates these two arguments

The integer passed to main ( ) is the total number of items on the commandline In our example, the value of argc passed to main ( ) is four, whichincludes the name of the program plus the three command line arguments Theone-dimensional list passed to main ( ) is a list of pointers containing the start-ing storage address of each string typed on the command line, as illustrated inFigure 14-4

We can now write the complete function definition for main ( ) to receivearguments Since an integer and an array are passed to main ( ) and C requiresthat these two items be named argc and argv, respectively, the first line inmain ( )'s definition must be main (int argc, char *argv [ ])

Because argc is an integer, its declaration is int argc; Because argv isthe name of an array whose elements are addresses that point to where the actualcommand line arguments are stored, its proper declaration is char *argv [ ];.This is nothing more than the declaration of an array of pointers It is read "argv

is an array whose elements are pointers to characters." Putting all this together,the full function header line for a main ( ) function that will receive commandline arguments is:!

main(int argc, char *argv[]) /* complete main() header line */

No matter how many arguments are typed on the command line, main ( )only needs the two standard pieces of information provided by argc and argv:the number of items on the command line and the list of starting addresses indi-cating where each argument is actually stored

1 In traditional (non-ANSI) C, this header is written as:

Trang 27

14.4 Command Line Arguments 545

argc I Integer

Table

addresses

FIGURE 14-3 An Integer and an Array Are Passed to main ( )

Program 14-4 verifiesour descriptionby printingthe data actuallypassed tb

main ( ).The variableargv [i] used in Program 14-4 containsan address.Thb

notation *argv [i ] refers to lithe character pointed to" by the address in

FIGURE 14-4 Addresses Are Stored in the argv Array

The argv array

Trang 28

546 Chapter Fourteen Additional Capabilities

Assuming that the executable version of Program 14-4 is namedshowad exe, a sample output for the command line showad three blindmice is:

The number of items on the command line is 4The address stored in argv [0] is FFE4

The character pointed to is sThe address stored in argv [0] is FFEBThe character pointed to is t

The address stored in argv[O] is FFFlThe character pointed to is b

The address stored in argv[O] is FFF7The character pointed to is m

The addresses displayed by Program 14-4 clearly depend on the machineused to run the program Figure 14-5 illustrates the storage of the command line

as displayed by the sample output.2 As anticipated, the addresses in the argvarray "point" to the starting characters of each string typed on the command line.Once command line arguments are passed to a C program, they can be usedlike any other C strings Program 14-5causes its command line arguments to bedisplayed from within main ( )

Assuming that the name of the executable version of Program 14-5is a out,the output of this program for the command line a out three blind miceis:

The following arguments were passed to main( ): three blind mice

FIGURE 14-5 The Command Line Stored in Memory

Trang 29

14.4 Command Line Arguments

Notice that when the addresses in argv [ ] are passed to the printf ( )

function in Program 14-5, the strings pointed to by these addresses are

dis-played When these same addresses were passed to the printf ( )function in

Program 14-4, the actual values of the addresses were printed The difference in

displays is caused by the printf ( )function When a %s control sequence is

used in printf ( ),as it is in Program 14-5,it alerts the function that a string

will be accessed.printf ( )then expects the address of the first character in the

string; this is exactly what each element inargv [ ]supplies

One final comment about command line arguments: Any argument typed on

a command line is considered to be a string If you want numerical data passed

tomain ( ),it is up to you to convert the passed string into its numerical coun1

terpart This is seldom an issue, however, since most command line arguments

are used as flags to pass appropriate processing control signals to an invoked

program

Exercises 14.4

1 a Write a C program that accepts the name of a data file as a command line argument.

Have your program open the data file and display its contents, line by line, on the CRT

screen.

b Would the program written for Exercise 1a work correctly for a program file?

2 a Modify the program written for Exercise 1a so that each line displayed is preceded

by a line number.

b Modify the program written for Exercise 2a so that the command line argument -p

will cause the program to list the contents of the file on the printer attached to your

system.

3 Write a C program that accepts a command line argument as the name of a data file.

Given the name, your program should display the number of characters in the file.(Hint: I

Use the fseek ( ) and ftell ( ) library functions discussed in Section 8.2.) :

4 Write a C program that accepts two integer values as command line arguments The

program should multiply the two values entered and display the result. (Hint: The

command line must be accepted as string data and converted to numerical values before

multiplication.)

Trang 30

14.5 The goto Statement

The goto statement provides an unconditional transfer of control to some otherstatement in a program The general form of a goto statement is:

goto label;

where label is any unique name chosen according to the rules for creating al;>lenames The label name must appear, followed by a colon, in front of anyother statement in the function that contains the goto statement For example,the following section of code transfers control to the label named err if division

vari-by zero is attempted:

if (denom == 0.0)goto err;

elseresult num / denom;

err: printf("Error - Attempted Division by Zero";

The astute reader will realize that in this case goto provides a cumbersomesolution to the problem It would require a second goto above the printf ( )statement to stop this statement from always being executed Generally it ismuch easier either to call an error routine for unusual conditions or to use abreak statement if this is necessary

Theoretically, a goto statement is never required because C's normal tures provide sufficient flexibility to handle all possible flow control require-ments Also, gotos tend to complicate programs For example, consider the fol-lowing code:

struc-if (a == 100)goto first;

Trang 31

14.6 Chapter Summary

Both sections of code produce the same result; however, the second version:

clearly is easier to read It is worthwhile to convince yourself that the two sec-'

tions of code do, in fact, producelthe same result by running the code on your'

computer This will let you experience the sense of frustration when working

with goto-invaded code

In C/ the goto statement should be used in a limited manner, if at all The

presence of goto statements can rapidly make a program extremely difficult to:

1 An expression is any combination of operands and operators that yields a

value

2 A conditional expression provides an alternate way of expressing a simple

if - e 1s e statement The general form of a conditional expression is:

expressionl ? expression2 : expression3

The equivalent if-else statement for this is:

if (expressionl)expression2;

elseexpression3;

3 An enumerated data type is a user-defined scalar data type The user must

select a name and list the acceptable values for the data type For example, the

enumeration

enum color {red, green, yellow}

creates a color data type Any variable may be subsequently declared with

this data type and may store one of the acceptable values listed

4 A typedef statement creates synonyms for both standard and enumerated

data types For example, the statement

typedef int WHOLE_NUM;

makesWHOLE_NUM a synonym for into

5 Using the #def ine command, complete expressions can be equated to

symbolic names These expressions can include arguments I

6 Arguments passed to main ( ) are termed command line arguments C provide~

a standard argument-passing procedure in which main ( ) can accept any ,

number of arguments passed to it Each argument passed to main ( ) is

549

Trang 32

considered a string and is stored using a pointer array named argv The totalnumber of items on the command line is stored in an integer variable namedargc.

7 C also provides a goto statement In theory this statement need never beused In practice it produces confusing and unstructured code It should beused only in a very limited and controlled manner, if at all

Trang 33

Appendixes

551

Ngày đăng: 12/08/2014, 09:22

TỪ KHÓA LIÊN QUAN