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

Advanced C 1992

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

Part II • Managing Data in C

Listing 9.9. continued

if (nStatus & RTS)

{

printf(“RTS is high. \n”);

}

else

{

printf(“RTS is low. \n”);

}

nStatus = inp(IER_PORT);

printf(“IER_PORT returned %2.2X\n”, nStatus);

nStatus = inp(IIR_PORT);

printf(“IIR_PORT returned %2.2X\n”, nStatus);

nStatus = inp(LCR_PORT);

printf(“LCR_PORT returned %2.2X\n”, nStatus);

nStatus = inp(MCR_PORT);

printf(“MCR_PORT returned %2.2X\n”, nStatus);

nStatus = inp(LSR_PORT);

printf(“LSR_PORT returned %2.2X\n”, nStatus);

nStatus = inp(MSR_PORT);

printf(“MSR_PORT returned %2.2X\n”, nStatus);

nTempStatus = inp(LCR_PORT);

outp(LCR_PORT, nTempStatus | DIVISOR_LATCH_BIT);

nStatus = inp(DLM_PORT);

printf(“DLM_PORT returned %2.2X\n”, nStatus);

316

Disk Files and Other I/O

C C C

 

C9C

 

C C C

 

C

nStatus = inp(DLL_PORT);

printf(“DLL_PORT returned %2.2X\n”, nStatus);

outp(LCR_PORT, nTempStatus);

return(1);

}

READCOMM.C uses a simple loop to read the characters. The part of the program that does the reading is shown in bold in the following code fragment. The other parts of the code fragment are the echo code. Echoing received characters is optional and is usually controlled by the user.

nStatus = inp(LSR_PORT);

if (nStatus & DATA_READY)

{/* A character has been received. */ *chChar = inp(RBR_PORT);

/* Echo the data byte to the sender. The program

*must wait until the last character has been sent

*because the simple hardware does not have a queue.

*/

nStatus = inp(LSR_PORT);

while (!(nStatus & TRANS_HOLDING_REGISTER))

{/* Simply get the status again, which wastes time */ nStatus = inp(LSR_PORT);

}

outp(THR_PORT, *chChar);

The READCOMM program also shows how to switch between the speed controlling ports, DLL and DLM. This is accomplished by setting the DIVISOR_LATCH_BIT bit in the LCR_PORT register, as follows:

nTempStatus = inp(LCR_PORT);

outp(LCR_PORT, nTempStatus | DIVISOR_LATCH_BIT);

317

BAUD_

Part II • Managing Data in C

nStatus = inp(DLM_PORT);

printf(“DLM_PORT returned %2.2X\n”, nStatus);

nStatus = inp(DLL_PORT);

printf(“DLL_PORT returned %2.2X\n”, nStatus);

outp(LCR_PORT, nTempStatus);

First, the program gets the current contents of the LCR_PORT and saves the contents in nTempStatus. Then the program writes to LCR_PORT with nTempStatus logically ORd with the DIVISOR_LATCH_BIT. This switches the meaning of RBR_PORT to

DLL_PORT and the meaning of THR_PORT to DLM_PORT.

Be sure you reset LCR_PORT after you have finished setting (or checking) the baud rate. You set the baud rate using the identifiers prefaced with in either program.

Summary

In this chapter, you learned about input and output using C, and how to use both file I/O and port I/O.

Files used for both program input and program output are vital to any program’s operation.

Text-based files can be read, printed, edited, and otherwise used without conversion by people. Text files usually contain only printable, newline, and form-feed characters.

Binary files contain any bytes that a program must place in the file. Generally, a binary file is intended for use by the program or by other programs and cannot be edited, printed, or read.

Using temporary work files, a programmer can extend a program’s data storage space to almost the amount of free space on the disk. Work files can be text or binary, depending on the program’s requirements.

Stream files are supported by many functions, can be text or binary, and are usually buffered and formatted.

318

Disk Files and Other I/O

C C C

 

C9C

 

C C C

 

C

Every C program has five opened files: stdin, stdout, stdaux, stdprn, and stderr. These files are opened as stream files.

Low-level files are accessed with a minimum number of C functions and are usually unformatted and unbuffered.

C compilers provide console functions to access the screen and keyboard.

In PC compatible systems, your programs can access ports using C. This access allows direct interaction with the device, without DOS or the BIOS.

319

Part II • Managing Data in C

320

Data Management:CSorts, Lists,Cand Indexes CC C C

C10C C

C10C CC C C

C C C

Data Management:

Sorts, Lists, and Indexes

Data management is what it’s all about. Almost all computer programs manage data— even a simple computer game must manage and access data to update its list of current high scores.

Sorting, merging, and purging. Indexed files. Tree access methods. Everyone knows what sorting is, but the other terms may be unfamiliar. Merging is the process of combining two sorted files and creating a resultant, sorted file. Purging uses a sorted file to create a new file in which duplicate lines from the original file are eliminated. An indexed file (or in-memory data object) consists of two files: the main data file and a second, smaller index file. A tree access method offers fast searching and sorted access to data. (This chapter discusses B-trees.)

321

Part II • Managing Data in C

I’ll use the creation of this book’s index as an example of sorting, merging, and purging. For each chapter, I created a file in which each word is on a separate line (I simply changed all spaces to newline characters). I then sorted the file, then purged it, which eliminates all duplicate words (and makes the file size more manageable).

Then, I merged each chapter’s file of unique words into one large file for the entire book. I then purged that file—even though each chapter’s file contains only unique words, other chapters might contain some of these words too. After this final purge, I had a file of unique words in the book. After a quick session with an editor, I deleted any words that were not index material, leaving only the important words.

I used programs that I created to sort, merge, and purge as part of this chapter. The DOS SORT utility is limited to files under 64K, but the sort program in this chapter is limited only by the available memory. The merge and purge utilities are not part of DOS. I hope they prove to be valuable additions to your stable of programming tools.

Sorting

Sorting a file can be both easy and difficult. It’s easy because C has a sort function called qsort() that is part of the library. This function’s performance is acceptable. The difficult part is reading in the files and other programming overhead. You must provide a compare function that qsort() can use.

When you write a program in which you do not know the amount of data that the user will input, you must rely on dynamic memory allocation. This is not a problem with the qsort() function: you pass a single array of pointers to the data being sorted and, when qsort() returns, use the (now sorted) array of pointers to access the data in sorted order. When you use this technique with character strings, it reduces overhead and increases the program’s performance because only the pointers are moved in memory, not the strings.

Listing 10.1, SORTFILE.C, sorts the input from stdin and writes the sorted results to stdout. If you use I/O redirection, the program could sort a file and place the results into a new file. Unlike the DOS SORT command, SORTFILE always sorts from column one. (Adding the capability to sort from any other column is an exercise I’ll leave to you.)

322

Data Management: Sorts, Lists, and Indexes

C C C

 

10C

 

C C C

 

C C

Listing 10.1. SORTFILE.C.

/* SORTFILE, written 1992 by Peter D. Hipson

*This program sorts from stdin and sends the results

*to stdout. If your PC has memory models, you must

*compile with the LARGE model.

*/

 

#include <stdio.h>

// Make includes first part of file

#include <string.h>

// For string functions

#include <process.h>

// For exit(), etc.

#include <malloc.h>

// For malloc(), calloc(), realloc(), free()

#include <search.h>

// For qsort()...

int main(void); // Define main() and the fact that this program // does not use any passed parameters

int compare(void *arg1, void *arg2);

#define MAX_CHARACTERS

32767 /*

Total maximum characters */

 

#define MAX_LINES

15500 /*

Total maximum lines */

 

#define

BIGEST_LINE

512

/*

Largest line readable from

keyboard */

#define

MAX_BLOCKS

128

/*

Allow 128 * MAX_CHARACTERS

of memory */

/* Although these variables are defined as external, they could

*be defined inside the function or allocated dynamically,

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

*/

char

szInput[BIGEST_LINE];

char

*szBuffer;

char

*pBlocks[MAX_BLOCKS];

char

*pBuffer[MAX_LINES];

int

nCurrentBlock = 0;

int

nBufferPointer = {MAX_CHARACTERS};

int

nLine = 0;

int main()

{

continues

323

Part II • Managing Data in C

Listing 10.1. continued

int i;

/* Use fprintf(stderr...) to force prompts and error messages

*to be displayed on the user’s screen regardless of whether

*the output has been redirected.

*/

fprintf(stderr,

“\n”

“Peter’s SORTFILE: Sorts large files at the speed of light!\n” “\n”

syntax: \n”

sortfile <inputfile >outputfile \n”

“\n”

where: \n”

the program’s I/O is redirected\n\n”);

fprintf(stderr, “Reading input...\n”);

while (gets(szInput))

{

if ((nBufferPointer + strlen(szInput)) > MAX_CHARACTERS) { // The line won’t fit! Allocate new memory:

szBuffer = (char *)malloc(MAX_CHARACTERS);

fprintf(stderr, “ Allocating buffer (32K).\n”); nBufferPointer = 0;

pBlocks[nCurrentBlock] = szBuffer;

++nCurrentBlock;

if (szBuffer == NULL)

{

fprintf(stderr, “System sort memory exceeded, can’t \ sort.\n”);

324

Data Management: Sorts, Lists, and Indexes

exit(16);

}

}

pBuffer[nLine] = &szBuffer[nBufferPointer];

strcpy(pBuffer[nLine], szInput);

// The + 1 skips over the terminating NULL in each string. nBufferPointer += strlen(szInput) + 1;

if (++nLine >= MAX_LINES)

{ // Too many lines! End the program.

fprintf(stderr, “Too many lines—cannot sort.\n”);

exit(16);

}

}

//

// Now sort the input lines

//

fprintf(stderr, “Sorting, %d lines, in %d buffers.\n”, nLine,

nCurrentBlock);

qsort((void *)pBuffer, (size_t)nLine, sizeof(char *), compare);

fprintf(stderr, “Writing output...\n”);

for (i = 0; i < nLine; i++)

{

printf(“%s\n”, pBuffer[i]);

}

fprintf(stderr, “\n”);

C C C

C10C C

C C C

continues

325