Use backtick code blocks for syntax highlighting
This commit is contained in:
parent
8ed9dea394
commit
f658bfbb40
203 changed files with 26546 additions and 25801 deletions
284
08-03.md
284
08-03.md
|
|
@ -12,125 +12,127 @@ pages: 156-160
|
|||
|
||||
**LISTING 8.1 L8-1.C**
|
||||
|
||||
/* Program to search an array spanning a linked list of variable-
|
||||
sized blocks, for all entries with a specified ID number,
|
||||
and return the average of the values of all such entries. Each of
|
||||
the variable-sized blocks may contain any number of data entries,
|
||||
stored as an array of structures within the block. */
|
||||
```c
|
||||
/* Program to search an array spanning a linked list of variable-
|
||||
sized blocks, for all entries with a specified ID number,
|
||||
and return the average of the values of all such entries. Each of
|
||||
the variable-sized blocks may contain any number of data entries,
|
||||
stored as an array of structures within the block. */
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef __TURBOC__
|
||||
#include <alloc.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#ifdef __TURBOC__
|
||||
#include <alloc.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
void main(void);
|
||||
void exit(int);
|
||||
unsigned int FindIDAverage(unsigned int, struct BlockHeader *);
|
||||
/* Structure that starts each variable-sized block */
|
||||
struct BlockHeader {
|
||||
struct BlockHeader *NextBlock; /* Pointer to next block, or NULL
|
||||
if this is the last block in the
|
||||
linked list */
|
||||
unsigned int BlockCount; /* The number of DataElement entries
|
||||
in this variable-sized block */
|
||||
};
|
||||
void main(void);
|
||||
void exit(int);
|
||||
unsigned int FindIDAverage(unsigned int, struct BlockHeader *);
|
||||
/* Structure that starts each variable-sized block */
|
||||
struct BlockHeader {
|
||||
struct BlockHeader *NextBlock; /* Pointer to next block, or NULL
|
||||
if this is the last block in the
|
||||
linked list */
|
||||
unsigned int BlockCount; /* The number of DataElement entries
|
||||
in this variable-sized block */
|
||||
};
|
||||
|
||||
/* Structure that contains one element of the array we'll search */
|
||||
struct DataElement {
|
||||
unsigned int ID; /* ID # for array entry */
|
||||
unsigned int Value; /* Value of array entry */
|
||||
};
|
||||
/* Structure that contains one element of the array we'll search */
|
||||
struct DataElement {
|
||||
unsigned int ID; /* ID # for array entry */
|
||||
unsigned int Value; /* Value of array entry */
|
||||
};
|
||||
|
||||
void main(void) {
|
||||
int i,j;
|
||||
unsigned int IDToFind;
|
||||
struct BlockHeader *BaseArrayBlockPointer,*WorkingBlockPointer;
|
||||
struct DataElement *WorkingDataPointer;
|
||||
struct BlockHeader **LastBlockPointer;
|
||||
void main(void) {
|
||||
int i,j;
|
||||
unsigned int IDToFind;
|
||||
struct BlockHeader *BaseArrayBlockPointer,*WorkingBlockPointer;
|
||||
struct DataElement *WorkingDataPointer;
|
||||
struct BlockHeader **LastBlockPointer;
|
||||
|
||||
printf("ID # for which to find average: ");
|
||||
scanf("%d",&IDToFind);
|
||||
/* Build an array across 5 blocks, for testing */
|
||||
/* Anchor the linked list to BaseArrayBlockPointer */
|
||||
LastBlockPointer = &BaseArrayBlockPointer;
|
||||
/* Create 5 blocks of varying sizes */
|
||||
for (i = 1; i < 6; i++) {
|
||||
/* Try to get memory for the next block */
|
||||
if ((WorkingBlockPointer =
|
||||
(struct BlockHeader *) malloc(sizeof(struct BlockHeader) +
|
||||
sizeof(struct DataElement) * i * 10)) == NULL) {
|
||||
exit(1);
|
||||
}
|
||||
/* Set the # of data elements in this block */
|
||||
WorkingBlockPointer->BlockCount = i * 10;
|
||||
/* Link the new block into the chain */
|
||||
*LastBlockPointer = WorkingBlockPointer;
|
||||
/* Point to the first data field */
|
||||
WorkingDataPointer =
|
||||
(struct DataElement *) ((char *)WorkingBlockPointer +
|
||||
sizeof(struct BlockHeader));
|
||||
/* Fill the data fields with ID numbers and values */
|
||||
for (j = 0; j < (i * 10); j++, WorkingDataPointer++) {
|
||||
WorkingDataPointer->ID = j;
|
||||
WorkingDataPointer->Value = i * 1000 + j;
|
||||
}
|
||||
/* Remember where to set link from this block to the next */
|
||||
LastBlockPointer = &WorkingBlockPointer->NextBlock;
|
||||
}
|
||||
/* Set the last block's "next block" pointer to NULL to indicate
|
||||
that there are no more blocks */
|
||||
WorkingBlockPointer->NextBlock = NULL;
|
||||
printf("Average of all elements with ID %d: %u\n",
|
||||
IDToFind, FindIDAverage(IDToFind, BaseArrayBlockPointer));
|
||||
exit(0);
|
||||
}
|
||||
printf("ID # for which to find average: ");
|
||||
scanf("%d",&IDToFind);
|
||||
/* Build an array across 5 blocks, for testing */
|
||||
/* Anchor the linked list to BaseArrayBlockPointer */
|
||||
LastBlockPointer = &BaseArrayBlockPointer;
|
||||
/* Create 5 blocks of varying sizes */
|
||||
for (i = 1; i < 6; i++) {
|
||||
/* Try to get memory for the next block */
|
||||
if ((WorkingBlockPointer =
|
||||
(struct BlockHeader *) malloc(sizeof(struct BlockHeader) +
|
||||
sizeof(struct DataElement) * i * 10)) == NULL) {
|
||||
exit(1);
|
||||
}
|
||||
/* Set the # of data elements in this block */
|
||||
WorkingBlockPointer->BlockCount = i * 10;
|
||||
/* Link the new block into the chain */
|
||||
*LastBlockPointer = WorkingBlockPointer;
|
||||
/* Point to the first data field */
|
||||
WorkingDataPointer =
|
||||
(struct DataElement *) ((char *)WorkingBlockPointer +
|
||||
sizeof(struct BlockHeader));
|
||||
/* Fill the data fields with ID numbers and values */
|
||||
for (j = 0; j < (i * 10); j++, WorkingDataPointer++) {
|
||||
WorkingDataPointer->ID = j;
|
||||
WorkingDataPointer->Value = i * 1000 + j;
|
||||
}
|
||||
/* Remember where to set link from this block to the next */
|
||||
LastBlockPointer = &WorkingBlockPointer->NextBlock;
|
||||
}
|
||||
/* Set the last block's "next block" pointer to NULL to indicate
|
||||
that there are no more blocks */
|
||||
WorkingBlockPointer->NextBlock = NULL;
|
||||
printf("Average of all elements with ID %d: %u\n",
|
||||
IDToFind, FindIDAverage(IDToFind, BaseArrayBlockPointer));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Searches through the array of DataElement entries spanning the
|
||||
linked list of variable-sized blocks, starting with the block
|
||||
pointed to by BlockPointer, for all entries with IDs matching
|
||||
SearchedForID, and returns the average value of those entries. If
|
||||
no matches are found, zero is returned */
|
||||
/* Searches through the array of DataElement entries spanning the
|
||||
linked list of variable-sized blocks, starting with the block
|
||||
pointed to by BlockPointer, for all entries with IDs matching
|
||||
SearchedForID, and returns the average value of those entries. If
|
||||
no matches are found, zero is returned */
|
||||
|
||||
unsigned int FindIDAverage(unsigned int SearchedForID,
|
||||
struct BlockHeader *BlockPointer)
|
||||
{
|
||||
struct DataElement *DataPointer;
|
||||
unsigned int IDMatchSum;
|
||||
unsigned int IDMatchCount;
|
||||
unsigned int WorkingBlockCount;
|
||||
unsigned int FindIDAverage(unsigned int SearchedForID,
|
||||
struct BlockHeader *BlockPointer)
|
||||
{
|
||||
struct DataElement *DataPointer;
|
||||
unsigned int IDMatchSum;
|
||||
unsigned int IDMatchCount;
|
||||
unsigned int WorkingBlockCount;
|
||||
|
||||
IDMatchCount = IDMatchSum = 0;
|
||||
/* Search through all the linked blocks until the last block
|
||||
(marked with a NULL pointer to the next block) has been
|
||||
searched */
|
||||
do {
|
||||
/* Point to the first DataElement entry within this block */
|
||||
DataPointer =
|
||||
(struct DataElement *) ((char *)BlockPointer +
|
||||
sizeof(struct BlockHeader));
|
||||
/* Search all the DataElement entries within this block
|
||||
and accumulate data from all that match the desired ID */
|
||||
for (WorkingBlockCount=0;
|
||||
WorkingBlockCount<BlockPointer->BlockCount;
|
||||
WorkingBlockCount++, DataPointer++) {
|
||||
/* If the ID matches, add in the value and increment the
|
||||
match counter */
|
||||
if (DataPointer->ID == SearchedForID) {
|
||||
IDMatchCount++;
|
||||
IDMatchSum += DataPointer->Value;
|
||||
}
|
||||
}
|
||||
/* Point to the next block, and continue as long as that pointer
|
||||
isn't NULL */
|
||||
} while ((BlockPointer = BlockPointer->NextBlock) != NULL);
|
||||
/* Calculate the average of all matches */
|
||||
if (IDMatchCount == 0)
|
||||
return(0); /* Avoid division by 0 */
|
||||
else
|
||||
return(IDMatchSum / IDMatchCount);
|
||||
}
|
||||
IDMatchCount = IDMatchSum = 0;
|
||||
/* Search through all the linked blocks until the last block
|
||||
(marked with a NULL pointer to the next block) has been
|
||||
searched */
|
||||
do {
|
||||
/* Point to the first DataElement entry within this block */
|
||||
DataPointer =
|
||||
(struct DataElement *) ((char *)BlockPointer +
|
||||
sizeof(struct BlockHeader));
|
||||
/* Search all the DataElement entries within this block
|
||||
and accumulate data from all that match the desired ID */
|
||||
for (WorkingBlockCount=0;
|
||||
WorkingBlockCount<BlockPointer->BlockCount;
|
||||
WorkingBlockCount++, DataPointer++) {
|
||||
/* If the ID matches, add in the value and increment the
|
||||
match counter */
|
||||
if (DataPointer->ID == SearchedForID) {
|
||||
IDMatchCount++;
|
||||
IDMatchSum += DataPointer->Value;
|
||||
}
|
||||
}
|
||||
/* Point to the next block, and continue as long as that pointer
|
||||
isn't NULL */
|
||||
} while ((BlockPointer = BlockPointer->NextBlock) != NULL);
|
||||
/* Calculate the average of all matches */
|
||||
if (IDMatchCount == 0)
|
||||
return(0); /* Avoid division by 0 */
|
||||
else
|
||||
return(IDMatchSum / IDMatchCount);
|
||||
}
|
||||
```
|
||||
|
||||
The main body of Listing 8.1 constructs a linked list of memory blocks
|
||||
of various sizes and stores an array of structures across those blocks,
|
||||
|
|
@ -154,32 +156,34 @@ instruction can be used.
|
|||
|
||||
**LISTING 8.2 L8-2.COD**
|
||||
|
||||
; Code generated by Microsoft C for inner loop of FindIDAverage.
|
||||
;|*** for (WorkingBlockCount=0;
|
||||
;|*** WorkingBlockCount<BlockPointer->BlockCount;
|
||||
;|*** WorkingBlockCount++, DataPointer++) {
|
||||
mov WORD PTR [bp-6],0 ;WorkingBlockCount
|
||||
mov bx,WORD PTR [bp+6] ;BlockPointer
|
||||
cmp WORD PTR [bx+2],0
|
||||
je $FB264
|
||||
mov cx,WORD PTR [bx+2]
|
||||
add WORD PTR [bp-6],cx ;WorkingBlockCount
|
||||
mov di,WORD PTR [bp-2] ;IDMatchSum
|
||||
mov dx,WORD PTR [bp-4] ;IDMatchCount
|
||||
$L20004:
|
||||
;|*** if (DataPointer->ID == SearchedForID) {
|
||||
mov ax,WORD PTR [si]
|
||||
cmp WORD PTR [bp+4],ax ;SearchedForID
|
||||
jne $I265
|
||||
;|*** IDMatchCount++;
|
||||
inc dx
|
||||
;|*** IDMatchSum += DataPointer->Value;
|
||||
add di,WORD PTR [si+2]
|
||||
;|*** }
|
||||
;|*** }
|
||||
$I265:
|
||||
add si,4
|
||||
loop $L20004
|
||||
mov WORD PTR [bp-2],di ;IDMatchSum
|
||||
mov WORD PTR [bp-4],dx ;IDMatchCount
|
||||
$FB264:
|
||||
```nasm
|
||||
; Code generated by Microsoft C for inner loop of FindIDAverage.
|
||||
;|*** for (WorkingBlockCount=0;
|
||||
;|*** WorkingBlockCount<BlockPointer->BlockCount;
|
||||
;|*** WorkingBlockCount++, DataPointer++) {
|
||||
mov WORD PTR [bp-6],0 ;WorkingBlockCount
|
||||
mov bx,WORD PTR [bp+6] ;BlockPointer
|
||||
cmp WORD PTR [bx+2],0
|
||||
je $FB264
|
||||
mov cx,WORD PTR [bx+2]
|
||||
add WORD PTR [bp-6],cx ;WorkingBlockCount
|
||||
mov di,WORD PTR [bp-2] ;IDMatchSum
|
||||
mov dx,WORD PTR [bp-4] ;IDMatchCount
|
||||
$L20004:
|
||||
;|*** if (DataPointer->ID == SearchedForID) {
|
||||
mov ax,WORD PTR [si]
|
||||
cmp WORD PTR [bp+4],ax ;SearchedForID
|
||||
jne $I265
|
||||
;|*** IDMatchCount++;
|
||||
inc dx
|
||||
;|*** IDMatchSum += DataPointer->Value;
|
||||
add di,WORD PTR [si+2]
|
||||
;|*** }
|
||||
;|*** }
|
||||
$I265:
|
||||
add si,4
|
||||
loop $L20004
|
||||
mov WORD PTR [bp-2],di ;IDMatchSum
|
||||
mov WORD PTR [bp-4],dx ;IDMatchCount
|
||||
$FB264:
|
||||
```
|
||||
|
|
|
|||
Loading…
Reference in a new issue