Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Advanced C 1992

.pdf
Скачиваний:
92
Добавлен:
17.08.2013
Размер:
4.28 Mб
Скачать

Pointers and Indirection

C C C

 

C3C

 

C C C

 

C

To make up for the shortcomings in C’s character handling, a large number of string functions are in the standard library (see Chapter 14, “ANSI C Library Functions”). Because the particular functionality your application requires might not be present in one of the C library functions, you can write a function to do whatever you want.

This section doesn’t show you how to count words in a string (the demo program does that), but it does show you how easy it is to work with strings and manipulate pointers to strings.

By now, you should not still be writing programs that compare strings using logical operators, as in the following example:

char szFirst[] = {“This is a string”}; char szNext[] = {“Before this one”);

if (szFirst > szNext)

{

/* the test was meaningless! */

}

This comparison simply evaluates the addresses of the two strings, not their contents. The result of the test is undefined because you cannot predict where in memory the strings will be located, nor are their contents related to their memory address.

The correct way to compare two strings is to call the library function strcmp(), which returns a value based on the logical relationship between the two strings:

char szFirst[] = {“This is a string”}; char szNext[] = {“Before this one”);

if (strcmp(szFirst, szNext) > 0)

{

/* szFirst is before szNext! */

}

This relationship is much more useful to your programs than are the string’s addresses. NUMWORD.C counts the number of words in a sentence that are entered from the keyboard (see Listing 3.4).

75

Part I • Honing Your C Skills

Listing 3.4. NUMWORD.C.

/* NUMWORD, written 20 May 1992 by Peter D. Hipson */ /* Program to count words in sentences. */

#include <stdio.h> // Make includes first part of file #include <string.h> // For string functions

#define

TRUE

1

#define

FALSE

0

int main(void); // Define main() and the fact that this program doesn’t // use any passed parameters.

int

NumberWords(char

* pString);

#define

BIGEST_LINE

256

/* The biggest line readable from keyboard */

/* Though these variables are defined as external, they can be

*defined inside the function or be allocated dynamically,

*depending on the program’s needs and the amount of memory available */

char szInput[BIGEST_LINE];

int main()

{

int i;

printf(

“Enter lines, when last one is entered\n”

“provide a End-Of-File (ctrl-Z on most systems)\n” “to end the program.\n\n”);

while (gets(szInput))

{

76

Pointers and Indirection

printf(“Words = %2d ‘%.50s’\n”,

 

NumberWords(szInput),

 

szInput);

}

 

printf(“\n”);

return (0);

}

 

int

NumberWords(

char

szString[])

{

 

int

i;

int

nBlank = TRUE;

int

nCount = 0;

for (i = 0; szString[i]; i++)

{

if (szString[i] != ‘ ‘)

{

if (nBlank)

{

++nCount;

}

nBlank = FALSE;

}

else

{

nBlank = TRUE;

}

}

return(nCount);

}

C C C

C3C C

C C C

77

Part I • Honing Your C Skills

NUMWORD has a very simple loop that calls gets() until the end-of-file is reached. After gets() returns, the loop itself calls printf(), which has as one of its parameters a call to the NumberWords() function.

printf(“Words = %2d ‘%.50s’\n”, NumberWords(szInput), szInput);

C first calls NumberWords() and then passes to printf() the returned value, along with the other parameters.

for (i = 0; szString[i]; i++)

{

if (szString[i] != ‘ ‘)

{

if (nBlank)

{

++nCount;

}

nBlank = FALSE;

}

else

{

nBlank = TRUE;

}

}

NumberWords() has a loop that looks at the passed string and parses out the words. The format for this loop is a for() loop; while() can be used, however. This loop moves through the character string and increments an index to the passed string. When the loop starts, it is assumed that a blank has been encountered already. This assumption is made by setting the blank flag (nBlank) on so that you can count the first word regardless of whether it’s preceded by blanks. Also, the word count (nCount) is set to zero, which indicates that no words have been counted.

When the first nonblank character is found, the word counter is incremented (a word has been found), and the blank flag is turned off. The loop continues searching for the next blank; when it is found, the blank flag is set to on and the process continues until the end of the string is found.

78

Pointers and Indirection

C C C

 

C3C

 

C C C

 

C

Indirection to Access Character Strings

To change NUMWORD to use indirection to access the string, the loop in NumberWords() must change slightly (see Listing 3.5).

Listing 3.5. NUMWORD1.C.

/* NUMWORD1, written 21 May 1992 by Peter D. Hipson */ /* Program to count words in sentences. */

#include <stdio.h> // Make includes first part of file #include <string.h> // For string functions

#define

TRUE

1

#define

FALSE

0

int main(void); // Define main() and the fact that this program doesn’t // use any passed parameters.

int

NumberWords(char

* pString);

#define

BIGEST_LINE

256

/* The biggest line readable from keyboard */

/* Although these variables are defined as external, they can be

*defined inside the function or be allocated dynamically,

*depending on the program’s needs and memory available. */

char szInput[BIGEST_LINE];

int main()

{

int i;

printf(

continues

79

Part I • Honing Your C Skills

Listing 3.5. continued

“Enter lines, when last one is entered\n”

“provide a End-Of-File (ctrl-Z on most systems)\n” “to end the program.\n\n”);

while (gets(szInput))

{

printf(“Words = %2d ‘%.50s’\n”,

 

NumberWords(szInput),

 

szInput);

}

 

printf(“\n”);

return (0);

}

 

int

NumberWords(

char

* pString)

{

 

int

nBlank = TRUE;

int

nCount = 0;

do

 

{

 

 

if (*(pString) && *(pString) != ‘ ‘)

 

{

 

if (nBlank)

 

{

 

++nCount;

 

}

nBlank = FALSE;

}

else

{

nBlank = TRUE;

}

80

Pointers and Indirection

C C C

 

C3C

 

C C C

 

C

} while(*(pString++));

return(nCount);

}

NumberWords() again has a loop that looks at the passed string and parses out the words. The format for this loop is do()...while(). A straight while() or even a for() loop, however, can be used:

do

{

if (*(pString) && *(pString) != ‘ ‘)

{

if (nBlank)

{

++nCount;

}

nBlank = FALSE;

}

else

{

nBlank = TRUE;

}

} while(*(pString++));

You no longer need to use an index variable, because you are using the pointer that was passed to keep track of where you are in the string. One possible advantage to this method is that by incrementing the pointer rather than an index to a string, the function generally is both faster and smaller.

This loop moves through the character string and increments the passed pointer. Remember that this passed pointer is a private copy for this function and can be modified. It is assumed that a blank has been encountered already, by setting the blank flag on so that you can count the first word regardless of whether it is preceded by blanks. Also, the word count is set to zero so that no words are counted. When the first nonblank character is found, the word counter is incremented (a word has been found) and the blank flag is turned off. The loop continues searching for the next blank; when it is found, the blank flag is set to on and the process continues until the end of the string is found.

81

Part I • Honing Your C Skills

Listing 3.6 shows the assembly listing for the version of NumberWords() that uses pointer indexing. The compiler produces this machine code, commented with the original source lines, when the function is compiled.

Listing 3.6. NUMWORD3.COD, the assembly listing for the pointer version of NumberWords().

;Edited for size.

;Static Name Aliases

TITLE numword3.c NAME numword3

.8087

 

 

_TEXT

SEGMENT

WORD PUBLIC ‘CODE’

_TEXT

ENDS

 

_DATA

SEGMENT

WORD PUBLIC ‘DATA’

_DATA

ENDS

 

CONST

SEGMENT

WORD PUBLIC ‘CONST’

CONST

ENDS

 

_BSS

SEGMENT

WORD PUBLIC ‘BSS’

_BSS

ENDS

 

DGROUP

 

GROUP

CONST, _BSS, _DATA

ASSUME

CS: _TEXT, DS: DGROUP, SS: DGROUP

EXTRN

 

--acrtused:ABS

EXTRN

 

--chkstk:NEAR

_TEXT

 

SEGMENT

ASSUME

CS: _TEXT

;|*** /* NUMWORD3, written 21 May 1992 by Peter D. Hipson */

;|***

 

 

 

;|*** #include <stdio.h>

// Make includes first part of file

;|*** #include <string.h> // For string functions

;|***

 

 

 

;|*** #define

TRUE

1

 

;|*** #define

FALSE

0

 

;|***

 

 

 

;|***

 

 

 

;|*** int

NumberWords(char

* pString);

;|***

 

 

 

;|*** int

NumberWords(

 

 

82

 

 

 

 

 

 

Pointers and Indirection

C C C

 

 

 

 

 

 

 

C3C

 

 

 

 

 

 

 

C C C

;|***

char

* pString)

 

 

C

 

 

 

;|***

 

 

 

 

 

 

 

;|*** {

 

 

 

 

 

 

 

; Line 15

 

 

 

 

 

 

 

PUBLIC

 

_NumberWords

 

 

 

_NumberWords

PROC

NEAR

 

 

 

*** 000000

55

 

 

push

bp

 

*** 000001

8b

ec

 

mov

bp,sp

 

*** 000003

b8

06

00

mov

ax,6

 

*** 000006

e8

00

00

call

__ chkstk

 

;pString = 4

;nBlank = -2

;nCount = -4

;|***

;|*** int

 

nBlank

= TRUE;

 

 

 

 

; Line 17

 

 

 

 

 

 

 

 

*** 000009

c7

46

fe 01 00

 

mov

WORD PTR [bp-2],1

;nBlank

 

 

 

 

 

 

 

 

;|*** int

 

nCount

= 0;

 

 

 

 

; Line 18

 

 

 

 

 

 

 

 

*** 00000e

c7

46

fc 00 00

 

mov

WORD PTR [bp-4],0

;nCount

 

 

 

 

 

 

 

 

;|***

 

 

 

 

 

 

 

 

;|***

do

 

 

 

 

 

 

 

; Line 20

 

 

 

 

 

 

 

 

 

 

 

$D239:

 

 

 

 

;|***

{

 

 

 

 

 

 

 

; Line 21

 

 

 

 

 

 

 

 

;|***

 

if (*(pString) && *(pString) != ‘ ‘)

 

; Line 22

 

 

 

 

 

 

 

 

*** 000013

8b

5e

04

mov

bx,WORD PTR [bp+4]

;pString

*** 000016

8a

07

 

mov

al,BYTE PTR [bx]

 

*** 000018

88

46

fa

mov

BYTE PTR [bp-6],al

 

*** 00001b

0a

c0

 

or

al,al

 

 

*** 00001d

74

15

 

je

$I242

 

 

*** 00001f

3c

20

 

cmp

al,32

 

 

*** 000021

74

11

 

je

$I242

 

 

;|***

 

{

 

 

 

 

 

 

; Line 23

 

 

 

 

 

 

 

 

;|***

 

if

(nBlank)

 

 

 

 

continues

83

Part I • Honing Your C Skills

Listing 3.6. continued

; Line 24

 

 

 

 

 

 

 

 

*** 000023

83

7e fe 00

cmp

WORD PTR [bp-2],0

;nBlank

*** 000027

74

03

je

$I243

 

 

 

;|***

 

{

 

 

 

 

 

 

; Line 25

 

 

 

 

 

 

 

 

;|***

 

 

++nCount;

 

 

 

 

 

; Line 26

 

 

 

 

 

 

 

 

*** 000029

ff 46 fc

inc

WORD PTR [bp-4]

;nCount

;|***

 

}

 

 

 

 

 

 

; Line 27

 

 

 

 

 

 

 

 

;|***

 

 

 

 

 

 

 

 

;|***

 

nBlank = FALSE;

 

 

 

 

 

; Line 29

 

 

 

 

 

 

 

 

 

 

 

$I243:

 

 

 

 

 

*** 00002c

c7

46 fe 00 00

 

mov

WORD PTR [bp-2],0

 

;nBlank

 

 

 

 

 

 

 

 

;|***

 

}

 

 

 

 

 

 

; Line 30

 

 

 

 

 

 

 

 

;|***

 

else

 

 

 

 

 

 

; Line 31

 

 

 

 

 

 

 

 

*** 000031

eb 06

jmp

SHORT $I244

 

 

*** 000033

90

 

nop

 

 

 

 

 

 

 

$I242:

 

 

 

 

 

;|***

 

{

 

 

 

 

 

 

; Line 32

 

 

 

 

 

 

 

 

;|***

 

nBlank = TRUE;

 

 

 

 

 

; Line 33

 

 

 

 

 

 

 

 

*** 000034

c7

46 fe 01 00

 

mov

WORD PTR [bp-2],1

 

;nBlank

 

 

 

 

 

 

 

 

;|***

 

}

 

 

 

 

 

 

; Line 34

 

 

 

 

 

 

 

 

 

 

 

$I244:

 

 

 

 

 

;|***

 

 

 

 

 

 

 

 

;|***

} while(*(pString++));

 

 

 

 

 

; Line 36

 

 

 

 

 

 

 

 

*** 000039

8b

5e 04

mov

bx,WORD PTR [bp+4]

;pString

*** 00003c

ff 46 04

inc

WORD PTR [bp+4]

;pString

*** 00003f

80

3f 00

cmp

BYTE PTR [bx],0

 

 

*** 000042

75

cf

jne

$D239

 

 

 

84