Download as pdf or txt
Download as pdf or txt
You are on page 1of 254

HOWARD W.

SAMS & COMPANY 22673


Essential Guide Series

The Waite Group’ S


Essential Guide to
UN Ee
\ @. Naba Barkakati
ANSI C Library Routines Arranged Alphabetically

abort, 114 getc, 82 signed, 42


abs, 154 getchar, 83 sin, 166
acos, 155 getenv, 116 sinh, 167
asctime, 215 gets, 83 sizeof, 42
asin, 155 gmtime, 278 sprintf, 94
assert, 174 goto, 39 sqrt, 167
atan, 156 if, 39 srand, 168
atan2, 156 int, 40 sscanf, 94
atexit, 175 isalnum, 174 static, 43
atof, 142 isalpha, 175 strcat, 190
atoi, 143 iscntrl, 175 strchr, 197
atol, 143 isdigit, 175 stremp, 197
auto, 32 isgraph, 175 strcoll, 192
break, 33 islower, 175 strepy, 792
bsearch, 209 isprint, 175 strespn, 193
calloc, 132 ispunct, 175 strerror, 194
case, 34 isspace, 175 stritime, 220
ceil, 157 isupper, 175 strlen, 194
char, 34 isxdigit, 175 strncat, 195
Clearerr, 69 labs, 162 strncmp, 195
clock, 216 Idexp, 163 strncpy, 196
const, 34 Idiv, 163 strpbrk, 197
continue, 35 localeconv, 116 strrchr, 197
cos, 158 localtime, 218 Strspn, 198
cosh, 158 log, 164 strstr, 199
ctime, 217 log10, 164 strtod, 144
default, 35 long, 40 strtok, 199
difftime, 217 longjmp, 118 strtol, 145
div, 159 malloc, 133 strtoul, 146
do, 35 mblen, 185 struct, 44
-double, 36 mbstowcs, 186 strxfrm, 200
else, 36 mbtowc, 186 switch, 44
enum, 37 memchr, 187 system, 122
exit, 115 memcmp, 188 tan, 168
exp, 159 memcpy, 188 tanh, 169
extern, 37 memmove, 189 time, 227
fabs, 160 memset, 189 tmpfile, 95
fclose, 69 mktime, 219 tmpnam, 96
feof, 70 modf, 164 tolower, 176
ferror, 77 perror, 118 toupper, 177
fflush, 77 pow, 165 typedef, 45
fgetc, 72 printf, 84 ungetc, 96
fgetpos, 73 putc, 87 union, 46
fgets, 73 putchar, 87 unsigned, 46
float, 38 puts, 88 va_arg, 126
floor, 760 qsort, 210 va_end, 126
fmod, 167 raise, 119 va_ start, 126
fopen, 74 rand, 166 vfprintf, 97
for, 39 realloc, 133 void, 47
fprintf, 75 register, 47 volatile, 47
fputc, 76 remove, 89 vprintf, 98
fputs, 76 rename, 89 vsprintf, 98
fread, 77 return, 47 westombs, 207
free, 132 rewind, 90 wctomb, 207
freopen, 78 scanf, 90 while, 48
frexp, 162 setbuf, 92
fscanf, 79 setimp, 120
fseek, 79 setlocale, 120
fsetpos, 80 setvbuf, 93
ftell, 87 Short, 42
fwrite, 87 signal, 127
- The Waite Group’s

-ANSIC
Essential Guide to
HOWARD W. SAMS & COMPANY
HAYDEN BOOKS

Related Titles
The Waite Group’s The Waite Group’s
C Primer Plus, QuickC™ Bible
Revised Edition Naba Barkakati
Mitchell Waite, Stephen Prata,
and. Donald Martin The Waite Group’s
Turbo C® Bible
The Waite Group’s Naba Barkakati
Advanced C Primer + +
Stephen Prata
The Waite Group’s
Turbo C® Programming
The Waite Group’s
for the PC,
C++ Programming
Revised Edition
(Version 2.0)
Robert Lafore
Edited by The Waite Group

The Waite Group’s The Waite Group’s


Essential Guide to MS-DOS® Bible,
ANSI C Second Edition
Naba Barkakati Steven Simrin

The Waite Group’s The Waite Group’s


Essential Guide to MS-DOS® Developer’s
Microsoft® C Guide, Revised Edition
Naba Barkakati John Angermeyer, Kevin Jaeger, et al

The Waite Group’s The Waite Group’s


Microsoft® C Bible Understanding MS-DOS®
Naba Barkakati Kate O’Day and John Angermeyer

The Waite Group’s The Waite Group’s


Microsoft® C Tricks of the MS-DOS®
Programming for the Masters
PC, Revised Edition John Angermeyer, Rich Fahringer,
Robert Lafore Kevin Jaeger, and Dan Shafer

For the retailer nearest you, or to order directly from the


publisher, call 800-428-SAMS. In Indiana, Alaska,
and Hawaii call 317-298-5699.
The Waite Group's
Essential Guide to

ANSI C
NEVI ort Barkakati

_ HOWARD W SAMS &ComPANY


A Division of Macmillan, Inc.
4300 West 62nd Street
Indianapolis, Indiana 46268 USA
©1988 by The Waite Group, Inc.

FIRST EDITION
SECOND PRINTING—1989 2

All rights reserved. No part of this book shall be reproduced, stored in a retrieval
system, Or transmitted by any means, electronic, mechanical, photocopying,
recording, or otherwise, without written permission from the publisher, No
patent liability is assumed with respect to the use of the information contained
herein. While every precaution has been taken in the preparation of this book,
the publisher and author assume no responsibility for errors or omissions.
Neither is any liability assumed for damages resulting from the use of the
information contained herein.

International Standard Book Number: 0-672-22673-1


Library of Congress Catalog Card Number: 88-62491

From The Waite Group, Inc.:


Development Editor: Mitchell Waite
Editorial Director: James Stockford
Content Editor: Harry Henderson
Managing Editor: Scott Calamar

From Howard W. Sams & Company:


Development Editor: James Rounds
Acquisitions Editor: Richard K. Swadley
Manuscript Editor: Don MacLaren, BooksCraft, Inc., Indianapolis
Designer: Glenn Santner
Illustrator: 77 R. Emrick
Cover Artist: Kevin Caddell
Indexer; Ted Laux
Keyboarder: Lee Hubbard, Type Connection, Indianapolis
Compositor: Shepard Poorman Communications Corp.

Printed in the United States of America

Trademarks
All terms mentioned in this book that are known to be trademarks or service
marks are listed below. In addition, terms suspected of being trademarks or
service marks have been appropriately capitalized. Howard W. Sams & Company
cannot attest to the accuracy of this information. Use of a term in this book
should not be regarded as affecting the validity of any trademark or service
mark.

IBM, IBM PC, and IBM AT are registered trademarks of the International Business
Machines Corporation,
Intel and Intel 8088 and 8086 are registered trademarks of Intel Corporation.
Macintosh is a registered trademark of Macintosh Laboratory, Inc., licensed by
Apple Computers, Inc,
Microsoft, MS-DOS, and QuickC are registered trademarks of Microsoft
Corporation,
MC68000 is a registered trademark of Motorola, Inc.
Turbo C is a registered trademark of Borland International.
UNIX is a registered trademark of AT&T Bell Laboratories,
VAX is a registered trademark of Digital Equipment Corporation.
Contents

Preface ix

Acknowledgments ><

An Overview of ANSI C
1. How to Use This Essential Guide
Organization
What You Need to Know to Use This Guide
Typographic Conventions

An Overview of ANSI C
Introduction
Structure of a C Program NIN
Trigraphs, Multiple Characters,
and Escape Sequences
What ANSI C Means to You

The ANSI C Preprocessor


Preprocessor Directives
File Inclusion
Macro in #include Directives
Token Replacement and Macro Processing
Token Pasting and String-izing Operators
Conditional Compilation
Other Preprocessor Directives

The ANSI C Language


Declarations in C
vi Essential Guide to ANS! C

Data Types in C
New Data Type: enum
Arrays
Pointers
Structures and Unions
Naming Your Own Data Types
Visibility and Lifetime of Variables
New Keywords: const and volatile
Function Declarations
Prototypes
The Type void
Expressions in C
Statements in C
Function Definitions
Complex Return Types for Functions
Pointers to Functions
ANSI C Keywords

The ANSI C Library


Introduction

ANSI C Files and 1/0 o/


Streams and Files in ANSI C 59
Introduction SY:
Streams DS)
Text and Binary Streams 59
Files 60
Buffered Stream I/O 60
Notes on Using the File I/O Routines 62
Streams Already Opened for Your Convenience 62
Global Variables and Constants that Matter 62
Catalog of I/O Routines 62
String I/O 65
Formatted I/O: printf and scanf
Further Reading 67

ANSI! C File 1/0 Routines 69

ANSI C Process Control! and


Memory Management 107
Process Control 109
Introduction 109
Process, Environment, Locale, and Signals 109
Contents Vii

Passing Information Via Environment Variables 109


Signals 109
Nonlocal Jumps in C: longjump and setjump 110
Locale of a Program fell
The Process Control Routines iil
Executing Operating System Commands Te
Terminating a Process 12

Variable Arguments 125


Introduction 125
Using the Variable Arguments Macros WAS)
End of the Argument List 126

70. Memory Allocation 129


Introduction 129
Using the Memory Allocation Routines 129
Requesting Memory 130
Using the Allocated Block 130
Releasing Memory 131
Altering the Size of a Block 131
Further Reading NSyil

IV. ANSI C Data Processing 137

71. Data Conversion 139


Introduction 159
Internal Representations of Data £39
Notes on Using the Data Conversion Routines 141
Data Conversion Routines by Task 142
Other Data Conversion Resources 142

12. Math Functions 149


Introduction 149
Floating-Point Operations 149
Precision: Single or Double 149
Error Conditions in Math Functions Syl
Using the Math Functions 15
The Math Functions by Task WS)
Integer Arithmetic 153
Generating Random Numbers IDS
Further Reading 154

73. Character Classification and Conversion 173


Introduction 173
Vill Essential Guide to ANS! C

Using the Character Classification


and Conversion Functions 173
Classifying and Converting 174

14. String and Buffer bistros 179


Introduction 179
Strings in C 179
Declaring Strings in C 179
Lexicographic Ordering 180
Multibyte and Wide Character Strings 180
Using the String and Buffer Manipulation Routines 181
Finding Length of a String 183
Comparing Strings and Buffers 183
Copying and Appending 183
Parsing a Command Line: Extracting Tokens 184
Conversion Between Multibyte
and Wide Characters 184
Cautions 185

15. Searching and Sorting


Introduction
Searching and Sorting
Sorting
Searching:
Using the Search and Sort Routines
Further Reading

16. Time and Date Functions 213


Using the Time and Date Routines PANG:
Time in Many Forms 214
Printing Date and Time 214
Elapsed Time 215
Cautions 215

Index 225
Preface

The American National Standards Institute (ANSI) began devel-


oping a standard for the C programming language in June 1983
and at this writing the draft proposal is in its third and final pub-
lic review. The ANSI X3J11 committee intends to finalize the
standard by the end of 1988. The first edition of The C Program-
ming Language by Kernighan and Ritchie (Prentice-Hall, 1978)
has always served as the de facto standard (the “K&R standard’’)
for C. The K&R standard did not specify the C library; most
compilers provide a UNIX-compatible library. Now, with the
ANSI standards, there is a formal standard for all aspects of C: the
language, the preprocessor, and the library. This has significant
implications on the portability of C programs: as long as a pro-
gram uses the standard ANSI C constructs and library functions,
it will compile in every standard-conforming implementation.
Many compiler vendors already support the proposed ANSI
standard. If you use Microsoft C 5.1 or Turbo C 1.5 on MS-DOS
systems, you have already used ANSI C. Most other compiler
vendors will conform to the standard in the near future. Learn-
ing ANSI C will give you an important advantage in porting C
programs between different machine architectures. Knowing
the standard will also enable you to identify what is nonstandard
in a given C implementation (such as machine-specific functions
for graphics and I/O). There are other advantages as well. For ex-
ample, “function prototypes,’ introduced in the standard, pro-
vide for strict type-checking, enabling the compiler to catch
errors in the number and type of arguments passed to functions.
The bottom line is that familiarity with ANSI C will soon be a
necessity—the key to writing portable C programs.
This book is a reference guide to ANSI C for intermediate to
professional level programmers. It summarizes the essentials of
the new standard: the new features of the preprocessor, the
changes in the language, and the standard library functions. It
X Essential Guide to ANS! C

features

& An overview of the ANSI C language


& The new features of the ANSI standard C preprocessor
®&Asummary of the standard ANSI C library
> Individual reference entries for the library routines with ex-
amples, and ‘
© Quick page-reference listings, by subject and by alphabetic
ordering, of all library functions
This book is not an introduction to C; refer to the suggested
reading list in Chapter 1 for introductory and advanced books
on GC. This guide assumes familiarity with C and concentrates on
what’s new in ANSI C. Even if you are already familiar with ANSI
C, this guide can serve as a ready reference for the keywords and
the library functions.

Acknowledgments
The guidance of Mitchell Waite and the thoughtful comments of
Harry Henderson have made writing this book a pleasant learn-
ing experience. Thanks to Scott Calamar for making sure I had
the support needed to complete the book on time. Finally, Iam
thankful for the love and support of my wife Leha and my
daughters Ivy and Emily as I worked on yet another book.

Nabajyoti Barkakati

The Waite Group wishes to thank the following people for their
contributions. First, thanks to Naba Barkakati. Naba’s careful cal-
culations made this book the most comprehensive ANSI pocket
guide on the market. Thanks to Harry Henderson for his content
review and careful guidance. Thanks to Jim Rounds for his devel-
opment management, and to Wendy Ford, Marj Colvin, and Don
MacLaren for their management of production and careful edit-
ing. Thanks to Glenn Santner for his pursuit of artistic integrity.
Finally, thanks to Richard Swadley, Jim Hill, and Jim Irizarry of
Howard Sams for making this series possible.

Mitchell Waite
||

An Overview of ANSI C
How to Use This
Essential Guide

Organization
The Waite Group's Essential Guide to ANSI Cis a handy, concise,
and practical guide to the essential aspects of the ANSI C lan-
guage and the library routines. It is organized in four parts. Part I
is an overview of ANSI C and the C preprocessor. In addition to
summarizing the ANSI C library and its keywords, the Guide in-
troduces the new keywords that differentiate ANSI C from the
K&R C, such as volatile and const; new types, such as enum and
void; and the new token-pasting and string-izing operators of
the preprocessor.
Parts II, III], and IV cover the ANSI C library in detail. Each
group of library functions starts with a short tutorial section fol-
lowed by alphabetically arranged reference entries on the
group’s functions. The reference entries are generally presented
in the form shown in Figure 1-1, although not all are used in ex-
ample programs.
Part II describes the file input/output (I/O) routines in the ANSI
C library, in particular, the “stream” model of files in C and how I/O
is performed with the streams. Part III introduces the dynamic
memory allocation facilities in C and explains how to handle ab-
normal conditions occurring during the execution of your pro-
gram. This part presents such routines as malloc and free and
explains how advanced process control routines such as setjmp
and longjmp work. Finally, Part 1V discusses data processing with
the C library, including how to compute math formulas, manipu-
late strings, search and sort, and get the current time and date.

What You Need to Know to Use This Guide


To use this guide you should be familiar with C, but not neces-
sarily knowledgeable about the new ANSI features. If you are

3
4 An Overview of ANSI C

Short description of where © The name of the


the function is used and how library function
it works

: fclose <
Full ANSI prototype:
Describes argument ee
: includes u
deciataiia) se ies Use fclose to close the stream specified by stream. If the stream
files needed “ was open for writing, the content of the buffer associated with the
stream is written to the file (‘flushed’) before the file is closed. If it
was open for reading, unread data in the buffer are discarded.

: oS Syntax
A sample invocation Of —ginctude <stdio.m
the function in a real int fclose(FILE *stream);
fe bse *stream; Pointer to stream to be closed
application

Example Call
fclose(infile);

Returns

Describes the return ae the stream was successfully closed, feof returns a zero; other-
value, if any wise, it returns EOF.
See Also
ae fflush

_ Lists related functions Exaniple


Lines 57 and 58 in Example 7-1 call fclose to close files before
exiting the program.

Where it appears, this


contains an example or
—aline reference to the
end—of-chapter example
in which the function
is used

Figure 1-1. Reference Entry Format

just beginning to learn C and want to start with an awareness of


all ANSI features, the latest book by Kernighan and Ritchie!
would be helpful. Until the ANSI standard C came out, the previ-
ous edition of their book? served as the de facto standard be-
cause Ritchie was the developer of C. This original edition of the
book is often referred to as the “K&R standard.’ Kochan’s
books** provide a more gentle yet still thorough introduction to
the C language. His latest book* covers ANSI C. If you use either
Microsoft C or Turbo C on the IBM PC, you can use one of
Lafore’s books®® as a starting place. Another alternative is the
best-selling introduction to the C language by Waite, Prata, and
Martin’, which is based on UNIX C. You can follow up with the
more advanced guide by Prata®.
Each C compiler has certain features and library functions
that are not covered by ANSI C. You should consult a good refer-
ence book on your C compiler to take full benefit of its features.
The Waite Group’s Microsoft C Bible’, Turbo C Bible’, and
1—How to Use This Essential Guide 5

Quick C Bible" are ideal for this purpose. These books comple-
ment this essential guide by providing specific compiler details,
references to graphics and other compiler-specific functions, ex-
tensive tutorials, and complete example programs.
1. Brian W. Kernighan and Dennis M. Ritchie, The C Program-
ming Language, Second Edition, Prentice-Hall, Inc., Engle-
wood-Cliffs, NJ, 1988, 261 pages.
2. Brian W. Kernighan and Dennis M. Ritchie, The C Program-
ming Language, First Edition, Prentice-Hall, Inc., Engle-
wood-Cliffs, NJ, 1978, 228 pages.
3. Stephen G. Kochan, Programming in C, Revised Edition,
Hayden Books, a Division of Howard W. Sams & Company,
Indianapolis, IN, 1988, 476 pages.
4. Stephen G. Kochan, Programming in ANSI C, Hayden
Books, a Division of Howard W. Sams & Company, Indian-
apolis, IN, 1988, 450 pages.
5. Robert Lafore, The Waite Group’s Microsoft C Program-
ming for the IBM, Howard W. Sams & Company, Indianapo-
lis, IN, 1987, 681 pages.
6. Robert Lafore, The Waite Group’s Turbo C Programming
for the IBM, Howard W. Sams & Company, Indianapolis, IN,
1987, 681 pages.
- 7. Mitchell Waite, Stephen Prata, and Donald Martin, The
Waite Group's C Primer Plus, Revised Edition, Howard W.
Sams & Company, Indianapolis, IN, 1987, 536 pages.
8. Stephen Prata, The Waite Group’s Advanced C Primer++,
Howard W. Sams & Company, Indianapolis, IN, 1986, 502
pages.
9. Nabajyoti Barkakati, The Waite Group's Microsoft C Bible,
Howard W. Sams & Company, Indianapolis, IN, 1988, 808
pages.
10. Nabajyoti Barkakati, The Waite Group's Turbo C Bible,
Howard W. Sams & Company, Indianapolis, IN, 1988, 900
pages.
11. Nabajyoti Barkakati, The Waite Group’s QuickC Bible,
Howard W. Sams & Company, Indianapolis, IN, 1988, 800
pages.

Typographic Conventions
The Waite Group’s Essential Guide to ANSI C uses a simple nota-
tional style. All function names, keywords, and variable names ap-
pearing in text are typeset in ¢talics. Annotation of program code
under the Syntax headings in the reference pages is also italicized.
File names and constants are in uppercase roman. All program list-
ings are typeset in a monospace font for easy reading.
Every effort has been made to reproduce single computer
lines in their entirety. The practical limits of typeset line length,
however, cause an occasional line break. Where this occurs, the
broken portion is placed at the right margin of the second line as
a visual signal.
: Eyer pea
7 8 AES oh catek

a S
» a cal
7 Mts
ae {2fe
an

ARS ES
e Ee Niee y
bah

leetat
& baile

Tae ; \\ eg : ae Hs ,
ie wel . , ae ea gem YS ‘

5 aeurte., 8 ba liad

a idea hia ier ve et


aa fi “Ase abit ehfway PROF eae 0 hes

= P gah pd aes hae i wrapaan


icy bastara! sit ti ie te ¢ fnew
ant
7 < : “3905 i
= we at =, fs 2 ie
cr, . to Tea ite ivianpt SOF.
Milita Giarv eS ae ial :
ie } ~s ? . a 4 : ee: ——— =
- 3 > { é rt tie 2 :

-_ is u

. - ‘> pa ry

et Te
: d ss ”
~S ' " itvrsAs rd “ * iy.
~ “ ed vi “ey > vit

WARGAMES
| aT Raabith ato
Salve) bee rah ag et PHS tt
Oe ae 111th a eS at ng
} an > wy oo cH ah Rkerg NaS) Y “aie
\ WS ered ? dati yi bs tie =

ae fe cose! me iets Teh


Far nT St peter
waa
414 Ast settee Ss Wee
% sui? (ees ee by DRY actihastel Q
ht Svae ag eh . ve Tak es™
: mR Be tee” 7
ee crersgee © Gute
i
> reekSeg= Bi
HOWARD W. SAMS & COMPANY

Bf

DEAR VALUED CUSTOMER:


Howard W. Sams & Company is dedicated to bringing you timely and authoritative
books for your personal and professional library. Our goal is to provide you with
excellent technical books written by the most qualified authors. You can assist us in
this endeavor by checking the box next to your particular areas of interest.
We appreciate your comments and will use the information to provide you with a
more comprehensive selection of titles.
Thank you,

Vice President, Book Publishing


Howard W. Sams & Company

COMPUTER TITLES:
Hardware Programming Languages
O Applei4o =) Macintosh 101 JC 103 OD Pascal Los
OC Commodore tio O Prolog u12 C Assembly to1
COIBM & Compatibles 114 0 BASIC to2 O HyperTalk tia
Business Applications Troubleshooting & Repair
DC Word Processing so1 CZ Computers s05
O Data Base Jo4 C Peripherals sto
C Spreadsheets Jo2
Operating Systems Other
0 MS-DOS kos 0S/2 ki0 CO Communications/Networking mos
0 CP/M koi OCOUNIX ko3 CO AI/Expert Systems tis

ELECTRONICS TITLES:
Amateur Radio 101 OC Instrumentation 105
© Audio 103 : Digital Electronics T11
O Basic Electronics 120 Troubleshooting & Repair
Basic Electricity 121 © Audiosi ~~ O Television sos
Electronics Design 112 2 VCR soi Compact Disc so2
CO Electronics Projects tos CZ Automotive sos
D Satellites tos C) Microwave Oven so3

Other interests or comments:

Name
Title
Company
Address
City
State/Zip
Daytime Telephone No.

A Division of Macmillan, Inc.


4300 West 62nd Street
Indianapolis, Indiana 46268 22673
NO POSTAGE
NECESSARY
IF
MAILED
THEIN
STATES UNITED
BUSINESS REPLY CARD INDIANAPOLIS, IND.
FIRST CLASS PERMIT NO. 1076
POSTAGE WILL BE PAID BY ADDRESSEE
HOWARD W. SAMS & CO.
ATIN: Public Relations Department
P.O. BOX 7092
Indianapolis, IN
46209-9921
An Overview of ANSI C

Introduction
The composition of C—a sparse core with a large support li-
brary—makes it an ideal language for developing software. The
core offers a good selection of data types and control structures
while all additional tasks, including I/O, math computations,
and access to peripheral devices are relegated to a library of func-
tions. This access to all parts of the system enables you to har-
ness the system’s full potential.
The forthcoming ANSI standardization makes C even more
appealing because the draft proposal, now in its final stages of
review, greatly enhances the portability of C programs by defin-
ing all aspects of the language: from the preprocessor to the stan-
dard C library.
This book is designed to help you use ANSI C to its fullest
potential. The focus is on the keywords of the language, the pre-
processor directives, and the library routines. The concepts that
unify each group of related functions are presented in a tutorial
section followed by individual reference entries on each mem-
ber function.
The next four chapters constitute a refresher course on C.
Chapters 3, 4, and 5 describe the ANSI C preprocessor, the ANSI
C language, and the ANSI C library, respectively. The following
discussion of the basic features of C points out how the pro-
posed ANSI standard affects a particular feature. For your con-
venience these notes are marked in the text with this symbol:

Structure of a C Program
As shown in Figure 2-1, a file containing a C program consists of
preprocessor directives, declarations of variables and functions,

i
8 An Overview of ANSI C

a main function, the body of the main function, and other func-
tions. The body of each function, including main, contains ex-
pressions and statements.

# include <stdio.h>
Preprocessor # include <math.h>
directives # definePI3.14159
Variable and # define SQUARE (x) ((x) * (x))

function double area;


declarations >| double area of_circle (double);
Main { main (int argc, char**argy)
function {
double radius; Lo
Body of if (arge <2) exit (0); ~
function radius = atof (argv [1]);
(a statement) area = area_of_circle (radius); __
printf ("Area of circle with radius 4f=%of\n", radius, area);
}
/to ee ee
Other double area_of_circle (double r)
functions ‘ return (4.0 * PI * SQUARE (r));
} ES

Figure 2-1. Structure of a C Program

The “preprocessor” is a facility unique to C. As its name im-


plies, it processes the source file before the compilation begins.
The preprocessor performs several important tasks such as in-
corporating the contents Of another file into the C program (the
#include directive) and replacing one string pattern in the pro-
gram with another (the #defie directive).
“Declarations” state which variables and functions will be
used in the program and what type of data will be used by cach,
Declarations outside the body of the functions are “global?” that
is, they are available to any functions, including code in other
source files. Variables and functions from other files used by
functions in this file are also declared: these declarations are “ex-
ternal” Variables “local” to a function are declared within the
body of the function, Declaring a variable also informs the com-
piler to allocate storage for that variable. Storage is not allocated,
however, for variables being referenced from other files.
The “body ofa funetion” contains declarations that are lo-
cal to that function and statements and expressions that imple-
ment the procedure being performed by that function. The
“statements” control the flow of execution and use the values
provided by expressions, An “expression” is a combination of
operators, variables, and function calls that results in a single
Value. An expression is always part of a statement.
2—An Overview of ANSIC 9

Trigraphs, Multibyte Characters, and Escape Sequences


ANSI C introduces the concept of “‘trigraph sequences” to pro-
vide a way to enter certain important characters from keyboards
that do not have them (non-English keyboards may not have
these characters). Each three-character trigraph sequence begins
with two question marks (??) followed by another character. For
example, if your keyboard does not have a left brace ({), you can
still enter it in your C program using the ??¢ trigraph. The nine
trigraph sequences in ANSI C are summarized in Table 2-1.

Table 2-1. ANSI C Trigraph Sequences

Trigraph Sequence Translation

ae #
22
22/
22)
29" SSS

22
22!
22) Sey
SS

2 y

ANSI C has enlarged the set of “escape” sequences, a se-


quence of characters that starts with a backslash (\). These es-
cape sequences allow you to embed nonprintable characters,
such as \n to denote a new line, in character arrays (“‘strings’’).
The complete list of escape sequences is shown in Table 2-2.
ANSI C also recognizes that the characters of certain lan-
guages may require more than 1 byte to store in encoded form.
Such multibyte characters are allowed in an ANSI C program.
There is also a new ‘“‘wide character” integral data type, defined
as wchar__t, that can hold a multibyte character. The ANSI C li-
brary includes support for multibyte and wide characters.

What ANSI C Means to You


If you have heard of ANSI C, you probably have heard about the
function “prototypes” and the new “token-pasting” and
“string-izing’”’ preprocessor operators (these features are dis-
cussed in the following chapters). These are by far the best publi-
cized elements of the draft ANSI proposal, but there is more to
ANSI C than a few new features. Many well-known members of
the C user community are on the X3J1l committee, which
started its work on standardizing C in June 1983. After each pro-
posed revision is prepared, the standard goes through a public
review period. Therefore, ANSI C reflects the current state OG}
10 © An Overview of ANSI C

Table 2-2. ANSI C Escape Sequences


Sequence Name Meaning When Printed

\a alert Produce an audible alert.


\b backspace Move character position backwards.
\f form feed Move to the beginning of a new page.
\n new line Move to beginning of next line.
\r carriage return Move to beginning of current line.
\t horizontal tab Move to next tabulation position on
this line.
\v vertical tab Move to next vertical tabulation point.
\\ Interpret as a single backslash.
W Interpret as ’
Ww Interpret as “
\? Interpret as ?
\<octal digits> Interpretation depends on printer or
terminal.
\x< hexadecimal digits> Interpretation depends on printer or
terminal.

and many aspects (such as the minimal contents of the library)


are spelled out clearly for the first time.
The K&R standard and the UNIX library are the foundation
for the standard. Although the K&R standard has served well
over the years, many aspects of the language were not specified
precisely so compiler vendors had no “base” definition of the
language or library to use in their implementation. The ANSI
standardization of C provides this base definition. The standard
does not prohibit vendors from including implementation-
specific features and routines, however. To the contrary, the stan-
dard clearly spells out the aspects of the library and the language
that may be implementation dependent, and consequently it
supports portability.
Another important aspect of the ANSI standard is the inclu-
sion of the capability to “internationalize” C programs. The li-
brary specifies routines for country- (or “‘locale”-) dependent
formatting of numeric and currency values. Alphabets requiring
multibyte characters are also supported.
If you have been using C for a while, the standard will not
“break” your existing programs. Of course, new programs using
elements of the standard will not compile in an old compiler.
This is rapidly changing though, with almost all vendors plan-
ning to release ANSI standard-conforming compilers. In the IBM
PC world, Microsoft C 5.1 and Turbo C 1.5 already support many
aspects of the standard, with full compliance promised in the fu-
ture.
The ANSI C Preprocessor

Preprocessor Directives
The preprocessor processes the source text of aprogram file and
acts on commands, called “preprocessor directives,’ embedded
in the text. These directives begin with the character #. Usually
the compiler automatically invokes the preprocessor before be-
ginning compilation, but most compilers allow you to invoke
the preprocessor alone by using compiler options. The prepro-
cessor provides three important services that enable users to
make their programs modular, more easily readable, and easier
to customize for different computer systems: including the con-
tents of a file into a C program (file inclusion), replacing one
string with another (token replacement and macro processing),
and compiling selected portions of aprogram (conditional com-
pilation).

File Inclusion
The ability to include files provides for modularity. Declarations
that are used repeatedly can be kept in a file and included where
needed using #include, which can be used in two forms:

#include <stdio.h>
#include "local.h"

The first and the most common format asks the preprocessor to
read in a named file, in this case a standard C header file, stdio.h,
from the default location for the include files in the system. The
second form of the directive typically asks the preprocessor to
look for local.h in the directory in which the source code resides
(this varies from one compiler to another).

11
12 An Overview of ANSI C

Macro in #include Directives


ANSI C allows you to specify the name of aheader file through a
macro. For example, the code fragment
#if defined(MSC)
#define INCLUDE_FILE_NAME <graph.h>
Helif defined (TURBOC)
H#define INCLUDE_FILE_NAME <graphics.h>
Hendif
#include INCLUDE_FILE_NAME
uses the #if defined and #define directives (to be described
soon) to set the symbol INCLUDE __FILE__NAME to name a file
according to the definition of the symbols MSC and TURBOC.

Token Replacement and Macro Processing


One common use of the preprocessor is to replace all occur-
rences ofa string (or “‘token’’) with another, for example, to de-
fine a symbolic name for a numerical constant. This greatly
improves the readability of the source code. The #define direc-
tive is used for this purpose. This directive can be used in two
forms, one of which takes optional parameters. Here is an ex-
ample:
H#define PI 3.14159
H#define SQUARE(x) ((x)*(x))

The first #define directive simply stipulates that the string 3.


“14159 be substituted at every occurrence of the string P/ in the
source file. The second line defines a macro with one parameter.
A “macro” can have arguments or parameters just as a function
does. In this case, if you use SOUARE(2) in your code, it be-
comes ((2)*(2)) after the preprocessor has performed the
replacement. This macro defines the in-line equivalent of afunc-
tion that squares its arguments, By the way, notice the number of
parentheses in the definition of SQUARE(x). They are absolutely
necessary. To understand why, consider what happens when
you define SQUARE(x) simply as x*x. Suppose you use the
macro in the form SQUARE(y+z) to square the sum of two vari-
ables y and z. After the preprocessor makes the replacements,
the macro will reduce to y+z*y+z which is certainly not what
you wanted. With the definition shown earlier, the macro would
have generated ((y+z) *(y+z)) which gives you the correct re-
sult. Use parentheses liberally when defining macros with argu-
ments that could possibly be ambiguous.

Token Pasting and String-izing operators


The ANSI proposal includes two new preprocessor operators.
The first one, called the “token-pasting”’ operator, enables you
to join one token to another to create a third token. Here is an
example:
Hdefine MSC4 4
3—The ANS! C Preprocessor 13

#define MSC5 5
#define version(x) MSC#H#Hx

When the preprocessor replaces version(5), it first gets the


string MSC##5 which, upon interpretation of the “token-
pasting”’ operator, reduces to the token MSC%5. The preprocessor
finds that this token is defined to be 5 and uses it as the replace-
ment for the macro version(5).
The “string-izing” operator makes a string out of an oper-
and witha # prefix. It does this by putting the operand in quotes.
For example, if you defined and used a macro vd/ue_now as
H#define value_now(x) printf (#x' = Z%d\n'', x)

value_now(counter) ;

the preprocessor generates the statement


printf(''counter'' = Zd\"'n, counter);

as the replacement. Since the ANSI proposal also stipulates that


adjacent strings will be concatenated, this becomes equivalent
to
printf(''counter = Zd\n'', counter);

which illustrates when the “string-izing” Operator is useful.

Conditional Compilation
This feature lets you control which parts of asource file get com-
piled, under which conditions. This capability enables you to
maintain a single set of source files that can be selectively com-
piled with different compilers and in different environments.
Other forms of customization are also possible; for example.
you may decide to insert for debugging prizf statements that
are compiled only if a symbol named DEBUG is defined,
The directives #if, #elif, #else, and #endif are the primary
means of conditionally excluding portions of text from being
used by the compiler. The #ifdef and #ifidef directives, special
cases of the #/f directive, are used more widely than the other
conditional directives. The typical use of these directives is of
the form:

#ifdef DEBUG
printf("Count = %d\n'"', count);
#endif

#if VERSION == 1
#include <version1.h>
#elif VERSION ==
#include <version2.h>
Hendi f
14° An Overview of ANSI C

The first fragment shows the use of #ifdef to compile a printf


statement only if the symbol DEBUG is defined. This can usually
be done at compile time with a compiler option. The second
fragment of code shows how you can include a different header
file depending on the version number of the software.

Other Preprocessor Directives


There are several other preprocessor directives meant for mis-
cellaneous tasks. For example, the #undef directive can be used
to undo the current definition of a symbol. Using #undef
DEBUG removes the definition of DEBUG, for instance. The
#pragma is another special-purpose directive that you can use
to instruct the C compiler to turn on or off certain special fea-
tures. Pragmas vary from one compiler to another. Table 3-1
summarizes the ANSI-specific preprocessor directives.

Table 3-1. ANSI C Preprocessor Directives


Directive Meaning

# operator String-izing operator


Example #define show(x) printf(#x)
show(me); expands to printf(“me”);
## operator _Token-pasting operator
Example #define version(x) MSC##x
version(5) results in the token MSC5
#define Define a symbol or a macro (you can redefine a macro with the same
expression as often as you want)
Example #define twice(x) ((x) + (x))
r=twice(2.0); sets rto 4.0
elif Else-if operator (See example for #if)
#else Else operator (see example for #if)
#endif Mark the end of an #/fdirective
#error Produce diagnostic message
Example #if defined(WRONG
_ OPTION)
#error Recompile with correct option #endif
#if Conditional directive
Example #if !defined(FILE_1_ INCLUDED)
#include <file1.h)
#elif defined(INCLUDE__FILE_2)
#include <file2.h)>
#else
#include <file3.h)
#endif
#ifdef Equivalent to #if defined
3—The ANSI C Preprocessor 15

Table 3-1. (cont.)


Directive Meaning

#ifndef Equivalent to #if !defined


#include File inclusion
Example #include <stdio.h)
#line Set the current line number
#pragma Instruct the compiler
#undeft Remove the definition of a symbol

The ANSI C standard requires that a number of preproces-


sor symbols be predefined by the compiler. Table 3-2 lists these
macros. Note that all such predefined macros must start with a
leading underscore (_) followed by a capital letter or another
underscore. You cannot use #undefto remove the definitions of
these macros.

Table 3-2. ANSI C Predefined Macros

Macro Name Defined to Be

__DATE__ The date of translation of the source file in the form of a string:
“MMM DD YYYY” (such as “Jul 12 1988”)
sya || a A string containing the name of the source file
See INESes The line number of the current source file as a decimal constant
__STDC__ __ The decimal constant 1, indicating that the C compiler conforms to
the ANSI standard
__TIME__ The time of translation of the source file as a string of the form:
“HH:MM:SS”
ne
¥ ) sty
iq. wdttasa
Mlne memes
te Va sTGOF; ve
or { had “ey . ¥ ore +

WZ)

ageer i Pz .
<a ‘ ' ¢.20
a
;
=

' >

( thy

“Ee re ie Aer
wae dhe

~ — ee a a

<2 tere TR ly By od ty veined iy eatoat


SS 9) OS ys v3) 2 ae
iis a & cenliniaa is ow 48%

ae i = a rene OnE et iadisr ood aA?


eta eee * shiMeiiier | tnirres banceb eff
sisi ends tek OAT

—=

a, yee
>

ws

~ >

- Piel

~
a)
=
~r _
The ANSI C Language

Declarations in C
All variables and functions must be declared before they are
used. The declaration ofa variable specifies the “visibility” and
the “lifetime” of the variable, its “type;’ and, where allowed, its
initial value. The declaration of a function specifies its visibility
as well as the type of value it returns.

Data Types in C
There are four basic data types in C: char and int are for storing
characters and integers, and float and double are for floating-
point numbers. The storage sizes for the floating-point types
depend on the convention used to represent floating-point
numbers in binary form. ANSI C uses the Institute of Electrical
and Electronics Engineers (IEEE) format for floating-point num-
bers. A char takes a single byte while an int is the same size as a
word on the underlying machine (for instance, 2 bytes on the
IBM PC and 4 bytes on a DEC VAX). Here are some declarations
using the basic types:
chain 9716;
int COUNEMP IEA is
filtoate a0;
double x, y, 2;

The basic data types can be expanded into a much larger set
with the use of Jong, short, and unsigned qualifiers as prefixes.
The Jong and the short qualifiers are size modifiers. For example,
a long int is 4 bytes long in ANSI C and capable of holding a
much larger value than a short, which is only 2 bytes. The size of
an int is system dependent but it is guaranteed to be at least as
large as a short. The unsigned qualifier is for int and char types
only. Normally, each of these types holds negative as well as pos-

17
18 An Overview of ANSI C

itive values. This is the default signed form of these variable


types. With the unsigned qualifier, you tell the compiler that the
variable will hold positive values only, which allows the variable
to hold maximum values twice as large as signed ones. Here is a
fragment of C code showing the use of the qualifiers.
unsigned char c;
short i, j, small_int; /* Shorthand for "short Tint x7
long large_int; /* Shorthand for "long int"! */
unsigned count; /* Shorthand for "unsigned int'' */
unsigned short ui, uj;
unsigned long ul;
long double xlarge;

Note that when the Jong, short, and unsigned qualifiers are used
with int types, you can drop the int from the declaration. Also,
among the floating-point types, only double takes the Jong qual-
ifier.
The exact sizes of various data types and the maximum val-
ues they can hold depend on the compiler. ANSI C specifies that
these limits be defined in two header files: /imits.b and float.h.
The constants that are defined in these files are summarized later
in this chapter.

New Data Type: enum


The proposed ANSI C standard introduces the type enum,
which holds one integer value from a fixed set of named integer
constants. An enum variable can be used anywhere an int type is
used, The enum type may be used in such a situation as:
enum boolean {false = 0, true = 1, no =0,
yes = 1, off = 0, on = 1};
enum boolean flag = off;

The example shows several properties of enw. The first line de-
fines boolean to be an enumerated type. The list within the
braces shows the constant names that are valid values of an
enum boolean variable. Each constant can be initialized to a
value of your choice and there can be several constants that use
the same value. In this example, the constants false, no, and off
are 0 and true, yes, and on are 1. The second line shows the dec-
laration of an enumerated variable of type boolean. Its name is
flag and it is initially set to the constant off. Note that enum does
not introduce a new basic data type; it simply improves the read-
ability of your programs.
The /ong double is another type of floating-point variable
specified in the ANSI standard. Some older compilers recog-
nized the type /ong float, which is no longer valid under the pro-
posed standard.

Arrays
An “array” is a convenient way to organize a large number of
identical data items. You can declare arrays of any type of data
4—The ANSI C Language 19

item, including structures and types defined by the typedef state-


ment. Arrays can be single- or multidimensional. For example,
char str(81];
int id{100];
double x40], af5][10];

str(Q] = 'A'; /* Set the first character in str to ‘A’ */


id{99] = -1; /* The last element in array id is -1 */
al4][9] = x[1]; /* Copy an element of x into another in a */

declares a character string named str, which can hold 81 charac-


ters; an array of 100 integers named 7d; an array of 40 double
variables x; anda 5x10 two-dimensional array of doubles named
da. Using the syntax of the last three lines any element in an array
can be referenced. Notice that while the dimension of an array
shows the actual number of items, the index goes up from 0. So
an array with 100 elements can have indices ranging from 0 to
99. Also, strings in C are always terminated by a byte containing a
0 (a “null character” denoted by \O). Thus in the example, str
can only hold 80 characters because the last space will be occu-
pied by a null. A two-dimensional array represents a mathemati-
cal entity known as a “‘matrix,’ such as a spreadsheet. Think of
a[5]{10] as a spreadsheet with 5 rows and 10 columns, capable of
holding up to 50 elements. Since memory is not laid out like a
spreadsheet, the actual storage is done by laying out one row af-
ter another in memory. In the notation shown above, the second
dimension denotes the number of columns, or the number of
elements along a row. Because C stores a matrix by row, it al-
ways needs the second dimension in the declaration of amatrix.

Pointers
A “pointer” is a variable that can hold the address of an object
that can be either a variable or a function. If px is a pointer to an
integer you would declare and use it as
int *px, Xx;

px = &x;

The compiler will allocate storage space for an integer x and a


“pointer to an integer” px. The number of bytes necessary to
hold the address will depend on the machine’s addressing
scheme. Of course, you should not use px until it contains the
address of a valid object. The last line shows px being initialized
to the address of the integer variable x (the & operator extracts
the address of x). Following this, you can refer to the value ofx
with *px (“the contents of the object whose address is in px’).
Pointers are useful in many situations. Consider, for ex-
ample, dynamic allocation of memory. In C you can request a
chunk of memory—enough to hold, say, 100 integers. Once the
memory is reserved, you get back the starting address of the
block. Since this address is the only way to reach that memory
20 =An Overview of ANSI C

block, you must store it in a variable capable of holding the ad-


dress of an integer, so you need a pointer to an integer. If you
used px for this purpose, how could you access the different in-
tegers in that block of memory? You would treat it like an array
of 100 integers with the name px. So the last element in the array
is referenced as
*

pxl99]

which is equivalent to
* (pxt+99)

Similarly, the compiler treats the name of an array as a


pointer to the first element of the array (element 0). The differ-
ence between the name of an array and a pointer variable is that
the first is a “constant” without any explicit storage necessary to
hold the address of the array’s first element, whereas the latter is
actually a ‘“‘storage bin” capable of holding the address of any
data of a specific type.
Neither an array nor a function can be returned by a func-
tion. To circumvent this, you can give the address of the array or
the function that you want as the return value. (Pointers to func-
tions are discussed in a later section.)

Structures and Unions


When organizing any type of data, it is preferable to group items
* ina way that makes sense. For example, when storing the names
and addresses of acquaintances, treat the name and the address
of each person as a single data record. In C, you can organize
your data in this manner with “‘structures.” The definition of-a
structure to hold names, addresses, and some other informa-
tion, might look like:
struct financial;
{
double annual_income;
double life_insurance;
double net_worth;
unsigned char investment_strategy;
3;
struct client_info
x
char name[80];
char company [80];
char street [80];
char city(40];
char state[40];
unsigned int zipcode;
struct financial details;
i;
struct client_info client(100];
4—The ANSI C Language 21

This is the data base of an investment counselor. First vou define


a structure called firancial that contains relevant information
about the client's financial situation. Each of the data fields in the
financial structure, such as annual_income and life_insur-
ance, is calleda “member” of the structure. Next vou define the
structure c/ient_ info that contains the name and address of the
client as well as the firancial structure embedded in it. Finally.
the last line declares a 100-element array called client where each
element is a structure of type client__ info. (The fields ofa struc-
ture are accessed by the member selection operator, which is
discussed later.)
“Unions” are declared like structures, but they are uscd
when you want to view the same data item in different ways. For
example, suppose you want to examine a long integer as 4 indi-
vidual bytes or as 2 short integers. This can be done with the
declaration
union
{
long longval;
short shortval(2];
char byteval(4];
+ a_long
in which a@_/ong.longvdl refers to the long integer and a_/ovig.
shortval/O] is one of the constituent short integers.

Naming Your Own Data Types


Using the 4'pedef facility, you can define names for your own
data types. Here are some examples:
typedef unsigned char byte;
typedef struct POINT
{
short x;
short y;
} POINT;
typedef POINT *P_POINT; /* Defines P_POINT as pointer to
POINT */
byte flag;
POINT a, b;
P_POINT p_a = 8a;

This defines byte. POINT, and P— POINTas synonyms for other


data types. The last three lines show the use of the new dats
types. Note that PONTis defined firstand then used in the defi
nition of P_ POINT. In this way, vou can use typedefto declare
complex data types and give them names that are meaningful in
a particular applicauon.
22 ~=An Overview of ANSI C

Visibility and Lifetime of Variables


The “visibility” or the “scope” of a variable tells you which
source files (also called ‘‘modules’’) of your program can use the
variable without declaring it. For example, all variables that are
declared outside the body of functions are global in nature; any
module can use them. On the other hand} declarations within
the function’s body define variables that are visible only inside
that function. Take, for example, the code:

int current_object_id;
.
.

main()
{
int id;

d = create_objectQ;
—+
oe
eo

1;
int create_object()
£
int id;

if(current_object_id == 0) ...

return(id);
2d
The variable current_object_id is declared before any of the
functions (including main), so it is visible in the entire source
file. On the other hand, the variable 7d is local to main( )and to
create__object().Each function has its own copy of id. Changes
made to one copy do not affect any of the others. The variable
current_object__id is not only visible in its source file, it can
even be referenced from other files with the declaration
extern int current_object_id;
This is how global variables are used in C. Since the variable may
be accessed at any time during the execution of the program,
these variables are allocated storage for the life of the program
and are said to have global “lifetimes.”
The qualifier, static, also declares variables with global life-
times, but it restricts the visibility of variables to a single source
file. For example, you could define the variable current_ object
—id as
static int current_object_id = 0;
in a file and use it within the file without altering its globally vis-
ible counterpart with the same name. In other words, you have a
separate storage location for the copy of current_object_id
that is visible only in the file where it is declared.
When a variable (¢d in our example) is defined within the
4—The ANSI C Language 23

body of a function, its storage remains allocated as long as that


function is active. Such variables are said to have “local” life-
times. You can also explictly declare variables with local life-
times by using the reserved words auto and register. Variables
declared inside a function are by default of type auto. The regis-
ter storage specifier is treated as a hint to the compiler to place
that variable in a register, if possible. You can use the register
qualifier only for variables of type int or for pointers that can be
stored in the same number of bytes as an int. Table 4-1 summa-
rizes the information on the visibility and lifetime of declara-
tions in C.

Table 4-1. Scope and Lifetime of C Declarations


Where Declared Keyword _ Visibility Lifetime

Before all functions ina None Entire file plus other Until program ends
file (may be initialized files where variable (Global)
here) is declared extern
Before all functions ina —_extern Entire file plus other Global
file (cannot be initialized files where variable
here) is declared extern
including file where
originally declared
Before all functions ina __ static Only in that file Global
file
Inside a function None Only in that function Until function
or auto returns
Inside a function register Only in that function Until function
returns
Inside a function static Only in that function Global

New Keywords: const and volatile


Two new keywords, const and volatile, are part of the proposed
ANSI standard C. You can use const as a modifier in a declaration
to tell the compiler that the particular data object must not be
modified by the program. This means the compiler must not
generate code that might alter the contents of the location where
that data item is stored. On the other hand, volatile specifies that
the value of a variable may be changed by factors beyond the
control of the program. You can use both keywords on a single
data item to mean that while the item must not be modified by
your program, it may be altered by some other process. The
const and volatile keywords always modify the item immedi-
ately to their right. The information provided by the const and
the volatile modifiers helps the compiler optimize the code it
generates. For example, if you declare and initialize the variable
OAS
const int x = 1024;

the compiler need not generate code to load the value ofx from
24 An Overview of ANSI C

memory. Instead it can use the value 1024 wherever x is used.


However, if you add volatile:
volatile const int x = 1024;

the compiler cannot optimize away any reference to x because


its contents may be changed by some external process. This can
happen when you declare a pointer to an I/O port or video mem-
ory in order to access them from your program.

Function Declarations
A function declaration tells the compiler the type of value the
function returns and the number and type of arguments it takes.
Most programmers are used to declaring functions only when
they return something other than an int. For example, a typical
declaration would be
char *locate_charQ;

This changes under the proposed ANSI standard for C.

Prototypes
The introduction of “function prototypes” is probably the most
significant feature of ANSI C. It requires you to declare the for-
mal parameters that a function takes as well as the return value. If
our sample function /ocate__char() takes a string and an integer
as an argument, the ANSI-style prototype for this function is
char *locate_char(char *, int);

with the formal argument list shown with the type of each pa-
rameter only. You may include an identifier for each formal pa-
rameter, such as
char *locate_char(char *str, int c);

In this case, the prototype can look exactly like the first line in
the definition of the function, except that in the prototype you
terminate the line with a semicolon.
Prototypes help the compiler check function arguments
and generate code that uses a faster mechanism for passing argu-
ments. Since the prototype tells the compiler the exact number
and type of arguments to expect, it can catch any mistakes you
might make when calling a function, such as passing the wrong
number of arguments (when the function takes a fixed number
of arguments), or passing a wrong type of argument to a func-
tion,
What do you do when a function does not return anything,
or when it does not accept any parameters? To answer this, we
have to describe a new data type that is part of the ANSI C pro-
posal.

The Type void


The ANSI standard adds to C the type void, which is useful for
declaring functions that return nothing and for describing
4—The ANSI C Language 25

pointers that can point to any type of data. For example, if a func-
tion does not return anything, say the exit function in the library,
it can be declared as
void exit(int);

On the other hand, if a function does not accept any formal pa-
rameters, its list of arguments is represented by the word void:
int getchar(void);

The use of a pointer to a void as a data type is appropriate for


functions that manipulate contiguous arrays of bytes (“‘buffers’’)
in memory. For example, when you request a certain number of
bytes from the memory allocation routine malloc, you can use
these locations to store any data that fits the space. In this case,
the address ofthe first location of the allocated block of memory
is returned as a pointer to a variable of type void with
void *malloc(size_t size);

as the prototype. By the way, size_t is a new standard data type


in ANSI C, defined to be the result of the sizeof operator. Most
library routines that require the size of adata item use the size_t
type.

Expressions in C
An “expression” in C is a combination of variables, function
calls, and operators that result in a single value. For example,
(strlen(a_string) * sizeof(char) + 1)

is an expression that yields a value of type size_t, involving a


function call, strlen(a__string), and the operators sizeof, a multi-
plication (*), and an addition (+).
Since operators are at the heart of expressions, Table 4-2
summarizes the operators available in C. Each operator is shown
with an example and a short explanation of its usage.

Table 4-2. Operators in C


Operator Name Example Explanation

Arithmetic Operators

* Multiplication x*y Multiply x and y


/ Division x/y Divide x by y
% Modulo x”y Divide remainder of x by y
+ Addition X+V Add x and y
- Subtraction x-y Subract y from x
++ Increment X+ + Increment x after use
-- Decrement —X Decrement x before use
26 An Overview of ANSI C

Table 4-2. (cont.)


Operator Name Example Explanation

= Negation -X Negate the value of x


ry Unary Plus +X Value of x (new in ANSI C)

Relational and Logical Operators

») Greater than X)>y 1 if x exceeds y, else 0


ie Greater than or equalto x)=y 1 if x is greater than or equal
to y, else 0
« Less than xy 1 if y exceeds x, else 0
(= Less than or equal to xX(=y 1 if x is less than or equal to
y, else 0
== Equal to X==y 1 if x equals y, else 0
!= Not equal to x!l=y 1 if x and y unequal, else 0
| Logical NOT Ix 1 if xis 0, else 0
&& Logical AND x&&y 0 if either x or y is 0
iad Logical OR x1 Y 0 if both x and y are 0
Assignment Operators

= Assignment X=; put value of y into x


0= Compound assignment x 0= y; equivalent to x = x Oy;
where 0 is one of the
operators: + -* / % << ))
coat

Data Access and Size Operators

[] Array element x[0] first element of array x


Member selection S.X member x in structure s
= Member selection px member named x in a
structure that p points to
a Indirection *D contents of location whose
address is in p
& Address of &Xx address of x
sizeof Size in bytes sizeof(x) size of x in bytes

Bitwise Operators
~ Bitwise complement ~X flip 1 bits to 0 and 0 bits to 1
& Bitwise AND xay bitwise AND of x and y
} Bitwise OR Xly bitwise OR of x and y
A Bitwise exclusive OR xy value with 1s at bits where
corresponding bits of x and y
differ
«« Left shift xX «C4 X shifted to the left by 4 bit
positions
»» Right shift x)>)4 X Shifted to the right by 4 bit
positions
4—The ANSI C Language 27

Table 4-2. (cont.)


Operator Name Example Explanation

Miscellaneous Operators

(a) Function malloc(10) call malloc with argument 10


(type) Type cast (double)i i converted to a double
he Conditional x1?x2: - if x1 is not 0, x2 is evaluated,
x3 else x3 is evaluated
; Sequential evaluation i++, first increment i, then
j++ incrementj

Operator Precedence
Typically, you use several operands and operators in many state-
ments of your program. For example, if you write
*ptr(2]

is the result the value to which ptr[2] points, or is it the third ele-
ment from the location whose address is in ptr? To determine
this, you need to know the order in which operators are applied.
This is specified by the operator’s ‘precedence,’ which is sum-
marized in Table 4-3. Operators with highest precedence—those
that are applied first—are shown first. The order in which opera-
tors at the same level get evaluated (‘‘associativity’’) is also
shown. If you consult the table, you will find that the [ ]operator
has precedence over the * operator. So in our example, ptr[2] is

Table 4-3. Operator Precedence and Associativity in C


Operator Type Operators Associativity

Expression (2)[ele Left to right


Unary -~!*&+4+ — sizeof (type) Right to left
Multiplicative */% Left to right
Additive +7 Left to right
Shift «(>> Left to right
Relational C=) = Left to right
(inequality)
Relational (equality) ==/= Left to right
Bitwise AND & Left to right
Bitwise XOR as Left to right
Bitwise OR 4 Left to right
Logical AND && Left to right
Logical OR 1} Left to right
Conditional Ue Right to left
Assignment = *=/=%h= +=-= ((= ))= & Rightto left
|
|

Sequential Evaluation , Left to right


28 An Overview of ANSI C

evaluated first and then the “indirection” operator is applied, re-


sulting in the value whose address is in ptr([2].

Statements in C
Statements control the flow of execution of a C program. A
“statement” consists of keywords, expressions, and other state-
ments. Each statement ends with a semicolon. Here are some
simple C statements:
i /* a null statement */
x=y=2;
Xt+7

iffy > 0) x /= y; /* x will be x/y */


The entire body ofa function that is enclosed in a pair of braces
({....}) is considered a single statement in C. Known as
“blocks,” such compound statements can have local variable
declarations and statements.
Here is a summary of C statements, in terms of the
keywords.

_ continue;

‘Example:

- do-while
loop —
Example:
4—The ANSI C Language 29

for loop For (exprl; expr2; expr3 (statements)


Evaluates exprl once, then expr2, and so on.
The <statements) are executed as long as
expr 2 is true (nonzero). After each pass
through the loop, expr3 is evaluated. Loop
stops when expr2 becomes false (0).
Example: for (i=0, sum=0; i < 11; i++) sum += i;
/* Computes sum of integers O through 10 x/

goto Transfers control to statement designated LA-


Statement BEL.
Example: ifGi ==0) gotoL1; a=xlil;
Ll: xlil = ¢;

if if (expr1) statement! else statement2


Statement Executes statement if expri is nonzero. Oth-
erwise expr2 is executed. The else clause is
optional and can be omitted.
Example: if Cy !=0) ee:
else
x = 0;

Null Indicates, with a solitary semicolon, that


statement nothing happens. Used, for example, when
all processing is to be done in the loop ex-
pressions rather than the body of the loop.
Example: for (i=0; strli] !='\O"; i++) ; /* Null
statement */

return Stops executing the current function and re-


turns control to the calling function. A single
value can be passed back.
Example: return (answer);

switch Switch (expr)


{
case valuel: statement _block_1
case value2: statement_block2

default: statement default


30 =An Overview of ANSI C

Ifexpr evaluates tovier statement block ©


_1 is executed. If it is equal to value2, state-
ment__2 is executed. If the value does not
match any of the case statements, contol
passes to the block statement default. Each
statement block typically ends with a break
statement.
Example: switch Cinterrupt_id) ¢
case MDMSTATUS: s_ms();
break;
case TXREGEMPTY: s_trmtyQ;
a break; Z
case RXDATAREADY: s_rdaQ);
break;
case RLINESTATUS: s_rlsQ);
break;
default: |

whileloop _—_—while (expr)statement_ block


The statement _block is executed repeatedly
as long as expr evaluates to a nonzero value.
Example: while (i >=0) /* Copy one string onto another */
t
- strlfi) = stretil;
ji--:
¢

Function Definitions
The building blocks of C programs, “functions” are indepen-
dent collections of declarations and statements you mix and
match to create stand-alone applications in C. Each C program
has at least one function: the main function. The library speci-
fied in ANSI C consists mainly of functions (in addition to quite a
few macros). For the most part, developing software in C is a
matter of writing functions.

Complex Return Types for Functions


The definition of a C function starts with the type of value re-
turned by the function; the function’s name; and, in parenthe-
ses, the list of arguments that the function accepts. For example,
a function getmax that returns the larger of two double variables
can be declared as:
double getmax( double a, double b)
4—The ANSI C Language 31

{
if ( a >= b)
return (a);
else
return (b);
}

If you wanted the definition of this function to be localized to


the source file where it appears, you could use the keyword
static as a prefix on the line declaring getmax. If you do not use
Static, the function is visible outside the source file.
Sometimes you need to return more complicated data types
from your function. Normally these complicated types are
pointers to one data type or another, but they could also be
structures because the proposed ANSI C standard allows a func-
tion to return a structure. When declaring complex return types,
you can use the typedef statement to your advantage. Suppose
you want to write a function that accepts a pointer to an array of
three double variables and its return value is of the same type. In
notation cryptic enough to confuse even an expert, the function
process3double can be declared as
double (*process3double(double (*)(3]))([3]; /* Prototype */

double (*process3double(double (*x)[3]))[3] /* Definition */


{
return (x);
:
On the other hand, with a judicious use of typedefs you can re-
write the example as
typedef double DBL3(3]; /* DBL3 is array of 3 doubles */
typedef DBL3 *PDBL3; /* PDBL3 is pointer to DBL3 */
PDBL3 process3double(PDBL3); /* Prototype */

PDBL3 process3double(PDBL3 x) /* Definition */


{
return (x);
}
The first approach takes less space, but the second method is
certainly more readable than the first.

Pointers to Functions
A function cannot return an array or another function directly.
Also, an array cannot have functions among its elements. This is
not a problem because you can always use pointers to functions
in places where functions themselves are not allowed. Declaring
a pointer to a function is similar to declaring a pointer to a vari-
32 =An Overview of ANSI C

able. For example, you can declare a pointer to a function that


accepts two int arguments and returns an int as
int (*p_func) (int, int);

Once p__func is initialized to point to an appropriate function,


its invocation will look like the declaration above:
z = (*p_func)
(x, y);

Again, the typedef keyword can come to your rescue when


you have to declare something complicated, say an array of 5
functions, each like the process3double function of our earlier
example. Using typedef, the declaration will be as simple as
/* First define a synonym for a pointer to this function */
typedef PDBL3 (*P_F_PDBL3)(PDBL3);
/* Now declare the array of functions */
P_F_DBL3 = funclist(5];
funclist[0] = process3double;

In this example, the first element of the array funclist is even ini-
tialized to the function process3double, which is defined in our
previous example.

ANSI C Keywords
Finally, here is a list of all the keywords of ANSI C. Individual
_teference entries for the keywords follow.

auto double int struct :


break else long — oswiich
case enum register typedef
char extern return union
const — float short unsigned
continue for signed void
default goto sizeof volatile
do oF Static _ | -while
*

> auto

Purpose
Use the auto storage class specifier to declare temporary vari-
ables. These are created when entering a block statement and
destroyed at exit. Local variables of a function have the auto
storage class by default.

auto
4—The ANSI C Language 33

Example
In this example, the variables 7, limit, and sum are created only
when the if statement is ttue— when the user presses a C.
#include <stdio.h> main)
{
Tint cs
c = getchar();
if(c == 'C')
{
auto int i, limit, sum;
printf(''Sum from 1 to ?!"');
scanf(" Z%d",&limit);
/* Compute sum from 1 to limit */
for(i=0, sum=0; i <= Limit; sum += i, i++);
printf('\nSum from 1 to %d = %d\n'', Limit, sum);

See Also

extern, register, static

break <4
Purpose
Use break to exit from the innermost do, while, orfor loop. It is
also used to exit from a switch statement.

Example
This code fragment adds the numbers from 1 to 10 in an endless
loop. It uses break to exit the loop.
sum = 0;
ij = 0;
while(1)
nf
sum += 1;
Ticteste
if(i > 10) break;
}

See Also

case, do, for, switch, while

break
34 An Overview of ANSI C =

———___e

Pm case

Purpose
Use case to label cases in a switch statement.

Example
See switch for an example.

See Also

default, switch

> char

Purpose
Use char to declare character variables and arrays.

Example
The example declares a character, a pointer to a char, and an ar-
ray of characters.
.char c, *p_c, stringl80);

See Also

double, float, int, long, short, signed, unsigned

> const

Purpose
Use the const qualifier to indicate that the variable that follows
may not be modified by the program. This means that you can-
not assign a value to that variable, increment it, or decrement it.

Example
This example declares that the value of x, the contents at the lo-
cation whose address is p_i, and the pointer p_.c_i must not
be changed by the program’s code.
const short x; /* x is constant */
const int *p_i; /* *p_i is constant */
int *const p_c_i; /* pointer p_c_i is constant */

const
4—The ANSI C Language 35

See Also
volatile

LN i ia a a cae ng hol
continue 4

Purpose

Use continue to skip execution of a loop. It is equivalent to exe-


cuting a goto to the end of the loop. The continue statement af-
fects the innermost loop in which it appears.

Example
This for loop is skipped when 7 is 5, giving us the sum of the
numbers from 1 to 10, excluding 5.
for(i=0, sum=0; i <= 10, i++)
{
if(i == 5) continue;
sum += i;
}

See Also
for, if, while

default <4

Purpose
Use default as the label in a switch statement to mark code to be
executed when none of the case labels match the switch expres-
sion.

Example
See switch for an example.

See Also
case, switch

do<4

Purpose
Use do with while to form iterative loops of the kind
36 =An Overview of ANSI C

do statement while(expression);

in which the statement is executed until the expression evaluates


to zero. The expression is evaluated after each execution of the
statement.

Example
The do loop shown here continues until 7 exceeds 10.
do
{
sum += 7;
a
}
while(i >= 10);

See Also
for, if, while

> double

Purpose
Use double to declare double-precision floating-point variables
and arrays.

Example
This example declares a double, a pointer to a double, and an
array of doubles.
double d, *p_d, dvars[80];

See Also

char, float, int, long, short, signed, unsigned

> else

Purpose

Use else with 7f to control the flow of execution by a construct of


the form
if (expression) statement_1 else statement_2

in which statement_1 is executed if the expression is not equal


to zero; otherwise, statement_2 is executed.

else
4—The ANSI C Language 37

Example
See if for an example.

See Also

ai

enum <4

Purpose
Use enum to define an integral data type that can take its values
from a list of enumerated constants. The declaration is of the
form

enum identifier { enumerated list };


enum identifier vari, var2;

in which the first line shows the definition of an enum type


named identifier and the second line declares two variables
varl and var2 of type identifier. The example shows the form
of the enumerated _list in the definition of an enum type.

Example
This code makes traffic_signal the name of an enumerated
type, and it declares signal_1 as a variable of that type and
p—signal as a pointer to traffic__signal. You can see that the def-
inition of the enum also enables you to initialize the entries in
the enumerated list.
enum traffic_signal {red = 10, yellow = 20, green = 30};
enum traffic_signal signal_1, *p_signal;

See Also
typedef

extern <4

Purpose
Use extern to tell the compiler that a variable or a function is de-
fined in another module (a separate file) and that you want to use
it in the current module. The variable or function cannot have
been declared with the static or extern qualifiers.

extern
38 An Overview of ANSI C

Example
In this example the variables current _state and state_table are
shared among FILE 1 and FILE 2. They are defined in FILE 1 and
declared to be extern in FILE 2.
(ke ap aS 1 */
int current_state, state_table[MAXSTATE] [MAXSYMB];
extern void next_state(int in_symbol);
main()
{
int in_symbol;

current_state = 0;
next_state(in_symbol);

[te 2 Se bal3 2 */
void next_state(int in_symbol)
a
extern int current_state, state_table[MAXSTATE] [MAXSYMB];
if ( current_state ==0).

current_state = state_table[current_state]Lin_symbol];

_ See Also
static

> float

Purpose
Use float to declare single-precision floating-point variables and
arrays. :

Example
This example declares a float, a pointer to a float, and an array of
floats.
float f, *p_f, fvars{100];

See Also

char, double, int, long, short, signed, unsigned

float
4—The ANSI C Language 39

for <4

Purpose
Use for to form iterative loops of the type
for (expression_1; expression_2; expression_3) statement

in which the expression_1 is evaluated once at the beginning of


the loop, and the statement is executed until expression _2 eval-
uates to zero. The third expression, expression _3, is evaluated
after each execution of statement.

Example
The for loop shown here adds the numbers from 1 to limit, all
inside the third expression in the for loop.

for(i=0, sum=0; i <= Limit; sum += i, i++);


printf(''\nSum from 1 to %d = %d\n", limit, sum);

See Also
break, continue, if, switch

goto <@

Purpose
Use goto to jump unconditionally to a label in the current func-
tion.

Example
if (system_price > 6000.0) goto TooExpensive;

TooExpensive:
seek_alternative(;

See Also
break, continue

if <

Purpose
Use if to excute code only when certain conditions hold. You
can use if alone or with else to form constructs such as

if
40 An Overview of ANSI C

if ( expression ) statement

or
if ( expression ) statement_1 else statement_2

in which the statement following the if is executed if the expres-


sion is not equal to zero. When an else is present, statement_ 2 is
executed if expression is equal to zero.

Example
This example shows how to use if and else to pick the smaller of
two variables.
: if ( x <= y) smaller = x;
else smaller = y;

See Also

else

> int

Purpose
Use int to declare integer variables and arrays. To declare an inte-
" ger of a specific size, use the size qualifiers short and long. The
size of an int is implementation dependent but it is guaranteed to
be larger than a short.

Example
int i, xf100);
See Also

char, double, float, long, short, signed, unsigned

> long

Purpose
Use long as a size qualifier for int and unsigned int variables.
Note that /ong alone means signed long int. A long qualifier indi-
cates that the integer data type is 4 bytes in size.

Example
This example shows the declaration of a Jong int and an un-
signed long int.

long
4—The ANSI C Language 41

long filepos;
unsigned long timer_tick;

See Also

char, double, float, int, short, signed, unsigned

register <4

Purpose
Use register as a storage Classifier for integer data types to inform
the compiler that access to that integer should be as fast as pos-
sible. (Some compilers may use a CPU register to store that vari-
able.)

Example
register int 1;

See Also

auto, extern, static

return <<

Purpose
Use return to terminate execution of the current function and
return control to the caller. If the function returns a value, use
the statement return (expression) to return the value repre-
sented by the <expression).

Example
This function returns the maximum of two integers.
int findmax(int a, int b)
{
if(a >= b)
return a;
else
return b;
}

See Also
break, continue, goto

return
42 An Overview of ANSI C e

> short

Purpose
Use short as a size qualifier for int and unsigned int variables.
Note that short alone means signed short int. A short qualifier
indicates that the integer data type is 2 bytes in size.

Example
This example shows the declaration of a short int and an un-
signed short int.
short offset;
unsigned short array_index;

See Also

char, double, float, int, long, signed, unsigned

> signed

Purpose
_Use the signed qualifier to indicate that data stored in an integer
type (int or char) is signed. For example, a signed char can take
values between —127 and +127 whereas an unsigned char can
hold values from 0 to +255. The int and char types are signed by
default.

Example
int i; /* signed by default */
Signed long int x;

See Also
char, double, float, int, long, short, unsigned

> sizeof

Purpose
Use the sizeof operator to get the size of a data element in bytes.
You can use it to determine the size of a structure, for example,
so that you can call calloc to allocate an array of them. Another
use of sizeofis to compute the number of elements in an array.

sizeof
4—The ANSI C Language 43

Example
This code fragment uses sizeof to get the size of a structure in
order to use it as an argument to calloc. It also uses sizeof to ini-
tialize the count of elements in an array.
struct mytype
{
char firstname(20];
char lastname(20];
};
short offsets{] = {-1, 10, 20, 32, 48};
short n_offsets = sizeof (offsets) /sizeof(offsets[0]);

p-mytype = (struct mytype*)calloc(100, sizeof(struct mytype));

See Also

typedef

static <¢

Purpose
Use static to localize the declaration of a data item or a function
to a program module (file). You can use this to “hide” functions
and data from other modules. Static variables are stored perma-
nently; they retain their values for the life of the program.

Example
In this example each file has its own copy of the variable current
_ index. Each copy is initialized once and each retains its last-
stored value throughout the execution of the program.
[xe (Pct EOE 1 */
static int current_index = 0;
main()
{

current_index = 1;

}
(ke (pei 1G 13 2 */
static int current_index = 0;
void some_function(void)
{
jf ( current_index ==0) ..

current_index = 2;

static
44 An Overview of ANSI C

See Also

auto, extern

> struct

Purpose
Use struct to group related data items together, and give the
group a name to which you can refer later. The general form is
struct structure_name
x
type item_1;
type item 2;

Ds
struct structure_name struct_1, struct_2;

in which the first declaration defines a structure, structure_


name, and the second one declares two structures, struct_1
AMC Siete

Example
This example defines a structure to be used in a linked list. It
contains several members, including one that is a pointer to it-
self.
struct node
{
int node_type;
char node_namel16];
struct node *next;
3;
struct node *p_node, first_node;

See Also

union

SS
SS

> switch

Purpose
Use the switch statement to perform a multibranching that de-
pends on the value of an expression. The syntax is
switch (expression) statement

Inside the statement use case labels to indicate what to do for

switch
4—The ANSI C Language 45

each expected value of the expression. Use break to separate the


code of one case label from another and default to mark code to
be executed if none of the case labels match the expression.

Example
The switch statement here executes different routines depend-
ing on the value of command. Note the use of break statements
to keep the execution from falling through one case label to an-
other.
switch (command)
{
case 'Q': exit(0);
case 'C': connect();
break;
case 'S': sendfile();
break;
case 'P': newparams();
break;
case '?': showparams();
break;
case 'H': printf (helplist);
break;
default: printf('"'Unknown command! \n"");
}

See Also
break, case, default

typedef <

Purpose
Use typedefto give anew name to an existing data type. The syn-
tax is
typedef existing_type new_name;

For example, typedef int (*P_FUNC)); enables you to use


P__FUNC as a data type meaning “pointer to a function return-
ing an integer.’ You can use typedef to build up complex declara-
tions easily.

Example
See the tutorial section for examples that use typedef to simplify
the declaration of complex data types.

See Also

enum

typedef
46 = An Overview of ANSI C

> union

Purpose
Use union to allocate storage for several data items at the same
location. The declaration of union is like that of struct, except
that in a wnion all data items in the declaration share the same
storage location.

Example
This example declares a wnion that stores a short in a location
with an array of two characters. Each individual byte of the short
stored in the union x can be accessed by x. bytes/[O] and x.
bytes[1].
union short_u
{
short sh_val;
char bytes(2];
};
union short_u x;

See Also

struct

> unsigned

Purpose
Use the unsigned qualifier with integer data types (char, int,
short int, and long int) to tell the compiler that the variable will
store non-negative values only. This effectively doubles the max-
imum value that can be stored in that variable. Another useful
feature is that arithmetic involving unsigned integers cannot
overflow because all operations are performed modulo a num-
ber that is one greater than the largest value that can be repre-
sented by that unsigned type.

Example
Here are some declarations of unsigned variables.
unsigned char data(1000];
unsigned long file_pos;
unsigned i; /* equivalent to unsigned int i */

See Also

char, double, float, int, long, short, unsigned

unsigned
4—The ANSI C Language 47

SibENON SEE SS el
void <4

Purpose
Use the data type void to indicate the nonexistence of a return
value or of arguments in a function definition and prototype.
You can use void * to declare a pointer to any type of data ob-
ject.

Example
void a_function(void *buffer);
int get_something(void);
extern void *p_buf;

See Also

char, int, double, float

volatile <4

Purpose
Use the volatile type qualifier to inform the compiler that the
variable that follows may be modified by factors outside the con-
trol of your program. For example, the register in the real-time
clock in your system is such a variable. The volatile qualifier
warns the compiler that actions performed on volatile data must
not be “optimized out.” You can use the qualifier const together
with volatile to qualify objects that must not be changed by
your program, yet may change due to external factors.

Example
This code shows the declaration of the register in a real-time
clock. It says that our code cannot change the content (*p_rt_
clock), but that the content may change by itself. We are free,
however, to modify the pointer p_rt_clock to point to another
long int.
const volatile long *p_rt_clock = CLOCK_ADDRESS;

See Also

const

volatile
48 An Overview of ANSI C

> while

Purpose
Use the while statement to construct loops such as
while (expression) statement

in which the statement is executed until expression evaluates to


zero. The expression is evaluated after each execution of the
statement.

Example
This while loop adds the numbers 1 through 10.
sum = 0;
i = 0;
while(i <= 10)
{
sum += i;
atte
}

See Also

do, for, if, switch


The ANSI C Library

Introduction
The proposed ANSI standard for C defines all aspects of the lan-
guage, including the library that makes C unique. The proto-
types of the library routines and all necessary preprocessor
constants and data structures are defined in a set of standard
header files. Tables 5-1 and 5-2 show the minimal contents ofthe
library that must be present in an ANSI standard-conforming C
compiler. Table 5-1 lists the standard header files and summa-
rizes their contents. Table 5-2 lists all macros and data types
defined in the standard header files in ANSI C. Almost all com-
mercial C compilers have additional routines in their libraries.
For example, the Turbo C 1.5 and Microsoft C 5.1 compilers,
available for MS-DOS systems, include library routines for
graphics and access to DOS functions and even the standard
header files have additional routines in them.

Table 5-1. Standard Header Files in ANSI C

Header File
Name Description

assert.h Defines the assert macro and NDEBUG symbol. Used for program
diagnostics.
ctype.h Declares character classification and conversion routines.
ermo.h Defines macros for error conditions, EDOM and ERANGE, and the
integer variable errno.
float.h Defines symbols for the maximum and minimum values of floating-
point numbers.
limits.h Defines symbols for the limiting values of all integer data types.
locale.h Declares functions necessary for customizing a C program to a
particular locale. Defines the /conv structure.
math.h Declares the math functions and the HUGE VAL constant.

49
50 =An Overview of ANSI C

Table 5-1. (cont.)


Header File
Name Description

setjmp.h Defines the jmp__ buf data type used by the routines setjmp and
longjmp.
signal.h Defines symbols and routines necessary for handling exceptional
conditions.
stdarg.h Defines the macros that facilitate handling variable-length argument
lists.
stddef.h Defines the standard data types ptrdiff_t, size_t, wehar_t, the
symbol NULL, and the macro offsetof.
stdlib.h Declares the utility functions such as the string conversion routines,
random number generator, memory allocation routines, and process
control routines.
string.h Declares the string manipulation routines.
time.h Defines data type time__t, the tm data structure, and declares the
time functions.

Table 5-2. Macros and Data Types in ANSI C Library

Macro or Where
Data Type Defined Description

BUFSIZ <stdio.h> Size of buffer used by setbuf


CHAR _ BIT <limits.h)> Maximum number of characters in a
char
CHAR_MAX <limits.h)> Maximum value of a char
CHAR_ MIN <limits.h) Minimum value of a char
CLK_TCK <time.h) Number of clock ticks per second
returned by the clock function
DBL_DIG (float.h)> Number of significant decimal digits in
a double value
DBL_EPSILON <float.h> Smallest positive double value x such
that 1+x/= 1
DBL_MANT_ DIG (float.h) Number of base FLT__RADIX digits in
the mantissa of a double
DBL_MAX <float.h> Maximum representable finite value that
can be stored in a double
DBL__MAX_ 10__ EXP (float.h> Maximum integer such that 10 raised to
that power is representable in a double
DBL__MAX_ EXP (float.h> Maximum integer such that
FLT__RADIX raised to that power is
representable in a double
DBL_ MIN (float.h> Minimum positive floating-point number
that can be stored in a double
DBL_MIN_ 10_EXP (float.h) Minimum negative integer such that 10
raised to that power is representable in
a double
5—The ANSI C Library 51

Table 5-2. (cont.)


Macro or Where
Data Type Defined Description

DBL__MIN_ EXP (float.h> Minimum negative integer such that


FLT _ RADIX raised to that power minus
1 is representable in a double
EDOM <errno.h)> Constant to indicate invalid argument
(or “domain”) error
EOF <stdio.h) A negative integer constant that
indicates “end-of-file”
ERANGE <errno.h) Constant to indicate unrepresentable
result (or “range”) error
EXIT_FAILURE <stddef.h)> Status code that can be used with exit
to indicate that the program ended with
an error
EXIT_ SUCCESS <stddef.h> Status code that can be used with exit
to indicate that the program executed
successfully
FILE <stdio.h> A data type capable of holding all
information needed to perform file 1/0
FILENAME
_ MAX <stdio.h> Maximum length of a file name string
FLT_DIG <float.h> Number of significant decimal digits in
a float value
FLT__ EPSILON <float.h> Smallest positive float value x such that
1+4X!= 1
FLT__MANT_ DIG <float.n)> Number of base FLT__ RADIX digits in
the mantissa of a float
FLT__MAX <float.h> Maximum representable finite value that
can be stored in a float
FLT__MAX__ 10__EXP <float.h > Maximum integer such that 10 raised to
that power is representable in a float
FLT __MAX_ EXP <float.h> Maximum integer such that
FLT_RADIX raised to that power is
representable in a float
FLT
__MIN (float. Minimum positive floating-point number
that can be stored in a float
FLT__MIN_ 10__EXP <float.n> Minimum negative integer such that 10
raised to that power is representable in
a float
FLT__MiN_EXP (float.h > Minimum negative integer such that
FLT __RADIX raised to that power minus
1 is representable in a float
FLT
_ RADIX <float.h> Radix of the exponent representation
(usually 2 for binary exponent)
FLT__ROUNDS <float.h> Constant to indicate how floating-point
values are rounded (-1 =
indeterminate, 0 = toward 0, 1 = to
nearest representable value, 2 =
toward positive infinity, and 3 = toward
negative infinity)
52 An Overview of ANSI C

Table 5-2. (cont.)

Macro or Where
Data Type Defined Description

FOPEN __MAX <stdio.h) Minimum number of files that can be


opened simultaneously
HUGE_ VAL <math.h)> A double expression that evaluates to a
very large value (for use as return value
by math functions when computed
result is too large)
INT__MAX <limits.n> Maximum value of an int
INT_ MIN <limits.h> Minimum value of an int
_\OFBF <stdio.h) Constant for “full buffering” (see
setvbuf)
_IOLBF <stdio.h> Constant for “line buffering” (see
setvbuf)
_IONBF <stdio.h> Constant for “no buffering” (see
setvbuf)
L_tmpnam <stdio.h> Size of char array that is large enough
to hold temporary file names generated
by tmpnam
LC_ALL <locale.h) Constant to indicate all locale-specific
characteristics of the program
LC_ COLLATE <locale.h)> Constant to indicate behavior of strcoll
and strxfrm
LC_CTYPE <locale.h)> Constant to indicate behavior of all
character-handling routines
LC_ MONETARY <locale.h)> Constant to indicate behavior of
monetary formatting information
returned by /ocaleconv
LC__NUMERIC <locale.h) Constant to indicate behavior of decimal
point format information returned by
localeconv
LC_TIME <locale.h)> Constant to indicate behavior of strftime
function
LDBL_ DIG (float.h)> Number of significant decimal digits in
a long double value
LDBL_ EPSILON <float.h) Smallest positive long double value x
such that 7+x/= 7
LDBL_MANT_ DIG (float.h) Number of base FLT__ RADIX digits in
the mantissa of a long double
LDBL__ MAX (float.h)> Maximum representable finite value that
can be stored in a long double
LDBL__MAX_ 10__ EXP <float.h) Maximum integer such that 10 raised to
that power is representable in a long
double
LDBL__ MAX _EXP <float.h> Maximum integer such that
FLT __RADIX raised to that power minus
1 is representable in a long double
LDBL_ MIN (float.h)> Minimum positive floating-point number
that can be stored in a long double
5—The ANSI C Library 53

Table 5-2. (cont.)


Macro or Where
Data Type Defined Description

LDBL_MIN__10__EXP <float.h> Minimum negative integer such that 10


raised to that power is representable in
a long double
LDBL_MIN_
EXP <float.h)> Minimum negative integer such that
FLT __RADIX raised to that power minus
1 is representable in a long double
LONG_ MAX <limits.h> Maximum value of a /ong int
LONG_ MIN <limits.h)> Minimum value of a /ong int
MB_CUR_ MAX <stdlib.h> Number of bytes in a multibyte
character for the current locale (always
less than MB_LEN_ MAX)
MB_LEN_ MAX <limits.h)> Maximum number of bytes in a
multibyte character
NDEBUG not defined If defined, assert will be ignored
NULL <locale.h> Implementation-defined null pointer
<stddef.h)> constant
<stdio.h>
<stdlib.h>
<string.h>
<time.h)
RAND_ MAX <stdlib.h> Maximum integral value returned by the
and function
SCHAR_ MAX <limits.h)> Maximum value of a signed char
SCHAR_ MIN <limits.h)> Minimum value of a signed char
SEEK_CUR <stdio.h> Constant to indicate “relative to current
position” (see fseek)
SEEK_END <stdio.h> Constant to indicate “relative to end-of-
file” (see fseek)
SEEK_ SET <stdio.h> Constant to indicate “relative to start-
of-file” (see fseek)
SHRT_ MAX <limits.h> Maximum value of a short int
SHRT_ MIN <limits.h)> Minimum value of a short int
S!IG_DFL <signal.h)> Constant to indicate default handling of
a signal
SIG_ERR <signal.h)> Constant to indicate error return from
the ‘signal function
SIG_ IGN <signal.h) Constant to indicate that a signal should
be ignored
SIGABRT <signal.h)> Abnormal termination signal
SIGFPE <signal.h) Signal caused by divide-by-0, overflow,
or other floating-point errors
SIGILL <signal.h)> Signal caused by illegal instruction
SIGINT <signal.h)> Signal caused by a specified attention
key pressed by the user (for example,
Control-C)
54 =An Overview of ANSI C

Table 5-2. (cont.)


Macro or Where na!
Data Type Defined Description

SIGSEGV <signal.h)> Signal generated when accessing a


storage location at an invalid address
SIGTERM <signal.h> Signal sent te program to terminate it
TMP_MAX <stdio.h> Minimum number of unique names that
can be had from tmpnam
UCHAR_ MAX -.. <limits.h)> Maximum value of an unsigned char
UINT__MAX <limits.h)> Maximum value of an unsigned int
ULONG_ MAX <limits.h) Maximum value of an unsigned long int
USHRT_ MAX <limits.h> Maximum value of an unsigned short
int
Clock _t <time.h) Data type capable of holding value of
time returned by the clock function
errno <errno.h> Global variable to indicate error
div_t <stdlib.h> Data structure that can hold the value
returned by div
fpos_t <stdio.h> A data type capable of recording all
information necessary to specify each
unique position in a file
jmp _buf <setimp.h> An array type capable of holding
information necessary to restore a
calling environment
struct Iconv <locale.h) Structure to hold strings to be used in
formatting numeric and monetary
values
Idiv_t <stdlib.h> Data structure that can hold the value
returned by /div
offsetof <stddef.h> Macro of the form offsetof(structure_
type, member) that returns a size_t
value, which is the offset, in bytes, of
the member from the beginning of the
structure
ptrdiff_t <stddef.h> Signed integer data type that can hold
the result of subtracting one pointer
from another
sig__atomic_t <signal.h) A data type that can be accessed as a
single entity even in the presence of
hardware and software interrupts (See
Barkakati’ from Chapter 1 reading
recommendations)
size_t <stddef.h> An unsigned integral data type that is
<stdlib.h> the result of the sizeof operator
stderr <stdio.h> Pointer to FILE data associated with the
standard error stream
stdin <stdio.h> Pointer to FILE data associated with the
standard input stream
stdout <stdio.h> Pointer to FILE data associated with the
standard output stream
5—The ANSI C Library 55

Table 5-2. (cont.)


a

Macro or Where
Data Type Defined Description

time_t <time.h) Data type capable of representing value


of time returned by time
struct tm <time.h) Data structure for holding components
of a calendar time
va_list <stdarg.h) Data type suitable for holding
information needed by the macros
va_start, Va_arg, and va__end
wchar_t <stddef.h) An integral data type that can hold the
<stdlib.h> entire range of values necessary to
represent the largest extended
character set supported by the compiler
i aad aren
, i 5 7 *
pace Lainey
, 7 = oe ares

&

seg
7 y

==

. ye
i
ANSI C Files and 1/0
Streams and Files in ANSI C

Introduction
The C programming language has no built-in capability to per-
form I/O. This is the responsibility of the library accompanying
your C compiler. Fortunately, the ANSI standard for C also speci-
fies the I/O functions that must be present in a standard-con-
forming compiler.

Streams
The concept of a “stream” as a sequence of bytes of data is uni-
versal to all I/O in C and UNIX. While it is customary to use the
terms “‘stream” and “file” synonymously, you could better liken
a file to a faucet and a stream to a hose attached to get water (data)
from the faucet. All I/O operations in ANSI C, whether to or from
a disk file or a hardware port, are mapped to a stream.

Text and Binary Streams


In addition to this view of a stream, C programmers have to be
aware of another distinction among streams: how the constitu-
ent bytes are interpreted. In ANSI C, a stream can be either bi-
nary or text.
A “text” stream consists of lines of characters. Each line is a
sequence of one or more characters ending with a terminating
newline (\n) character. When reading from or writing to a file,
characters may have to be removed or added because the under-
lying file system may not store text in the same way as a text
stream in ANSI C. For example, in MS-DOS systems, lines end
with a combination of a carriage-return (\r) and a newline (CR-

59
60 ANSI C Files and |/0

LF). Thus, reading from an MS-DOS file using a text stream will
involve altering the CR-LF to a single newline character.
A “binary” stream, on the other hand, allows you to access
the data from an underlying file or device unchanged. To under-
stand and use the data from a binary stream you must know what
was stored in the file in the first place. After all, a 4-byte value in
the file could be a long integer or it could be a float variable. It
could even be two short integers. When you know how the bi-
nary file was written, reading from it is straightforward. For ex-
ample, if you write 1,000 short integer values to a binary file
from a 2,000-byte buffer in memory, each 2-byte value you later
read from the file represents a short integer—a perfect match.

Files
In ANSI C, a “file” represents the source of data. It can be an
actual file stored on a disk, a RAM disk, CD ROM, or some exter-
nal media. A file must be able to receive or impart a stream of
bytes; physical storage need not underlie a file as is shown in Fig-
ure 6-1A. Viewed in this manner, the keyboard, the serial com-
munications port, the display screen are all files—precisely the
“model” used by the file I/O routines in ANSI C.

Buffered Stream 1/0


The first step in performing file I/O is to associate a stream with
the file. ANSI C uses the stream to perform file I/O using the
model of files as a stream of bytes together with a buffer. The
“buffer” is essentially a temporary storage area for the bytes be-
ing read from or written to the stream.
The stream I/O routines use a buffer to hold data in transit to
and from a file. In a buffered read operation from a disk file, as
Figure 6-2 illustrates, a fixed size chunk of bytes is read from the
disk into a buffer of the same size. The routines requesting data
from the file actually read from the buffer. When the buffer has
no more characters left, it is automatically refilled by a disk read
operation. A similar sequence occurs when writing to a file.
The use of a buffer leads to efficient I/O on disk files be-
cause there are fewer disk accesses, which are much slower than
reading from a buffer in memory. There is only one drawback to
the buffered approach to I/O; data written to a buffer do not
appear in the disk file until the buffer is written out. This is
“flushing” the buffer, a housekeeping chore normally handled
automatically in C programs. In certain cases, however, the buf-
fers are not flushed. These include ending the program abnor-
mally because of a fatal error, or exiting a program with a call to
abort.
When a file is opened by a stream I/O routine such asfopen,
a pointer to a FILE structure is returned to the calling program.
6—Streams and Files in ANSI!C 61

a data
8
(A)
Serial port

RAM disk

(C)
Sector of disk

Figure 6-1. Files in C

Base of Current
buffer character

Buffer in
memory 1/0 routines
interact
with buffer
File on disk

Figure 6-2. Buffered File 1/0


62 ANSI C Files and I/0

Subsequent stream I/O operations identify the file by the


pointer. In fact, this pointer to the FILE data structure is com-
monly referred to as the “stream.” Thus, “read from the stream
stdin,’ means read from the file whose associated FILE struc-
ture’s address is named stdin. Incidentally, stdin is a stream that
refers to the keyboard, and it is already open when a C program
begins running. ;
Another important feature of the stream I/O routines is the
“formatting I/O,’ the process of converting internal binary val-
ues of variables to character strings that can be written to a file.
For example, Suppose a single byte contains the bit pattern:
01100100 (the binary representation of the decimal value 100).
Converting this binary pattern into three ASCII characters in the
string /00 involves formatting. So formatting is the step that
makes the binary representations printable. Not all stream I/O
routines are meant for formatted I/O; the fread and fwrite rou-
tines are meant for reading and writing unformatted binary data.

Notes on Using the File I/O Routines


In general, the file I/O routines are meant to be used as follows:
open the file (where file can mean device as well), perform the
read and write operations, and close the file. In addition to these
tasks, you will also find routines that enable you to perform I/O
from a specific position in the file, to format a value for printing,
or to read a single line or a single character and so on.

Streams Already Opened for Your Convenience


When your C program starts up, three text streams are already
opened for you and need not be opened explicitly. These
streams, stdin, stdout, and stderr, are used to get input from the
user, display output, and display error messages, respectively.

Global Variables and Constants that Matter


The I/O routines are affected by certain global variables and pre-
processor constants defined by the ANSI C library. Table 6-1 lists
the most important constants and global variables as they relate
to the I/O routines. Many more predefined constants are signifi-
cant to individual I/O routines. These are described in the rele-
vant reference entries.

Catalog of I/0 Routines


Table 6-2 catalogs the I/O routines. In Table 6-3 the routines are
grouped by task.
6—Streams and Files in ANSIC 63

Table 6-1. Certain Constants and Global Variables Relevant to


Se ANSI C 1/0 Routines
ee ee a eee eS
Name Meaning and Default Value

BUFSIZ This constant defines the size of each buffer associated with a
Stream. It is defined in stdio.h.
FILENAME MAX Maximum length of file name string.
FOPEN _ MAX Minimum number of files that the underlying operating system
guarantees can be opened simultaneously. This must be at
least eight, including the preopened streams stdin, stdout, and
stderr.
- EOF This constant denotes the end-of-file condition and is defined
in stdio.h as a negative number.
L_tmpnam This constant is the length of a character array large enough to
hold temporary file names generated by tmpnam.
NULL A constant defined in stdio.h to signify a null pointer.
TMP_MAX This constant denotes the number of file names that can be
generated by tmpnam.

Table 6-2. 1/0 Routines in the ANSI C Library


Routine Description

Clearerr Clears the error indicator of a stream.


fclose Closes a stream.
feof A macro that returns a nonzero value if current position in a stream is at
the end-of-file.
ferror A macro that returns a nonzero value if an error occurred during
read/write operations on a stream.
fflush Writes to the file the contents of the buffer associated with a stream.
fgetc Reads a character from a stream.
fgetpos Returns current position of a stream in an internal format suitable for use
by fsetpos.
fgets Reads a line (up to and including the first newline character) from a
stream.
fopen Opens a named file as a buffered stream (includes options for selecting
translation modes and access types).
fprintt Performs formatted output to a stream.
fputc Writes a character to a stream.
fputs Writes a string of characters to a stream.
fread Reads a specified amount of binary data from a stream.
freopen Closes a stream and reassigns it to a new file.
fscanf Performs formatted input from a stream.
fseek Sets current position to a specific location in the file.
fsetpos Sets current position of a stream using value returned by an earlier call
to fgetpos.
ftell Returns the current position in the file associated with a stream.
fwrite Writes a specified number of bytes of binary data to a stream.
64 ANSI C Files and 1/0

Table 6-2. (cont.)

Routine — Description

getc Reads a character from a stream.


getchar Reads a character from the stream stdin.
gets Reads a string up to a newline character from the stream stdin.
printf Performs formatted output to the stream stdout.
putc Writes a character to a stream.
putchar — Writes‘a character to the stream stdout.
puts Writes a string to the stream stdout.
remove Deletes a file specified by its name.
rename Changes the name of a file.
rewind Sets the current position to the beginning of the file associated with a
stream.
scant Performs formatted input from the stream stdin.
setbuf Assigns a fixed-length user-defined buffer to an open stream.
setvbuf Assigns a variable-length user-defined buffer to an open stream.
sprintf Performs formatted output to a buffer.
sscanf Performs formatted input from a buffer.
tmpfile Creates a temporary file open for buffered stream 1/0.
tmpnam — Generates a temporary file name.
ungetc Pushes a character back to the buffer associated with a stream.
viprintt Version of fprintfthat accepts a pointer to a list of arguments and
7 performs formatted output to a stream.
vprintf Version of printf that accepts a pointer to a list of arguments and
performs formatted output to the stream stdout.
vsprintf Version of sprintf that accepts a pointer to a list of arguments and
performs formatted output to a buffer.

Table 6-3. File 1/0 Routines in ANS! C by Task


1/0 Task Routine

Create or open a file fopen, freopen


Close a File fclose
Delete or rename a file remove, rename
Formatted read fscanf, scanf
Formatted write fprintf, printf, vfprintf, vprintt
Read a character fgetc, fgetchar, getc, getchar
Write a character fputc, fputchar, putc, putchar
Read a line fgets, gets
Write a line fputs, puts
Set read/write position fseek, fsetpos, rewind
Get read/write position fgetpos, ftell
Binary read fread
Binary write fwrite
6—Streams and Files in ANSI!C 65

Table 6-3. (cont.)


1/0 Task Routine

Flush buffer fflush


Check error/EOF Clearerr, feof, ferror
Manage temporary files tmpfile, tmpnam
Control buffering setbuf, setvbuf
Push character to buffer ungetc

String 1/0
If you think of files as a stream of bytes, the data sources or desti-
nations do not have to be disk files or devices; they can also be
buffers in memory. A group of ANSI C I/O routines provide the
capability to read from and write to arrays of characters
(“strings’’). These routines allow you to format data and place
the result in a string or to get characters from a string and convert
the characters to internal values. This is often convenient be-
cause yOu Can prepare a string to be output by routines that have
no formatting capability. Table 6-4 lists the three string I/O rou-
tines according to the task they perform.

Table 6-4. ANSI C String 1/0 Routines by Task

1/0 Task Routines

Format input from a string sscanf


Format output to a string sprintf, vsprintf

Formatted 1/0: printf and scanf


The formatting capabilities of printf and scanf deserve special
attention because they are widely used in C programs and a large
number of formatting options are available under each function.
Many other functions, such as fprintf, fscanf, sprintf, and sscanf
provide identical formatting options. Thus understanding printf
and scanf should help you use all the formatted I/O routines in
the ANSI C library.
Formatting involves converting internal representation of a
variable into a character string that humans can understand. To
interpret the contents of a set of memory locations you must
know the type of C variable being stored there. For example, a
set of 4 bytes can hold a long integer and it can also hold a single-
precision floating-point number. The printf and scanf func-
tions, responsible for formatting the data, have to be told how
the contents of these bytes are to be interpreted. This is done by
embedding formatting commands in the arguments passed to
printf and scanf.
66 ANSI C Files and 1/0

Formatted Output with printf


In the simplest case, when printing out values of variables, you
can use printf with a minimal amount of formatting code:
float floatvar = 24.95;
double dblvar = 99.95;
int intvar = 100;
char stringl] = "ANSI C";

printf("Float’= %f, Double = %f, Integer = %d,\n"


"String = %s\n"',
floatvar, dblvar, intvar, string);

In this case, each formatting command consists of apercent sign


(%) followed by a single letter that indicates the type of the vari-
able. The format codes are embedded in a string and each com-
mand appears exactly where you want the variable to be printed.
The string with the formatting codes is followed by the variables
that you want printed. Here’s what you will get if you embed the
code fragment in a small C program and execute it.
Float = 24.950001, Double = 99.950000, Integer = 100,
String = ANSI C

You may have noticed the discrepancy between the assigned


value of the float variable and the value shown by printf. The
single-precision float variables are accurate to 7 significant dig-
its. When you used the %f format to print this value, printf used
more than 7 significant digits (by default it used 6 digits follow-
ing the decimal point). Since the stored value is only accurate to
seven significant digits, the value prints as 24.95000/ instead of
the expected 24.950000. This illustrates an important point
about formatted output: you can print results that can have at
best the accuracy present in the stored value. Since a float vari-
able is accurate to 7 digits only, you cannot expect to get a more
accurate value by simply asking printf to use a formatting option
that requires the use of, say, 15 significant digits.
Notice too that both float and double floating-point values
are printed with six digits after the decimal place. The integer
value is printed without any leading blanks and the string is sim-
ply printed in its entirety. All of these happen to be the default
settings of the respective formats: %f, %d, and %s. Additional
qualifiers can be placed between the percent sign and the type
letter to indicate options, such as the number of digits after the
decimal point or the size of field within which to print a value.
Other data types can be printed out, including the /ong and
unsigned forms of integers, single characters, and addresses of
variables in a system-dependent format. See the reference pages
on printf for complete coverage of the formatting options and
commands. Note that while printfis meant for writing to the
stream stdout, fprintf performs the same operation to a file and
sprintf writes formatted output to a string. Each of these rou-
tines accepts the same formatting commnds as printf.
6—Streams and Files in ANSIC 67

Formatted Output with scanf


The scanf function is meant for formatted input which involves
reading characters and converting groups of them into internal
representation of C variables. Like printf, a string with embed-
ded format codes specifies how the input characters are treated
during the conversion process. In fact, a call to scanf looks like a
call to printf, except that the argument list has addresses of the
variables into which scanf loads the values converted from the
input string. If you were reading a float, a double, and an integer,
the call might look like this:
float floatvar;
double dblvar;
int intvar;

scanf(" ZF “Lf “d", &floatvar, &dblvar, &intvar);

This formatted read statement reads the three values with any
number of blank spaces between them. Note that the format
code meant for the float variable is different from that for the
double. The %f code tells scanf to convert the string into the
internal representation of a float variable. Adding the qualifier |
between the % and the f tells scanf to use the internal represen-
tation of a double instead of a float.
Like printf, scanf is meant for formatted input from the
stream stdin. The ANSI C I/O library also includes fscanf for for-
matted input from a file and sscanf for formatted input from aC
string. These routines use the same formatting commands as
scanf. The reference entry on scanf gives more details on the
formatting options.

Further Reading
The standard I/O routines are covered in almost any book on C.
Prata’s book' is a good place to start. The Waite Group’s refer-
ence guides for Microsoft C* and Turbo C? detail the I/O routines
offered by these implementations of C.
1. Stephen Prata, The Waite Group's Advanced C Primer++,
Howard W. Sams & Company, Indianapolis, IN, 1986, 502
pages.
2. Nabajyoti Barkakati, The Waite Group's Microsoft C
Bible, Howard W. Sams & Company, Indianapolis, IN, 1988,
808 pages.
3. Nabajyoti Barkakati, The Waite Group's Turbo C Bible,
Howard W. Sams & Company, Indianapolis, IN, 1988, 900
pages.
Fs 144reset
ait rab

ws esr thi gee he ncaa0 he ied mand


; ‘ A ‘ ae
ne ce ee re *
x 7
a ~— -
=

i
4

= ®

é i

™~

f “i
ANSI C File 1/0 Routines

clearerr <4

Purpose
Use clearerr to reset the error and end-of-file indicators of the
stream specified by the stream pointer stream.

Syntax
#include <stdio.h>
void clearerr(FILE *stream);
FILE *stream; Pointer to stream whose error flag is being cleared

Example Call
clearerr(outfile);

See Also
ferror, feof

Example
See Example 7-1 on page 99. Line 44 in that example uses
clearerr to reset the error flag after an error occurs during file
1/O.

fclose <4

Purpose
Use fclose to close the stream specified by stream. If the stream
was open for writing, the content of the buffer associated with the

69
70 ANSI C Files and I/0

stream is written to the file (“flushed”) before the file is closed. If it


was open for reading, unread data in the buffer are discarded.

Syntax
#include <stdio.h>
int fclose(FILE *stream);
FILE *stream; Pointer to stream to be closed

Example Call
fclose(infile);

Returns
If the stream was successfully closed, feof returns a zero; other-
wise, it returns EOF.

See Also
fopen, fflush

Example
Lines 57 and 58 in Example 7-1 call fclose to close files before
exiting the program.

> feof

Purpose
Use feof to determine whether stream’s end-of-file indicator is
set. When you get an error return from a read operation, you can
call feof to determine if the error occurred because you tried to
read past the end-of-file.

Syntax
#include <stdio.h>
int feof(FILE *stream);
FILE *stream; Pointer to FILE data structure associated with the stream
whose status is being checked

Example Call
if (feof(infile) != 0) printf("File ended\n");

Returns

If the end-of-file indicator is set for stream, feof returns a non-


zero.

feof
7—ANSI C File 1/0 Routines 71

See Also

clearerr, ferror, rewind

Example
Line 42 of Example 7-1 uses feof to check for end-of-file.
Si ena
ecaaen pis ede
Som gue rly se
ferror <4

Purpose
Use ferror to determine if the error indicator is set for the speci-
fied stream.

Syntax
#include <stdio.h>
int ferror(FILE *stream);
FILE *stream; Pointer to FILE data structure associated with the stream
whose status is being checked

Example Call
if (ferror(infile) != 0) printf("Error detected\n");

Returns

If the error indicator is set for stream, ferror returns a nonzero


value.

See Also
clearerr, feof

Example
Line 40 of Example 7-1 uses ferror to check the error indicator of
a stream.

fflush <4

Purpose
Use the fflush function to flush the current contents of the
buffer associated with the stream specified by stream. If the file
is open for write operations, the flushing involves writing the
contents of the buffer to the file. Otherwise, the buffer is
cleared. If stream is NULL, all open streams are flushed.

fflush
72. ANSI C Files and 1/0

Syntax
#include <stdio.h>
int fflush(FILE *stream);
FILE *stream; Pointer to stream whose buffer is being flushed

Example Call
fflush(stdin);

Returns
If the flushing is successful, fflush returns a zero. In case of an
error, it returns the constant EOF defined in stdio.h.

See Also
fopen, fclose, setbuf, setvbuf

Example
See Example 7-2 at the end of this chapter. Line 90 in that ex-
ample uses {flush to flush stdin’s buffer to ensure that a new
command line is read.

> fgetc
=

Purpose
Use fgetc to read a single character from the stream specified by
the pointer stream. The character is read from the current posi-
tion in the stream. After reading the character, the current posi-
tion advances to the next character.

Syntax
#include <stdio.h>
int fgetc(FILE *stream);
FILE *stream; Pointer to stream from which a character is to be read

Example Call
char_read = fgetc(infile);

Returns

If there are no errors, fgetc returns the character read as an un-


signed char converted to an int. Otherwise, it returns the con-
stant EOF. You should call ferror and feof to determine whether
an error occurred or the file simply reached its end.

See Also

getc, getchar, fputc, putc, putchar

fgetc
7—ANSI C File 1/0 Routines 73

eee
fgetpos <4

Purpose
Use fgetpos to get and save the current position indicator of the
stream specified by the argument stream in the fpos_t data ob-
ject whose address is in current__pos. This value is used by the
companion function fsetpos to reposition the stream at the time
of the call to fgetpos.

Syntax
#include <stdio.h>
int fgetpos(FILE *stream, fpos_t *current_pos);
FILE *stream; Pointer to stream whose current position is requested

fpos_t *current_pos; Pointer to variable to which file’s current


position is returned

Example Call
fgetpos(infile, &curpos);

Returns

If successful, fgetpos returns a zero. In case of error, it returns a


nonzero value and sets the global variable errno to an implemen-
tation-defined error constant.

See Also

fsetpos

fgets <4

Purpose
Use the fgets function to read a line from the stream specified by
stream. The line is read into the character array string until a
newline (\n) character is encountered, an end-of-file condition
occurs, or the number of characters read reaches one fewer than
the value given in the argument maxchar. A null character is
written to string immediately after the last character.

Syntax
#include <stdio.h>
char *fgets(char *string, int maxchar, FILE *stream);
char *string; Pointer to buffer in which characters will be stored

int maxchar; Maximum number of characters that can be stored

fgets
74. ANSI C Files and 1/0

FILE *stream; Pointer to stream from which a line is read

Example Call
fgets(buffer, 80, infile);

Returns

If there are no errors, fgets returns the argument string. Other-


wise, it returns a NULL. You can call ferror and feof to determine
whether the error is genuine or it occurred because the file
reached its end.

See Also
gets, fputs, puts

Example
Line 38 in Example 7-1 calls fgets to read a line from a file.

> fopen

Purpose
Use fopen to open the file whose name is specified in the string
filename and associate a stream with it. The argument ac-
cess__mode contains one of the strings listed in Table 7-1.

Table 7-1. Access Modes When Opening Files

access__ mode
String Interpretation

aie Open a text file for reading. Fail if file does not exist.
“w" If file exists, open and truncate it to zero length. Otherwise,
create the file and open it for writing in the text mode.
a’ Open text file for appending—writing at the end of file. Create
file if it does not exist.
“ilo Same as “r”—but binary mode.
“wb” Same as “w’—but binary mode.
“ab” Same as “a”—but binary mode.
(isa Open text file for updating—reading as well as writing.
“w+” If file exists, open it and truncate it to zero length. Otherwise,
create it and open it for updating.
rahi Open text file for appending. Create file if it does not exist.
“rb” or “rb” Open binary file for updating.
“w+b” or “wb+” If file exists, truncate to zero length. Otherwise, create a
binary file for update operations.
“a+b” or “ab+” Open or create binary file for appending.

fopen
7—ANSI C File 1/0 Routines 75

Syntax
#include <stdio.h>
FILE *fopen(const char *filename, const char *access_mode);
const char *filename; Name offile to be opened

const char *access_mode; A character string denoting whether file is


being opened for read, write, or append

Example Call
input_file = fopen("data.in", "rb!');

Returns

If the file is successfully opened, fopen returns a pointer to the


FILE data structure that controls the stream. The FILE structure
is allocated elsewhere and you need not allocate it. In case of an
error, fopen returns NULL.

See Also
fclose, freopen, setbuf, setvbuf

Example
Lines 19 and 29 in Example 7-1 show calls to fopen.

fprintf <

Purpose
Use the fprintf function to format and write character strings
and values of C variables to the stream specified by the argument
stream. See the reference entry for printf for a description of the
argument format_ string.

Syntax
#include <stdio.h>
int fprintf(FILE *stream, const char *format_string,...);
FILE *stream; Pointer to stream to which the output goes

const char *format_string; A character string that describes the


format to be used

ae A variable number of arguments depending on the number of items


being printed

Example Call
fprintf(resultfile, "The result is %f\n"', result);

fprintf
76 ANSI C Files and 1/0

Returns
The fprintf function returns the number of characters it has
printed. In case of error, it returns a negative value.

See Also
printf, vfprintf, vprintf, sprintf, vsprintf

Example
Line 62 in Example 7-2 uses fprintf to print an error message to
the stream stderr.

> fputc

Purpose
Use fputc to write the character c to the stream specified by
stream.

Syntax
H#include <stdio.h>
int fputc(int c, FILE *stream);
nt ce Character to be written

FILE *stream; Pointer to stream to which the character ts to be written

Example Call
fputc('X', p_datafile);

Returns

If there are no errors, fputc returns the character written. Other-


wise, it returns the constant EOF. You should call ferror to deter-
mine whether an error occurred or the integer argument c was
equal to EOF.

See Also

fgetc, getc, getchar, putc, puts

> fputs

Purpose
Use the fputs function to write the C string given by string to the
stream specified by stream.

fputs
7—ANSI C File 1/0 Routines 77

Syntax
#include <stdio.h>
int fputs(const char *string, FILE *stream);
const char *string; Null-terminated (\0) character string to be output

FILE *stream; Pointer to stream to which the string is output

Example Call
fputs(''Sample Input Data’, p_datafile);

Returns

The fputs function returns a non-negative value if all goes well.


In case of error, it returns the constant EOF.

See Also

fgets, gets, puts

Example
Line 52 in Example 7-1 uses fputs to write a line to a file.

fread <4

Purpose
Use fread to read the number of data items specified by count,
each of a size given by the argument size, from the current posi-
tion in stream. The current position of stream is updated after
the read.

Syntax
#include <stdio.h>
size_t fread(void *buffer, size_t size, size_t count,
FILE *stream);
void *buffer; Pointer to buffer where fread stores the bytes it reads

size_t size; Size in bytes of each data item

size_t count; Maximum number of items to be read

FILE *stream; Pointer to stream from which data items are to be read

Example Call
numread = fread(buffer, sizeof(char), 80, infile);

Returns

The fread function returns the number of items it successfully


read. If the return value is less than you expected, you can call

fread
78 ANSI C Files and I/0

ferror and feof to determine if a read error occurred or if end-of-


file has been reached.

See Also
fopen, fwrite, fclose

Example
Line 105 in Example 7-2 reads a record from a file using fread.

> freopen

Purpose
Use freopen to close stream, open another file whose name is in
the string filename, and attach stream to it. For example, you
can use freopen to redirect I/O from the preopened file stdout to
a file of your choice. See fopen for a description of the argument
access __mode. The error indicator of stream will be cleared after
the reopening.

Syntax
#include <stdio.h>
FILE *freopen(const char *filename, const char *access_mode,
FILE *stream);
const char *filename; Name offile to be reopened, including drive
and directory specification

const char *access_mode; A character string denoting whether file is


being reopened for read, write, or append

FILE *stream; Pointer to stream to be reopened

Example Call
freopen("output.txt", "w'', stdout); /* Redirect stdout to a
file */

Returns

If all goes well, freopen returns a pointer to the newly opened


file. This returned pointer will be the same as the argument
stream. In case of error, a NULL is returned.

See Also

fopen, fclose

freopen
7—ANSI C File 1/0 Routines 79

Ao DRL ee i en ee
fscanf <

Purpose
Use the fscanf function to read characters from stream, convert
them to values according to format specifications embedded in
the argument format_ string, and store the values in C variables
whose addresses are provided in the variable-length argument
list. See scanf for more details on the argument format_string.

Syntax
#include <stdio.h>
int fscanf(FILE *stream, const char *format_string,...);
FILE *stream; Pointer to the stream from which reading will occur

const char *format_string; A character string that describes the


format to be used

SAB Variable number of arguments representing addresses of variables


whose values are being read

Example Call
fscanf(infile, "Date: %d/%d/%d"", &month, &day, &year);

Returns

The fscanf function returns the number of input items that were
successfully read, converted, and saved in variables. The count
does not include items that were read and ignored. If an end-of-
file is encountered during read, the return value will be equal to
the constant EOF (defined in stdio.h).

See Also

scanf, sscanf

fseek <4

Purpose
Use the fseek function to reposition stream to the location speci-
fied by offset with respect to the argument origin. The valid val-
ues of origin are the following constants:

Origin Interpretation

SEEK_ SET Beginning of file


SEEK__CUR Current position in the file
SEEK __END End-of-file

fseek
80 ANSI C Files and 1/0

Syntax
#include <stdio.h>
int fseek(FILE *stream, long offset, int origin);
FILE *stream; Pointer to stream whose current position is to be set

long offset; Offset of new position (in bytes) from origin


int origin; Constant indicating the position from which to offset

Example.Call
fseek(infile, OL, SEEK_SET); /* Go to the beginning */

Returns

The fseek function returns a nonzero value only if it fails to posi-


tion the stream.

See Also
fgetpos, fsetpos, ftell

Example
Line 99 in Example 7-2 uses fseek to skip the file header when
reading records from a file.

> fsetpos

Purpose
Use fsetpos to set the position where reading or writing will take
place in stream. The new position is specified in an fpos_t data
object whose address is in current_pos. For file position, use
the value obtained by an earlier call to fgetpos.

Syntax
#include <stdio.h>
int fsetpos(FILE *stream, const fpos_t *current_pos);
FILE *stream; Pointer to stream whose current position is to be set

const fpos_t *current_pos; Pointer to location containing new


value of file position

Example Call
fgetpos(infile, &curpos);

Returns

If successful, fsetpos clears the end-of-file indicator of stream


and returns zero. Otherwise, the return value is nonzero and the
global variable errno is set to an implementation-defined error
constant.

fsetpos
7—ANSI C File |/0 Routines 81

See Also

fgetpos

ae
ee
ftell <4

Purpose
Use frel/ to obtain the current position of stream. The position is
expressed as a byte offset from the beginning of the file.

Syntax
#include <stdio.h>
long ftell(FILE *stream);
FILE *stream; Pointer to stream whose current position is to be
returned

Example Call
curpos = ftell(infile));

Returns

If successful, ftel/ returns a long integer containing the number


of bytes that the current position of stream is offset from the be-
ginning of the file. In case of error, fte/l returns —1L. Also, the
global variable errno is set to an implementation-defined con-
Stant.

See Also

fgetpos, fseek, fsetpos

Example
Line 104 in Example 7-2 shows how /tel/ can be used to get the
current position in the file.

fwrite <

Purpose
Use the fwrite function to write the number of data items speci-
fied by count, each of a size given by size, from buffer to the
current position in stream. The current position of stream is up-
dated after the write.

Syntax
#include <stdio.h>

fwriie
82 ANSI C Files and 1/0

size t fwrite(const void *buffer, size_t size, size_t count,


if FILE *stream);
const void *buffer; Pointer to buffer in memory where fwrite will get
the bytes it writes :

size_t size; Size in bytes of each data item


size_t count; Maximum number of items to be written

FILE *stream; Pointer to stream to which the data items are to be


ze written

Example Call
numwrite = fwrite(buffer, sizeof(char), 80, outfile);

Returns

The fwrite function returns the number of items it actually


wrote. If the return value is less than what you expect, an error
may have occurred. Use ferror to verify this.

See Also
fopen, fread, fclose

Example
Lines 69 and 76 in Example 7-2 illustrate how fwrite is used to
*write binary data to a file.

> getc

Purpose
Use the gefc macro to read a single character from stream. Ex-
cept that it is implemented as a macro, getc is identical to fgetc.
So you should not provide it an argument that might cause side
effects (see tutorial in Chapter 3).

Syntax
H#Hinclude <stdio.h>
int getc(FILE *stream);
FILE *stream; Pointer to stream from which a character is to be read

Example Call
in_char = getc(p_txtfile);

Returns

The getc macro returns the character read as an integer value. A


return value of EOF indicates an error.

getc
7—ANSI C File 1/0 Routines 83

See Also

fgetc, fputc, getchar, putc, putchar

Soo SNS ier nein belied ik ee Vcc oe


getchar <<

Purpose
Use the getchar macro to read a single character from the pre-
opened file stdin, which is normally connected to your key-
board input. Note that getchar is identical to getc with stream set
to stdin.

Syntax
#include <stdio.h>
int getchar(void);

Example Call
c = getchar();

Returns
The getchar macro returns the character read from stdin as an
integer value. In case of an error the return value is equal to the
constant EOF.

See Also
fgetc, fputc, getc, putc, putchar

Example
Line 87 in Example 7-2 uses getchar to read a single character
command from stdin.

gets <4

Purpose
Use gets to read a line from the standard input file stdin into the
string buffer. The reading continues until gets encounters a
newline character or end-of-file. At this point, it replaces the
newline character with a null character (\O) and creates a string.
You must allocate room for the buffer in which the string will be
stored. Note that fgets performs similarly but, unlike gets, it re-
tains the newline character in the final string.

gets
84 ANSI C Files and |/0

Syntax
#include <stdio.h>
char *gets(char *buffer);
char *buffer; Buffer where string will be stored

.
Example Call
gets(command_line);

Returns >
If successful, gets returns buffer. Otherwise, it returns a NULL.

See Also
fgets, fputs, puts

Example
Lines 15 and 25 in Example 7-1 call gets to read the user’s input.

> printf

Purpose
Use printfto write character strings and values of variables, for-
*matted in a specified manner, to the standard output file stdout
(normally the screen). The value of each argument is formatted
according to the codes embedded in the string format_ string.
The formatting command for each variable consists of a percent
sign (%) followed by a single letter denoting the type of variable
being printed. The complete format specification is of the form:
% |Flags][(Width].[{Precision][Size][Type]
Table 7-2 summarizes each component of the format string. Ta-
bles 7-3 and 7-4 explain the Flag and Type fields, respectively.

Syntax
#include <stdio.h>
int printf(const char *format_string,...);
const char *format_string; A character string that describes the
format to be used

A variable number of arguments depending on the number of items


being printed

Example Call
printf('The product of %d and %d is %d\n", x, y, x*y);

Returns

The printf function returns the number of characters it has


printed. In case of error, it returns a negative value.

printf
7—ANSI C File 1/0 Routines 85

Table 7-2. Fields in Output Format Specification


Field Explanation

Flags (Optional) One or more of the -, +, #, 0 characters or a blank space to


specify justification and the appearance of plus/minus signs
and of the decimal point in the values printed (see Table 7-3).
Width (Optional) A number to indicate how many characters, at a minimum,
must be used to print the value.
Precision (Optional) Another number specifying how many characters, at most,
can be used in printing the value. When printing integer
variables, this is the minimum number of digits used.
Size (Optional) This is a character that modifies the Type field which comes
next. One of the characters h, |, or L appears in this field.
This field is used to differentiate between short and long
integers, and between float and double. Shown below is a
summary of this field:

Prefix When to Use

h Use when printing integers using Type d, i, 0, x, or


X to indicate that the argument is a short integer.
Also, use with Type u to indicate that the variable
being printed is a short unsigned integer.
| Use when printing integers or unsigned integers
with a Type field of d, i, 0, u, x, or X to specify that
the variable to be printed is a long integer.
L Use when the floating-point variable being printed
is a long double and the Type specifier is one of e,
Ent 701 Ge:

Type (Required) A letter to indicate the type of variable being printed. Table 7-
4 lists the characters and their meanings.

Table 7-3. Flags Field in Output Format Specification

Flag Meaning

Left justify output value within the field.


If the output value is a numerical one, print a + or a — according to the
sign of the value.
space Positive numerical values are prefixed with blank spaces. This flag is
ignored if the + flag also appears.
When used in printing variables of type 0, x, or X (i.e., octal or
hexadecimal), nonzero output values are prefixed with 0, Ox, or OX,
respectively. When the 7ype field in the format specification is e, E, f, g, or
G, this flag forces the printing of a decimal point. For a g or G in the Type
field, all trailing zeroes will be printed.
For Type d, i, 0, u, x, X, e, f, g, or G, leading zeroes will be printed. This
flag is ignored if the — flag also appears.

printf
86 ANSI C Files and 1/0

Table 7-4. Type Field in Output Format Specification


Type TypeinC Resulting Output Format

Cc char Single character.


d int Signed decimal integer as a sequence of digits with or
without a sign depending on the Flags used. printf
(“%d”, 95);" prints 95.
e@ double or float Signed value in the scientific format. For example,
- 1,234567e+002.
E double or float Signed value in the scientific format, the above example
will print - 7.234567E + 002 if the %E format is used.
f double or float Signed value in the format, “(sign)(digits).(digits)”, the
example for 7ypee will print - 123.456700 if the %f
format is used. The number of digits before the decimal
point depend on the magnitude of the variable and the
number of digits that come after the decimal point depend
on the Precision field in the format specification. The
default precision is 6. Thus a %f format alone always
produces six digits after the decimal point, but a %.3f
will print the value — 123.457, which is - 123.4567
rounded off to three decimal places.
g double or float Signed value printed using one of e or f format. The
format that generates the most compact output for the
given Precision and value is selected. The e format is
used only when the exponent is less than —4 or when it
is greater than the value of the Precision field. Printing
the value - 123.4567 using a %qg format will result in
- 123.457 because the g format rounds off the number.
G double or float Signed value printed using the g format, but with the
letter G in place of e whenever exponents are printed.
i int Signed decimal integer as a sequence of digits with or
without a sign depending on the Flags field.
n Pointer to int This is not a printing format. The argument
corresponding to this format is a pointer to an integer.
Before returning, the printf function stores in this integer
the number of characters it has printed thus far to the
output file or to the file’s buffer.
0 unsigned Octal digits without any sign.
p pointer to void The address is printed in an implementation-defined
format.
u unsigned Unsigned decimal integer as a sequence of digits.
X unsigned Hexadecimal digits using lowercase letters, abcdef.
X unsigned Hexadecimal digits using uppercase letters, ABCDEF.
% nont
Prints a %

printf
7—ANSI C File 1/0 Routines 87

See Also

fprintf, sprintf, vfprintf, vprintf, vsprintf

Example
The printf function is used in almost every C program. Example
7-1. uses it in lines 13, 21, 24, 31, and 55.

putc <

Purpose
Use the putc macro to write a single character c to stream. Ex-
cept that it is implemented as a macro, putc is equivalent to
fpute.

Syntax
#include <stdio.h>
int putc(int c, FILE *stream);
intace Character to be written

FILE *stream; Pointer to stream to which the character is written

Example Call
putc('*', outfile);

Returns
The putc macro returns the character written. A return value of
EOF indicates an error. Call the ferror function to determine if an
error occurred.

See Also
fgetc, fputc, getc, getchar, putchar

putchar <4

Purpose
Use the putchar macro to write the character c to the preopened
stream stdout which has been initially connected to your dis-
play. The putchar macro is equivalent to putc with the second
argument set to stdout.

putchar
88 ANSI C Files and I/0

Syntax
#include <stdio.h>
int putchar(int c);
antes Character to be written

Example Call
putchar('?');

Returns

The putchar macro returns the character written to stdout. In


case of an error, the return value is equal to the constant EOF.

See Also

fgetc, fputc, getc, getchar, putc

> puts

Purpose
Use puts to Output string to the standard output stream stdout.
The terminating null character (\0) is replaced by a newline (\n)
»in the output.

Syntax
#include <stdio.h>
int puts(const char *string);
const char *string; Stringto be output

Example Call
puts("Do you really want to quit? ");

Returns

If successful, puts returns a non-negative value. Otherwise, it re-


turns EOF to indicate error.

See Also
fgets, fputs, gets

Example
Lines 41 and 43 in Example 7-1 use puts to print error messages
to stdout.

puts
7—ANSI C File 1/0 Routines 89

SL
TD

remove <

Purpose

Use remove to delete a file specified by its name file_name.

Syntax
#include <stdio.h>
int remove(const char *file_name);
const char *file_name; Name offile to be deleted

Example Call
remove("'/usr/tmp/tmp01234"); /* Delete temporary file */

Returns

If remove successfully deletes the specified file, it returns a zero.


Otherwise, the return value is nonzero.

See Also

rename

rename <@

Purpose
Use rename to change the name ofa file from oldname to new-
name.

Syntax
#include <stdio.h>
int rename(const char *oldname, const char *newname) ;
const char *oldname; Current file name

const char *newname; New file name

Example Call
/* Copy "'test.exe’ from /usr/tmp to /usr/bin and give it a new
name */
rename("'/usr/tmp/test.exe", '"'/usr/bin/grview.exe") ;

Returns
If rename is successful, it returns a zero. In case of an error, it
returns a nonzero value.

See Also
fopen, fclose, remove

rename
90 ANSI C Files and 1/0

> rewind

Purpose
Use the rewind function to set the current read or write position
associated with stream to the beginning of the file. The rewind
clears the end-of-file or error indicator of stream. Calling the re-
wind function is equivalent to calling (void) fseek(stream, OL,
SEEK __SET).

Syntax
#include <stdio.h>
void rewind(FILE *stream);
FILE *stream; Pointer to stream whose position is to be set to the
beginning of the file

Example Call
rewind(input_file);

See Also

fseek

>

Pm scanf

Purpose
Use scanf to read characters from the standard input file stdin
and convert the strings to values of C variables according to the
format specified in the string format_ string. For each variable’s
address included in the argument list to scanf there must be a
format specification embedded in the format_string. The for-
mat specification for each variable has the form:
%[*][Width]{Size][
Type]
Table 7-5 summarizes the purpose of each field in the format
specification used by scanf. Further details are provided in Table
7-6.
Normally strings read using the %s format are assumed to
be delimited by blank spaces. When you want to read a string
delimited by any character other than those ina specific set, you
can specify the set of characters within brackets and use this in
place of the letter s in the format specification. On the other
hand, if the first character inside the brackets is a caret (*), the set
is assumed to show the characters that terminate the string.
Thus, for example, %[/’\” will read a string delimited by single
or double quote characters.

scanf
7—ANSI C File 1/0 Routines 91

Table 7-5. Fields in Input Format Specification


Field Explanation

% (Required) Indicates the beginning of a format specification. Use %% to


read a percentage sign from the input.
* (Optional) The characters representing the value are read according to the
format specification, but the value is not stored. It is not
necessary to give an argument corresponding to this format
specification.
Width (Optional) A positive value specifying the maximum number of characters
to be read for the value of this variable.
Size (Optional) A character that modifies the Type field which comes next. One
of the characters h, |, or L appears in this field to differentiate
between short and long integers and between float and double.
Shown below is a summary of this field:

Prefix When to Use

h Use when reading integers using 7yped, i, or n to


indicate that the argument is a short integer. Also, use
with Type o, u, and x to indicate that the variable
being read is an unsigned short integer.
| Use when reading integers or unsigned integers with a
Type field of d, i, or n to specify that the variable to be
read is a long integer. Also use with 0, u, and x to
read values into unsigned long integers. For floating-
point variables (when the /ype field is e, f, or g) to
specify a double, rather than a float.
L Use with e, f, and g to indicate that the variable is a
long double.

Type (Required) A letter that indicates the type of variable being read. Table 7-6
lists the characters and their meanings.

Table 7-6. Type Field in Input Format Specification

Type Expected Input Type of Argument

Cc Single character. Whitespace Pointer to char


characters (space, tab, or
newline) will be read in this
format.
d Decimal integer. Pointer to int
e f g Signed value in the scientific Pointer to float
format—for example, - 1.
234567e + 002 and 9.
876543e-002 or in the format “
(sign)(digits).(digits)””
—for
example, — 1.234567 and 9.
876543.
Decimal, hexadecimal, or octal Pointer to int
integer.

scanf
92 ANSI C Files and |/0

Table 7-6. (cont.)

Type Expected Input Type of Argument

n This is not a reading format. The Pointer to int


argument corresponding to this
format is a pointer to an integer. ,
Before returning, the scanf
function stores in this integer the
number of characters it has read
thus far from the input file or the
input file’s buffer.
0 Octal digits without a sign. Pointer to int
p Implementation-defined format for Pointer to a pointer to void
an address.
S Character string. Pointer to an array of characters
large enough to hold input string
plus a terminating null (\0)
u Unsigned decimal integer. Pointer to unsigned int
X Hexadecimal digits. Pointer to int

Syntax
#include <stdio.h>
int scanf(const char *format_string,...);
const char *format_string; Character
string that describes the
R format to be used

Variable number of arguments representing addresses of variables


whose values are being read

Example Call
scant("' %d:%d:%d", &hour, &minute, &second);

Returns

The scanf function returns the number of input items that were
successfully read, converted, and saved in variables. This does
not include the items that were read and ignored. A return value
equal to the constant EOF (defined in stdio.h) means that an end-
of-file was encountered during the read operation.

See Also
fscanf, sscanf

> setbuf

Purpose

Use the setbuf function to assign buffer, of size BUFSIZ, instead


of the system-allocated one for use by stream for buffering. Call-

setbuf
7—ANSI C File 1/0 Routines 93

ing setbufisequivalent to using setubuf with _IOFBF and BUF-


SIZ as the third and fourth arguments, respectively. If buffer is
NULL, the third argument will be _IONBF

Syntax
#include <stdio.h>
void setbuf(FILE *stream, char *buffer);
FILE *stream; Pointer to stream whose buffer is being set

char *buffer; Pointer to buffer (or NULL if no buffering is to be done)

Example Call
setbuf(infile, mybuffer);

See Also
setvbuf

setvbuf <

Purpose
Use the setubuf function to assign buffer, of a size buf _size, to
stream. By specifying appropriate constants for the argument
buf_mode, you can control the type of buffering to be used or
turn off the buffering for stream. If buf__mode is _IOFBF, the
I/O operations with the stream will be fully buffered. If it is _
IOLBF, the buffering will be done one line at a time. Setting buf
_mode to _IONBEF causes I/O to be unbuffered.

Syntax
#include <stdio.h>
int setvbuf(FILE *stream, char *buffer, int buf_mode,
size_t buf_size);
FILE *stream; Pointer to stream whose buffer is being set

char *buffer; Pointer to buffer (or NULL if buffering not requested)

int buf_mode; Mode of buffering desired


size_t buf_size; Size of buffer in bytes, ifany assigned

Example Call
setvbuf(infile, buffer, _IOFBF, 2048);

Returns
If successful, setubuf returns a zero. In case of bad parameters or
other errors, the return value will be a nonzero.

See Also
setbuf

setvbuf
94 ANSI C Files and 1/0

Example
Line 66 in Example 7-2 turns off buffering when performing bi-
nary read and write operations on a file.

> sprintf

Purpose >
Use the sprintf function to format and write the values of vari-
ables to the string given in p__string. See printf for a description
of format _string.

Syntax
#include <stdio.h>
int sprintf(char *p_string, const char *format_string,...);
char *p_string; Pointer to an array of characters to which sprintf
sends its formatted output

const char *format_string; P character string that describes the


format to be used

eee Variable number of arguments that depends on the number of items


being printed

Example Call
sprintf(buffer, "FY 88 Profit = %.2f\n", profit);

Returns

The sprintf function returns the number of characters it has


stored in the buffer, not counting the terminating null character.

See Also

fprintf, printf, vfprintf, vprintf, vsprintf

Example
Line 50 in Example 7-1 uses sprintf to insert a line number into a
line read from a file.

NS SS SS SS

m sscanf

Purpose
Use sscanf to read characters from buffer and convert and store
them in variables according to the formats specified in for-
mat _string. See scanf for a description of the format_string
argument.

sscanf
7—ANSI C File 1/0 Routines 95

Syntax
#include <stdio.h>
int sscanf(const char *buffer, const char *format_string,...);
const char *buffer; Pointer to buffer from which characters will be
read and converted to values of variables

const char *format_string; A character string that describes the


format to be used

cee Variable number of arguments representing addresses of variables


whose values are being read

Example Call
sscanf(buffer, "Name: %s Age: %d'', &name, &age);

Returns

The sscanf function returns the number of fields that were suc-
cessfully read, converted, and assigned to variables. The count
excludes items that were read and ignored. If the string ends be-
fore the read operation is completed, the return value is the con-
stant EOF.

See Also

fscanf, scanf

tmpfile <

Purpose
Use tmpfile to open a temporary file for binary read/write opera-
tions (wb+ mode). The file is automatically deleted when your
program terminates normally or when you close the file.

Syntax
#include <stdio.h>
FILE *tmpfile(void);

Example Call
p_tfile = tmpfileQ;

Returns

The tmpfile function returns a pointer to the stream associated


with the temporary file it opens. In case of error, this pointer will
be NULL.

See Also
fclose, tmpnam

tmpfile
96 ANSI C Files and I/0

5se

> tmpnam

Purpose
Use the tmpnam function to generate a temporary file name in
the string file__name, which must have enough room to hold at
least L__tmpnam (a constant defined in stdio.h) characters. You
can generate_up to TMP_MAX (another constant defined in
stdio.h) file names with tmpnam.

Syntax
#include <stdio.h>
char *tmpnam(char *file_name);
char *file_name; Pointer to string where file name will be returned

Example Call
tmpnam(t filename) ;

Returns

The tmpnam function returns a pointer to the name generated.


If the argument to tmpnam is NULL, the return pointer will
point to an internal static buffer. If the generated name is not
unique, it returns a NULL.

See Also
tmpfile

> ungetc

PURPOSE
Use ungetc to push the character c back to stream. The charac-
ters that are pushed back are returned to subsequent read opera-
tions On stream in reverse order. You can push any character
except the constant EOF. Since wngetc pushes the character into
the stream’s buffer, any operation that tampers with the buffer or
the file’s current position (for example,fseek, fsetpos, or rewind)
may discard the pushed-back characters.

Syntax
Hinclude <stdio.h>
jnt ungetc(int c, FILE *stream);
int ¢y Character to be pushed into the file’s buffer

FILE *stream; Pointer to stream to which the character is pushed back

ungetc
7—ANSI C File |/0 Routines 97

Example Call
ungetc(last_char, infile);

Returns

If there are no errors, ungetc returns the character it pushed


back. Otherwise, it returns the constant EOF to indicate an error. .

See Also
fgetc, fputc, getc, getchar, putc, putchar

viprintf <

Purpose
Use ufprintf to write formatted output to stream, just as fprinif
would, except that vfprintf accepts a pointer to the list of vari-
ables (in arg__pointer) rather than the variables themselves, al-
lowing a variable number of items to be printed. See printf fora
detailed description of the format_ string argument.

Syntax
#include <stdarg.h>
#include <stdio.h>

int vfprintf(FILE *stream, const char


*format_string,
va_list arg_pointer);
FILE *stream; Pointer to stream to which the output goes

const char *format_string; Character


string that describes the
format to be used

va_list arg_pointer; Pointer to a list containing a variable number


of arguments that are being printed

Example Call
vfprintf(stderr, p_format, p_arg);

Returns
The vufprintf function returns the number of characters it has
printed, excluding the terminating null character.

See Also
printf, sprintf, vprintf, vsprintf, va_arg, va_end

Example
See Example 7-3 at the end of this chapter. Line 29 in that ex-
ample uses vfprintftoimplement an error-handling routine that
accepts a variable number of arguments.

viprintf
98 ANSI C Files and 1/0

_______
ee

> voprintf

Purpose
Use uvprintf to perform the same functions as printf (that is, write
formatted output to stdout) when you only have a pointer to the
list of variables to be printed (in arg_pointer) rather than the
variables themselves. This allows a variable number of argu-
ments to be printed. The format_string is described under
printf.

Syntax
#include <stdarg.h>
#include <stdio.h>

int vprintf(const char *format_string, va_list arg pointer);

const char *format_string; Character string that describes the


format to be used

va_list arg_pointer; Pointer to a list containing a variable number


of arguments that are being printed

Example Call
vprintf(p_format, p_arg);

Returns

The uvprintf function returns the number of characters it has


printed, excluding the terminating null character.

See Also
fprintf, printf, sprintf, vfprintf, va_arg, va_end

Example
Line 29 in Example 7-3 uses ufprintf. You can use vprinif in a
similar manner.

> vsprintf

Purpose
Use usprintf to perform the same function as sprintf (i.e., write
formatted output to the string p__string) except that vsprintf

vsprintf
7—ANSI C File 1/0 Routines 99

accepts a pointer to a list of variables (in arg__pointer) rather


than the variables themselves. Thus a variable number of argu-
ments can be formatted. See printf for a description of the
forma _ string
t argument.

Syntax
#include <stdarg.h>
#include <stdio.h>

int vsprintf(char *p_string, const char *format_string,


va_list arg_pointer);
char *p_string; Pointer to an array of characters to which vsprintf
sends its formatted output

const char *format_string; Character string that describes the


format to be used

va_list arg_pointer; Pointer to a list containing a variable number


of arguments that are being printed

Example Call
vsprintf(err_msg, p_format, p_arg);

Returns

The vsprinif function returns the number of characters it has


printed, excluding the terminating null character.

See Also

fprintf, printf, sprintf, vfprintf, vprintf, va_arg, va_end

Example
Line 29 in Example 7-3 uses vfprintf. You can use vsprintfin a
similar manner.

Example 7-1. This program numbers the lines of the listings


that appear in each example. It opens a source
file, reads a line, adds a line number, and writes
it to a destination file. This cycle is repeated
until you reach end-of-file in the soutce file.

1:/* This program numbers the lines in a file.


2: * Assume a maximum of 999 lines in the file.
3: */
4:#include <stdio.h>
5:4#define MAXCHR 80
6:main()
Gs
8: char Line[MAXCHR], infilename[MAXCHR],
9: outfilename[MAXCHR], *rline;
1 0: FILE *infile, *outfile;

vsprintf
100 ANSI C Files and 1/0

ANE int lineno = 0;


ties rline = &line[4];
Asi printf("Line numbering program\n"
14: "Enter input file name:");
Sis gets (infilename);
16:/* Open input file in text mode for read
17: * operations i
18: */
19: if (Cinfile = fopen(infilename,"r'')) == NULL)
20: { ~
CANE printf("Error opening %s\n"', infilename);
cee exit (1);
253 D:
24: printf("Enter output file name:'');
25: gets (out filename);
26:/* Open output file in text mode for write
27: * operations
28: */
29: if (Coutfile = fopen(outfilename,''w'')) == NULL)
30: i
bale printf("Error opening %s\n'', outfilename);
32: exit(1);
33: }
34:/* Read lines from the input file, add line numbers
35: * and write each Line out */
36: while 1)
SAE xf
38: if(fgets(rline, MAXCHR, infile) == NULL)
39: {
40: if(ferror(infile) != Q)
41: puts("Error during read'');
42: if(feof(infile) != 0)
43: puts("File ended");
44: clearerr(infile);
45: break; /* Exit the while loop */
46: }
47: else
48: fi
49: Lineno++;
50: sprintf(line, '%3d'', Lineno);
Bilis Line[3] = ':';
525 fputs(line, outfile);
D5 >
54: }
Shy printf(''%d lines written to %s\n",
56: Lineno, outfilename);
aye fclose(infile);
Doe fclose(outfile);
7—ANSI C File 1/0 Routines 101

Example 7-2 Here is a small data base program to illustrate


how fread and fwrite can be used to read and
write fixed-length records of binary data. The
data base stores records containing names of
books and authors. The program creates a data
base and allows you to search for books by ti-
tle. The program can find a book even if the
title isincomplete. Here is a sample output:
Database Program
Enter name of data base file to create:test.db
Enter command
(f = find a record, q = quit):f
Book's title: Turbo
=——— FOUND =——=
Title: Turbo C Bible
Author: Naba Barkakati
Publisher: Howard Sams & Company
Year: 1988
Enter command
(f = find a record, q = quit):
ExaibainGae

The program listing follows:

NS a a ea a */
2:/* A simple data storage and retrieval program */
Bie
4:#include <stdio.h>
5:#include <stdlib.h>
6:#include <string.h>
v:
8:/* Define data structures */
9:struct file_header
10:¢
Tas unsigned recordsize;
nliZis unsigned numrecords;
oa
14:
15:struct book_record
nose
ies char titlel80];
18: char author_last(20];
We char author_first[20];
20: char publisher[40];
Zi unsigned year;
eal?
25%
24:/* Declare data objects */
25:static struct book_record mybooks[] =
26:f
ts {"Microsoft C Bible", ''Barkakati", "Naba'',
28: "Howard Sams & Company", 1988},
102 ANSI C Files and 1/0

29: {''Turbo C Bible","Barkakati", ''Naba'',


30: "Howard Sams & Company'', 1988},
a1: {"Microsoft C Programming for the IBM", "Lafore",
See "Robert", "Howard Sams & Company'', 1987},
35: {"Essential Guide to ANSI C", "Barkakati",
34: "Naba'', "Howard Sams & Company", 1988},
35: {"Advanced C Primer Plus", "Prata", '"'Stephen",
36: "Howard Sams & Company'', 1986}
Stare
38: 2
39:static size_t numbooks = sizeof(mybooks) /
40: sizeof(struct book_record);
41:
42:static struct file_header myheader =
43: { sizeof(struct book_record),
44: sizeof(mybooks) / sizeof(struct book_record) };

48: FILE *dbfile;


49: int c, file_open = 0;
50: size_t numread, s_len, len;
ons long fpos;
EYH char dbname[80], bktitlel80);
Doi: struct book_record book;

Beis printf('"'Database Program\n'');

57:/* Create a database file */


58: printf("Enter name of data base file to create:');
59: gets (dbname) ;
60: if ((dbfile = fopen(dbname, ''wbt+')) == NULL)
61: Lu
62: fprintf(stderr, "%s <- No such file\n", dbname);
63: exit(1);
64: 33
65:/* Turn off buffering for the data base file */
66: setvbuf(dbfile, NULL, _IONBF, 0);
67:
68:/* Save file header and book records */
69: if (fwrite(&myheader, sizeof(struct file_header), 1,
70: dbfile) != 1)
(Gi {
(és fprintf(stderr, "Error writing to %s\n'"', dbname);
Tete exit(2);
74: a;
(as
76: if (fwrite(mybooks, sizeof(struct book_record),
{Cs numbooks, dbfile) != numbooks)
78: ti
79: fprintf(stderr, "Error writing to %s\n"', dbname);
80: exit(2);
7—ANSI C File 1/0 Routines 103

81: 2
82:
83:/* Let user manipulate data base */
84: printf("Enter command\n(f = find a record, "
85: "q = quit):");
86:/* Command processing loop */
87: while( (c = getchar()) != EOF)
88: {
89:/* Flush buffer so that fresh input can be read */
90: fflush(stdin);
91: switch (c)
92: {
93: case 'f': /* FIND */
94: case 'F';
95: printf("Book's title: '");
96: gets(bktitle);
97: s_len = strlen(bktitle);
98:/* Advance file pointer past file header */
99: fseek(dbfile, (long)sizeof (struct
100: file_header), SEEK_SET);
101:/* Find data record with this title */
102: do
103: {
104: fpos = ftell(dbfile);
105: numread = fread(&book, sizeof (struct
106: book_record), 1, dbfile);
107: len = strlen(book.title);
108: /* Compute length to compare */
109: len = min(s_len, len);
110: 3
Ae while(numread == 1 &&
112: strncmp(book.title, bktitle, len) != 0);
113: if (numread != 1) ;
114: {
115:/* Book by this author is not in data base */
116: fprintf(stderr, '"%s not in"
117: "data base\n", bktitle);
118: exit(3);
ARO D:
120:/* Display the
record that was found */
raul printf('\n---- FOUND ----\n''
122: ue Title: %s\n"
123: "Author: %s %s\n"
124: "Publisher: %s\n'"'
1252 dt Year: Zu\n'"', book.title,
126: book.author_first, book.author_last,
2G: book.publisher, book.year);
128:/* We have the spot marked for this record. If this
129: * record were updated, you could go to this position
130: * with fseek(dbfile, fpos, SEEK_SET) and use fwrite
131: * to write back the updated record.
ASeee kL.
104 ANSI C Files and !/0

133: break;
134:
135: case ‘q': /* QUIT */
136: case ‘Q':
“IBI/2 printf("\nExiting...\n'");
138: fclose(dbfile); /* Close file */
139: exit(0); :
140: } 141:/* Ask user for command again */
142: printf('\nEnter command\n(f = find a record, "'
143: ~ Ng = quite)
144: }
1453}

Example 7-3 This example shows an error-handling routine


that takes a variable number of arguments and
prints an error message to the predefined
stream stderr. The arguments are extracted by
the macros va__start, va_arg, and va_end,
which are defined in stdarg.h. The printing is
done by vfprintf. A sample main program is in-
cluded.

1:#include <stdio.h>
2:#include <stdarg.h>
3:void error_handler(char *,...);
4:char filename[80] = ''EXAMPLE.C'':
5:main()
6:¢
G int line_no = 31;
8:/* Call the error handler to print an error message.
9: * First just a single line. Then a more detailed message
10: * with more arguments.
Toe,
nee error_handler(''Syntax error\n');
ENP error_handler("'File: %s at line: %d\n'"', filename,
14: line_no);
1533
NOS] Rr crn errno */
17:/* error_handler: accepts variable number of arguments
18: * and prints messages to stderr
192 -#/
20:void error_handler(char *my_format,...)
PANERS
Zes va_list arg_pointer;
23:/* Use va_start macro to get to the start of the variable
24: * number of arguments. This will alter the pointer
25: * arg_pointer to point to the list of variables to be
26: * printed.
Ce
28: va_start(arg_ pointer, my_format);
29s vfprintf(stderr, my_format, arg_pointer);
7—ANSI C File |/0 Routines 105

30:/* Use the va_end macro to reset the arg_pointer */


Sis va_end(arg_pointer);
523)
33%
* pret Wie,
* laa vbw. 1
vii-geae
oe :

ss)

> =~

0 ae ike
*
rieie
Be a
ANSI C Process Control and
Memory Management

107
Process Control

Introduction
The process control routines include the signal-handling rou-
tines that take care of error conditions, and the utility routines
that terminate a process, communicate with the operating sys-
tem, and set up numeric and currency formats. The routines de-
scribed in this chapter are defined in locale.h, signal.h, setjmp.
h, and stdlib.h.

Process, Environment, Locale, and Signals


A “process” is an executable program in memory and its associ-
ated environment. When you run a program, you create a pro-
cess. The environment of a process includes all the information
necessary to execute the process. The exact interpretation of the
environment differs from one system to another. In UNIX and
MS-DOS, it includes a list of strings that contain definitions of
environment variables.

Passing Information Via Environment Variables


The capability of accessing environment variables can be ex-
ploited by your C programs. If you were to develop an electronic
mail application, for example, you could send a copy of a mes-
sage to all the addresses listed in an environment variable DIST-
LIST. You would get at this environment variable via the library
routine getenv, one of the utility routines defined in stdlib.h.

Signals
Signals are the operating system’s way of interrupting a process
when certain error conditions, also called “exceptions,” occur.

109
110 ANSI C Process Control and Memory Management

The signal mechanism is present in UNIX and is supported by


most C libraries, including the proposed ANSI C library.
Each exception has a signal to handle it. You can use the li-
brary routine signal to install your own routine to handle a par-
ticular signal. When that exception occurs, the handler for that
signal is called. You can use the raise function to explicitly gen-
erate a signal.
Table 8-1 shows the constants defined in the signal.b
header file for each of the signals that ANSI C recognizes. The
default action for each signal depends upon the implementa-
tion. The default action is indicated by the symbolic name
SIG_DFL, while the action SIG_IGN indicates that the signal is
ignored. See the reference entry of the signal function for the
calling convention.

Table 8-1. Signals in ANS! C


Signal Exception Condition

SIGABRT — Abnormal termination of program, for example, by calling the abort


function.
SIGFPE Floating-point error, such as overflow or division-by-zero.
SIGILL Illegal instruction in the program.
SIGINT Generated when user presses a key designed to get the attention of the
operating system. For example, pressing Control-C in UNIX or MS-DOS
would generate this signal.
SIGSEGV _Illegal memory access.
SIGTERM Termination request sent to the program.

Nonlocal Jumps in C: \ongjmp and setimp


Sometimes it is handy to be able to abort what you were doing
and get back to where you started. For example, you may want
to return to execute some code for error recovery no matter
where an error is detected in your application. The setjmp and
the /ongjmp functions provide the tools to accomplish this. The
setjmp function saves the “context” of the process and longjmp
uses the saved context to revert to a previous point in the pro-
gram. The context (or “state”’) of aprocess refers to the informa-
tion that allows you to reconstruct exactly the way the process is
at a particular point in its flow of execution. ANSI C requires that
a compiler define an array data type named jmp_ buf that will be
capable of holding the information needed to restore a calling
environment. This data type is defined in the header file setjmp.
b.
To understand the exact mechanics ofsetjmp and longjmp,
look at this code fragment:
#include <setjmp.h>
jmp_buf saved_context;
8—Process Control! 111

main()
{
if (setjmp(saved_context) == 0)
{
do_something();
3:
else
{
/* This part executed when longjmp is called «*/
handle_error();
}
}
do_something()
at
int something_wrong;

if(something_wrong) longjmp(saved_context, 1);


}

Upon entry to the setjmp function, it saves the current context


and returns a zero. In this case, the if statement is satisfied and
do__something( ) is called.
When something goes wrong in do_something( ) (indi-
cated by the flag something __wrong), call longjmp with two ar-
guments: the first is the buffer that contains the context to which
you return. When the calling environment reverts to this saved
state and the return statement in /ongjmp is executed, it is as if
you are returning from the call to setjmp, which originally saved
the buffer saved_context. The second argument to /ongjmp
specifies the return value to be used during this return. It should
be other than zero so that in the /f statement you can tell
whether the return is induced by a longjmp.
The setjmp/longjmp combination gives you the capability
to jump unconditionally from one C function to another with-
out using the conventional return statements. Essentially, setjmp
marks the destination of the jump and longjmp is a nonlocal
goto that executes the jump.

Locale of a Program
The term “locale” refers to the locality (a country) for which cer-
tain aspects of your program can be customized. ANSI C groups
the country or locale-dependent aspects of a C program into six
categories. Table 8-2 summarizes the locale categories defined in
the header file Jocale.b. You can use the setlocale function to set
each category shown in Table 8-2 to conform to a selected locale.
The locale named “‘C”’ indicates the minimal environment for C
translation. Other locale names will be implementation depen-
dent. The locale-specific functions and formatting information
are not yet present in any commercial C compilers. However, as
compilers begin to provide full ANSI compatibility, these func-
tions should become available in most C compilers.
112 ANSI C Process Control and Memory Management

Table 8-2. Local Categories in ANS! C

Locale Category Parts of Program Affected

LC_ALL The entire program’s locale-specific parts (all categories


shown below)
LC_ COLLATE Behavior of the routines strcol/ and strxfrm (see Chapter 14)
LC_ CTYPE Behavior of the character handling functions and multibyte
functions (See Chapters 13 and 14)
LC__MONETARY ~~ Monetary formatting information returned by the
localeconv function
LC__NUMERIC Decimal point character for the formatted output routines (for
example, printf) and the data conversion functions (see Chapter
11), and the nonmonetary formatting information returned by
the /ocaleconv function
LC_TIME Behavior of the strftime function (see Chapter 16)

You can obtain the numeric and currency formatting style


for the current locale by calling the function /ocaleconv. This
formatting information, returned in a /conv structure (defined in
locale.h), includes such details as the decimal point character
and the currency symbol for the current locale. The reference
entry for the /ocaleconv function shows the fields in the /conv
structure.

The Process Control Routines


The process control functions (see Table 8-3 for a complete cata-
log) can perform a variety of functions. Table 8-4 shows the pro-
cess control routines categorized by task.

Executing Operating System Commands


What if you wanted to use acommand of your operating system
from your C program? This task is made simple by the ANSI C
library routine system which can accept and execute a system
command. The implementation of the system function will vary
by system.

Terminating a Process
You can use two functions to terminate a process: abort and exit.
Of course, any process terminates automatically when its body
of code ends. When a C process terminates normally via a call to
exit or when its execution is complete, several things happen.
First, a set of up to 32 routines that were installed earlier by calls
to atexit are called in a last-in first-out (LIFO) order. Then, all
buffers associated with streams open for I/O will be flushed. Fi-
nally, the process will end and control will return to its parent.
The abort function terminates a process without going
8—Process Control 113

Table 8-3. Process Control Routines


a
eeeeeeSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSsSsSsS—

Routine Description

abort Raises the SIGABRT signal after printing a message to stderr. The
normal handler for SIGABRT terminates the process without flushing
file buffers.
assert Prints a diagnostic message and aborts program if a given logical
expression is false.
atexit Installs a routine to a stack of at least 32 routines that will be called in
“Jast-in first-out” order when the process terminates.
exit Calls the functions installed by atexit, flushes all buffers associated
with streams that are open for 1/0, and terminates the process and
returns to the operating system.
getenv Returns the definition of an environment variable from the environment
of the process.
localeconv Sets the components of a /conv structure with information about
numeric and monetary formatting appropriate for the current locale.
longjmp Restores the context of a process, which causes an unconditional
jump to the place from which setimp was called to save that
particular context.
perror Prints an error message using your message and the system message
corresponding to the value in the global variable errno.
raise Generates a signal (an exception).
setimo Saves the context of a process in a buffer that can be used by /ongjmp
to jump back.
signal Installs a function to handle a specific exception or signal.
setlocale Selects a locale for a specified portion of the program’s locale-
dependent aspects.
system Executes an operating system command.

Table 8-4. Process Control Routines by Task

Task Routines

Execute an operating system command system


Terminate a process abort, exit
Handle errors assert, perror
Get environment getenv
Install exception handler and generate an exception raise, signal
Nonlocal jump from one function to another longjmp, setjmp
Install routines to be called when the process terminates atexit
Control locale-specific numeric and currency formatting localeconv, setlocale

through the niceties of normal termination. The buffers are not


flushed (desirable when you know that the data in the buffers may
“be corrupted), nor do they call the routines that are supposed to
be called upon program termination. The abort function also
prints a message indicating that the program terminated abnor-
mally.
114 ANSI C Process Control and Memory Management

E
(PRE SEE a S

> abort

Purpose
Use abort, which calls raise(SIGABRT), to exit your program ab-
normally. Note that unlike exit, abort will not flush the file buf-
fers or call the routines set up by atexit. You can take care of
these chores; however, by setting up the processing for the
SIGABRT signal.

Syntax
#include <stdlib.h>
void abort(void);

Example Call
abort ();

See Also

atexit, exit, raise, signal

> assert
Purpose
Use the assert macro to print an error message and abort the pro-
gram if the <expression) is false. Typically, assert is used to iden-
tify program errors during the debugging phase. After the
program is debugged, you can disable all occurrences of the as-
sert macros by defining the preprocessor macro NDEBUG.

Syntax
#include <assert.h>
void assert (<expression>);
<expression> C statements specifying assertion being tested

Example Call
assert(arg_ value >= 0);

See Also

abort

assert
8—Process Control 115

SSS)

atexit <4

Purpose
Use atexit to set up a stack of up to 32 (this is the minimum num-
ber specified by ANSI C) functions that the system will call in
LIFO order when your program terminates normally. Note that
the functions passed to atexit cannot take arguments. This fea-
ture is useful for setting up housecleaning chores to be per-
formed at program termination.

Syntax
#include <stdlib.h>
int atexit(void (*func) (void));
void (*func) (void); Pointer to function to be called

Example Call
atexit(cleanup_all);

Returns

The atexit function returns a zero if successful. Otherwise, it re-


turns a nonzero value.

See Also
exit

Example
See Example 8-1 at the end of the chapter. Line 18 in that example
installs the cleanup function that will be called when the pro-
gram exits by an exit call.

exit <4

Purpose
Use exit to terminate your program normally by flushing file
buffers, closing files, and invoking functions set up with alexit.
A value of zero or EXIT __SUCCESS for status means normal exit.
EXIT_FAILURE indicates errors.

Syntax
H#include <stdlib.h>
void exit(int status);
int status; Exit status code

exit
116 ANSI C Process Control and Memory Management

Example Call
exit (EXIT_SUCCESS);

See Also

abort, atexit

Example
Lines 23, 51,-60, and 71 in Example 8-1 show calls to exit.

LS SD

> getenv

Purpose
Use getenv to get the definition of the environment variable
varname from the environment of the process.

Syntax
#include <stdlib.h>
char *getenv(const char *varname);
const char *varname; Name of environment variable to look for

Example Call
current_path = getenv("PATH') ;

Returns

If varname is found, getenv returns a pointer to the string value


of varname. If varname is undefined, getenv returns a NULL.

> localeconv

Purpose
Use the localeconv function to get detailed information on for-
matting monetary and numeric values by the rules of the current
locale,

Syntax
#include <locale.h>
struct lconv *localeconv(void);

Example Call
p_lconv = localeconv();

localeconv
8—Process Control 117

Returns

The /ocaleconv function returns a pointer to a /conv structure


whose fields are filled in with formatting information appropri-
ate for the current locale. Use setlocale to set the current locale.
The /conv structure is declared in locale.h as follows:
struct lconv
{
char xdecimal_point; /* Decimal point character for
nonmonetary quantities */
char *thousands_sep; /* Separator for groups of digits

to the left of decimal point


for nonmonetary quantities */
char *grouping; /* Size of each group of digits

in nonmonetary quantities */
char *int_curr_symbol; /* International currency symbol
for the current locale */
char *currency_symbol; /* Local currency symbol
for the current locale */
char *xmon_decimal_point; Decimal point character for
monetary quantities */
char *mon_thousands_sep; Separator for groups of digits
to the left of decimal point
for monetary quantities */
char *mon_grouping; /* Size of each group of digits
in monetary quantities */
char *positive_sign; /* String denoting sign for non-
negative monetary quantities
*/
char *xnegative_sign; /*x String denoting sign for
negative monetary quantities
*/
char int_frac_digits; /* Number of digits to the right
of decimal point in
internationally formatted
monetary quantities */
char frac_digits; /* Number of digits to the right
of decimal point in formatted
monetary quantities */
char p_cs_precedes; |x 1 = currency_symbol precedes,
0 = succeeds positive value */
char p_sep_by_space; /* 1 = space, 0 = no space
between currency_symbol and
positive formatted values */
char n_cs_precedes; /* 1 = currency_symbol precedes,
0 = succeeds negative value */
char n_sep_by_space; /* 4 space, 0 = no space
between currency_symbol and
negative formatted values */
char p_sign_posn; /* Position of positive_sign
in positive monetary
quantities */

localeconv
118 ANSI C Process Control and Memory Management

char n_sign_posn; /* Position of negative_sign


in negative monetary
quantities */
i;

See Also

setlocale

> longimp

Purpose
Use the /ongjmp function to restore the calling environment to
that contained in the jmp_buf array env. This environment
must have been saved by an earlier call to setjmp. Note that
longjmp restores all local variables (except the ones declared
volatile) to their previous states and returns as if from the last call
to setijmp with the return value retval.
Since /ongjmp jumps to the return address of the last match-
ing call to setjmp, make sure that the call to Jongjmp occurs be-
fore the function in which you called setjmp has returned.

Syntax
‘Hinclude <set jmp.h>
void longjmp(jmp_buf env, int retval);
jmp_buf env; Array data type where the calling environment is stored

int retval; Value that appears to be returned by the earlier call to


setjmp

Example Call
longjmp(stack_env, 1);

See Also
set jmp

Example
Line 75 in Example 8-1 calls /ongjmp to return to the main com-
mand loop when the user presses a Control-C.

SE
EE

Pm perror

Purpose
Use perror to construct an error message concatenating the mes-

perror
8—Process Control 119

sage you provided in the argument string with the system mes-
Sage corresponding to the current value in the global variable
errno and print the message to stderr.

Syntax
#include <stdio.h>
void perror(const char *string);
const char *string; Your part of the message

Example Call
perror("Error closing file");

See Also

strerror

Example
Line 22 in Example 8-1 uses perror to display an error message.

raise <4

Purpose
Use rdise to “raise a signal” that creates an exception condition
corresponding to the number signum. The exception is handled
by invoking a routine set up earlier by calling the function sig-
nal. The abort function uses raise to create the exception
SIGABRT to initiate actions to be taken when aborting a pro-
gram.

Syntax
#include <signal.h>
int raise(int signum);
int signum; Signal number to be raised

Example Call
raise(SIGABRT) ;

Returns
If successful, raise returns a zero. Otherwise, it returns a non-
zero value.

See Also

abort, signal

raise
120 ANSI C Process Control and Memory Management

> setjmp

Purpose
Use the setjmp macro to save a stack environment in the
jmp —buf array env before calling another function. You can re-
store this environment by a call to /ongjmp, achieving the effect
of a nonlocal goto. When /ongjmp is called later with the saved
calling environment, it restores all stack-based local variables in
the routine to the values they had when setjmp was called and
then jumps to the return address that setjmp saved. This feels
like a return, one more time, from the last call to setjmp. Note
that this process does not guarantee the proper restoration of
register-based and volatile variables.

Syntax
#include <setjmp.h>
int setjmp(jmp_buf env);
jmp_buf env; Array data type where the current calling environment is
stored

Example Call
if (setjmpCenv) != 0) printf ("Returned from longjmp\n");

Returns
After saving the stack environment, setjmp returns a zero. When
longjmp is called with the environment saved by this call to
setjmp, the effect is of returning from setjmp again, this time
with the second argument of /Jongjmp as the return value.

See Also

Long jmp

Example
Line 30 in Example 8-1 establishes a mark in the main program to
which you can jump from any place in the program by calling
longjmp.

SSS

> setlocale

Purpose
Use setlocale to define the locale named in the string /o-
cale__name for the locale-dependent aspects of your program

setlocale
8—Process Control! 121

specified by the argument category. The category can take any


of the values shown in Table 8-2.

Syntax
#include <locale.h>
char *setlocale(int category, const char *locale_name);
int category; Indicates which part of your program’s locale-dependent
aspects you are defining a locale for: LC_ALL,
LC_COLLATE, LC_CTYPE, LC __MONETARY,
LC_NUMERIC, or LC_TIME

char *locale_name; The name of the locale that will control the
Specified category

Example Call
setlocale(LC_ALL, ''C");

Returns

If /ocale_name is not NULL and setlocale is successful, it re-


turns the string associated with the specified category for the
new locale. Otherwise, setlocale returns a NULL and the pro-
gram’s locale is not changed.

See Also
localeconv

signal <

Purpose
Use the signal function to set up the routine func as the handler
for the exception or signal number signum. The handler is ex-
pected to accept the signal number as an argument. The signal
number signum must be one of the constants shown in Table
8-1. These are defined in the include file signal. h. If you want to
ignore a signal, use SIG__IGN as the second argument to s7gnal.
Specifying SIG__DFL as the second argument sets up the imple-
mentation-defined default handling for the signal.

Syntax
#include <signal.h>
void (*signal(int signum, void (*func) Cint))) Cint);
int signum; Signal number for which a handler is being set up

void (*func) (int); Pointer to handler that can accept an integer


argument

Example Call
if(signal (SIGINT, ctrlc_handler) == SIG_ERR)

signal
122 ANSI C Process Control and Memory Management

{
perror("signal failed");
exit (0);
a6

Returns
If successful, signal returns the pointer to the previous handler.
In case of error, it returns the constant SIG_ERR and sets the
global variable errno to an implementation-defined error con-
stant. SS

See Also
abort, raise

Example
Lines 20, 68, and 73 in Example 8-1 illustrate the use ofsignal to
handle the SIGINT signal.

> system

Purpose
Use system to execute the operating system command contained
in string from your program. If string is NULL, system returns a
nonzero value only if a command processor (for example, the
UNIX shell) is present in the environment.

Syntax
#include <stdlib.h>
int system(const char *string);
const char *string; Command to be executed

Example Call
system("Ls'"');

Returns

If string is not NULL, system will return an implementation-


defined value.

; system
8—Process Control 123

Example 8-1 The pair setjmp and longjmp is ideal for error
handling or handling special conditions ina
program. You call setjmp at a place where vou
have code that you may want to execute later.
Then, whenever your conditions are met, call
longjmp with the jmp_ buf variable saved ear-
lier by setjmp. This places you where setjmp
was called originally. It appears as if the setjmp
function returned a second time, this time
with the value from the second argument to
longjmp. Here is a small program that illus-
trates a way to use this versatile duo. Notice
how atexit is used to set up a function that
handles housecleaning chores before exiting
the program. This program also establishes
signal handling for the Control-C keypress
(SIGINT signal).
1:#include <stdio.h>
2:#include <signal.h>
3:#include <setjmp.h>
4:
5:static int ctrlc_handler(int);
6:static void cleanup(void);
as
8:/* Buffer used by setjmp and longjmp */
9:jmp_buf main_menu;
10:
11:static FILE *datafile = NULL;
12:
13:main®
T4Et
iD char input(80];
16: int choice=0;
17:/* Install routine to be called by ‘exit’ */
18: atexit (cleanup);
19:/* Take over the Control-C interrupt */
20: if(signal (SIGINT, ctrlc_handler) == SIG_ERR)
21: xg
22: perror("signal failed’);
233 exit(1);
24: }
2a printf("Installed SIGINT signal handler\n"');
26:
27:/* Call ‘setjmp’ to set up for returning to this
28: * point after user presses Control-C
29: */
30: if(setjmp(main_menu) != 0)
571: {
32:/* Returning from a ‘longjmp' -- print message */
53% printf (''Interrupted...\n');
34: fflush(stdin); /* flush input buffer */
35: }
124 ANSI C Process Control and Memory Management

:/* This is the main menu of the program */


38: printf(''1 Loop endlessly...\n"
59% "anything else to exit\n\n"
40: "Enter Choice: ');
41: gets (input);
42: choice = atoi (input);
43: switch(choice)
44: €
45: case 1:
46: printf("Enter name of file to open: ');
47: gets (input);
48: if (datafile = fopen(input,"'r')) == NULL)
49: {
50: printf("Error opening %s\n"', input);
Slr exit(2);
528 }
55:
54:/* The next Line is an endless loop - simulates a
55: * process gone awry.
56: */
Bs forG=) {print feloopingee..
58: "press “C to interrupt\n');
59:
60: default: exit (0);
61: }
62:}
63 ; /k--------------------------------------------------- */
64:int ctrlc_handler(int sig)
65:¢
66:: nity crs
67:/* First arrange to ignore further SIGINT */
68: Signal (SIGINT, SIG_IGN);
69: printf('"\nInterrupted. Quit?'');
70: c = getchar();
cls if(c == 'y' |! ¢ == 'Y') exit(0);
72:/* Re-enable interrupt handler -- and return */
73 signal (SIGINT, ctrlc_handler);
74:/* Return to the main menu--to place marked by setjmp*/
755 longjmp(main_menu, 1);
76:}
Vg|Rome nnnna= x/
78:void cleanup(void)
CIERE
80:/* This routine handles the "house cleaning" chores */
81: puts("Cleaning up...'');
82: if (datafile != NULL) fclose(datafile);
83:)
Variable Arguments

Introduction
In writing C programs you encounter functions, such as printf,
that can take a variable number of arguments. Take, for instance,
a routine (findmax) that picks the largest integer from an array. If
the routine can accept a variable number of arguments, you can
use such calls as findmax(1,2,3) and findmax(a,b,c,d) to find
the maximum of any number of arguments. A set of macros in
ANSI C makes handling a variable number of arguments a
straightforward task.

Using the Variable Arguments Macros


The macros for handling variable-length argument lists are de-
fined in the header file stdarg.h. Table 9-1 shows a catalog of
these macros.
The function accepting variable arguments must declare a
pointer to hold the address of the current argument. Use the
macro va _start to initialize this pointer. Each successive use of
the macro va__arg sets the pointer to the next argument. The
type of the variables on the stack is required as an argument to
these macros. The ANSI standard requires that you invoke the
macro va__end after your program accesses all the arguments.
The function must require at least one fixed argument (which
precedes the ellipsis in the function’s prototype) to be present
when the function is called. Here is a step-by-step procedure for
accessing the variable arguments:
1. Access the fixed arguments by name. These arguments are
declared as parameters in the usual manner. Declare a vari-
able arg__ptr of type va_list, which is a type suitable for

125
126 ANSI C Process Control and Memory Management

holding information needed by the macros va_arg,


va _end, and va _start.
2. Use the va_start macro with arg_ptr and the name of the
last fixed argument. This sets arg__ptr to the beginning of
the list of optional arguments to the function. Caution: If
the last fixed argument is declared with the register storage
class, va__start will not work properly. ,
4. Use the va_arg macro to retrieve the next argument of a
specified type. This macro updates arg_ptr and returns a
pointer to the argument being sought. Repeat this step until
you havevaccessed all of the arguments. You have to decide
on a value that will mark the end of the list. For example, if
you are accessing integer arguments, a value of —1 might be
used to mark the end of the argument list.
4. Use the va_end macro when you are ready to return from
the function.

Table 9-1. Variable Argument Macros

Macro Description

Va__arg Gets the next argument from the stack


va__end Resets everything so that the function can return normally
va_start Initializes the argument pointer to the address of the first argument to
the function

End of the Argument List


After the va__start macro is called once, you can get the func-
tion’s parameters with successive calls to the va_arg macro.
While these macros help us access the arguments, they cannot
tell when the argument list ends. In fact, the only way to tell this
is by adopting some sort of convention. For example, if each ar-
gument were a pointer, you could mark the end of the argument
list with a NULL value.

> va_arg, va__end, va__ start

Purpose

Use the va_start, va__arg, and va_end macros to access the


arguments of a function when it takes a fixed number of re-
quired arguments followed by a variable number of optional
ar-
guments. The required arguments are in standard style and
are
accessed by parameter name. Access the optional arguments
with the macros va_start, va__arg, and va_end.

va__arg, va__end, va__start


9—Variable Arguments 127

S yntax
# include <stdarg.h>
< type> va_arg(va_list arg_ptr, <type>);
void va_end(va_list arg_ptr);
Vv oid va_start(va_list arg ptr, prev_param);

Vv a_list a EGuptr; Pointer to list of arguments

p rev_param Name of parameter


just preceding first optional argument

< type> Type of argument to be retrieved, for example char *

Example Call
v a_start(argp, firstint);
f
irst_x = firstint;
n ext_x = va_arg(argp, int);

Returns

The va_arg macro returns a pointer to the next argument of


given type. The va_start macro sets a pointer to the beginning
of the list of arguments.

See Also

Vv fprintf, vprintf, vsprintf

Example 9-1 Demonstrate the use of variable-length argu-


ment processing by writing a function that ac-
cepts a variable number of integer arguments
and returns the largest value. Assume that a
value of —999 marks the end of the argument
list. Write a main program that shows how the
function is used.
#include <stdio.h>
# include <stdarg.h>
i nt findmax(int, ...);
m ain®
{
int maxvalue;
/ * The end of the list of integers is marked by -9999 x/
maxvalue = findmax(-1, 20, 30, 50, -9999);
printf (''findmax(-1, 20, 30, 50, -9999) returns: \
%d\n"', maxvalue);
maxvalue = findmax(1, 2, 3, 4, 5 pale (hr ip Sel
printf ("findmax(1, 2, 3, 4, 5, 6, Thy hp AAD
ig eturns: %d\n'', maxvalue);

/ * The '"'findmax" finds the largest value in a list


* of integers. It uses the "va_...'' macros to get
* the arguments. This is the ANSI version.
*/

va__arg, va__end, va__start


128 ANSI C Process Control and Memory Management

int findmax(int firstint, ...)


{
int maxval = -9999, x = 0;
va_list argp;
/* Get the first optional parameter using ''va_start' */
va_start(argp, firstint);
x = firstint;
while(x != -9999)
{
if(maxval. < x) maxval = x;
x = va_arg(argp, int);
}
return (maxval);
Memory Allocation

Introduction
Most computer systems store instructions and data in memory
and use a central processing unit (CPU) such as the Intel
8088/8086 microprocessor in an IBM PC or the Motorola
MC68000 in an Apple Macintosh to retrieve instructions from
memory and execute them. The operating system, itself a pro-
gram residing in memory, takes care of loading other programs
and executing them. It has its own scheme of managing the avail-
able memory for its data and that for other programs as well.
In older programming languages, such as FORTRAN, no
provision is made for requesting memory at run-time. All data
items and arrays have to be declared before the program is com-
piled, so you have to guess beforehand the maximum size of an
array and there is no way to exceed the maximum other than by
recompiling the program. This is inefficient because you are
locking in the maximum amount of memory your program will
ever need.
In most modern languages, including C, you can request
blocks of memory at run-time and release the blocks when your
program no longer needs them. A major advantage of this is that
you can design your application to exploit all available memory
in the system. Like most other capabilities in C, this one is avail-
able as a set of library routines, known as the “memory alloca-
tion” routines. The ANSI C set has four basic memory allocation
routines.

Using the Memory Allocation Routines


The memory allocation functions, cataloged in Table 10-1, give
you all the memory management tools necessary for building

129
130 ANSI C Process Control and Memory Management

complex applications that use the available memory intelli-


gently. This section summarizes usage of the routines.

Table 10-1. Memory Allocation Routines

Routine Description

calloc Allocates memory for an array of data elements and nitializes them to zero
free Frees previously allocated memory
malloc Allocates a number of bytes and returns a pointer to the first byte of the
allocated memory
realloc Enlarges or shrinks a previously allocated block of memory, moving the
block in the physical memory of the system, if necessary

You need memory allocation capabilities when you cannot


determine in advance the exact amount of space you will need to
store the data used or generated in your program. If the data is
generated during the course of the program, you may simply
want to get space as and when needed. (Also you may want to free
memory when it is no longer needed.) Typically, the data ele-
ments are in the form of a C structure with a field containing
pointers to the next element. This enables you to link one ele-
ment to the next and keep them accessible via a single pointer to
the beginning of the list. This type of data structure is known as a
linked list.
It is also common to want to allocate, at run time, a number
of data elements contiguously. Such a structure, called an array,
provides faster access than linked lists do to arbitrary data ele-
ments because you do not have to start at the beginning and
trace through the links.

Requesting Memory
You can use either malloc or calloc to get the needed memory.
While malloc simply returns a block of memory of specified
size, calloc allocates room for an array of a specified number of
elements, each of a given size, and it also initializes all the allo-
cated bytes to zero. Use the sizeof operator to get the size of a
data element.

Using the Allocated Block


The allocation routines return the address of the allocated block
as a pointer to void. You should always cast this pointer into a
pointer of the type of data for which you requested space so that
you can handle data items correctly. Since this pointer is the only
way to access the newly allocated block, you have to assign it to a
pointer variable to ensure that it is not destroyed. If the request
for memory fails, the return value will be NULL. Therefore, you
10—Memory Allocation 131

must always check for a NULL return value when you call any
memory allocation routines.

Releasing Memory
If you no longer need the data you stored in a block of memory
and you do not plan to store anything in that memory, you
should call free to release the block. Always pass a valid pointer
to the free function; if you pass a pointer that was not returned
by the calloc, malloc, or realloc, later calls to the memory alloca-
tion functions may fail.

Altering the Size of a Block


What if you allocate room for an array and later discover that you
need room for more elements? The library includes the realloc
function that can either enlarge or shrink the size of an allocated
block. The realloc function relocates the block in the physical
memory, if necessary, to satisfy the request for enlargement. It
also guarantees that the data up to the old size of the block will
remain intact.

Further Reading
Memory management is covered in most books on operating
systems. The books on XINU by Comer' and on MINIX by Ta-
nenbaum? describe memory management from the point of
view of an operating system. Each book includes samples of C
code that implement the memory management algorithms.
Knuth’s classic text? describes the basic algorithms used in de-
ciding how to assign a particular block of memory to satisfy a
request. For a more practical and relevant description of the C
memory allocation routines and their usage, consult Prata’s
book".
1. Douglas Comer, Operating System Design: The XINU Ap-
proach, Prentice-Hall, Inc., Englewood Cliffs, NJ, 1984, 486
pages.
2. Andrew S. Tanenbaum, Operating Systems Design and Im-
plementation, Prentice-Hall, Inc., Englewood Cliffs, NJ.
1987, 719 pages.
3. Donald E. Knuth, The Art of Computer Programming, Vol-
ume 1: Fundamental Algorithms, Addison-Wesley, Read-
ing, MA, 1968, 640 pages.
4. Stephen Prata, The Waite Group’s Advanced C Primer++.
Howard W. Sams & Company, Indianapolis, IN, 1986, 502
pages.
132 ANSI C Process Control and Memory Management

ss

> calloc

Purpose
Use calloc to allocate memory for an array af num_elems ele-
ments, each of size elem__size bytes. All bytes of the allocated
array will be initialized to zero.

Syntax
#include <stdlib.h>
void *calloc(size_t num_elems, size_t elem_size);
size_t num_elems; Number of elements

size_t elem_size; Size of each element in bytes

Example Call
p_int = (int *) calloc(100, sizeofCint));

Returns

The return value from calloc is a pointer to void, representing


the address of the allocated memory. If the memory allocation is
unsuccessful because of insufficient space or bad values of the
arguments, a NULL is returned.

See Also
free, malloc, realloc

Example
See Example 10-1 at the end of the chapter. Line 9 in that example
uses calloc to allocate a buffer.

> free

Purpose
Use the free function to deallocate (return to the pool of free
memory) a block of memory allocated earlier by malloc, calloc,
or realloc. The address of the block is specified by the argument
mem _dddress, which is a pointer to the starting byte of the
block. A NULL pointer argument is ignored byfree.

Syntax
#include <stdlib.h>
void free(void *mem_address);
void *mem_address; Pointer to block of memory to be released

free
10—Memory Allocation 133

Example Call
free(buffer);

See Also

calloc, malloc, realloc

Example
Lines 38 and 39 in Example 10-1 use free to deallocate memory.

ISA Al Stil TE Me AR abl


malloc <4

Purpose

Use the malloc function to allocate the number of bytes re-


quested in the argument num_ bytes.

Syntax
#include <stdlib.h>
void *malloc(size_t num_bytes);
size_t num_bytes; Number of bytes needed

Example Call
buffer = (char *)malloc(100*sizeof(char));

Returns

The malloc function returns a pointer that is the starting address


of the memory allocated. If the memory allocation is unsuccess-
ful, because ofinsufficient space or bad values of the arguments,
a NULL is returned.

See Also
free, calloc, realloc

Example
Line 20 in Example 10-1 uses malloc to allocate room for a buffer.

realloc <4

Purpose
Use the realloc function to change the size of an allocated block
of memory to a new Size given in the argument newsize. The ad-
dress of the block is specified by the pointer mem _address.

realloc
134 ANSI C Process Control and Memory Management

This pointer must be either NULL or a value returned by an ear-


lier call to malloc, calloc, or realloc. If the argument mem _ad-
dress is a NULL, then realloc behaves like malloc and allocates a
new block of memory of size newsize. The memory block of
altered size may not be located at the same address any more,
but, up to the old size, the contents of the block are guaranteed
to be unchanged. i

Syntax
#include <stdlib.h>
void *realloc(void *mem_address, size_t newsize);
void *mem_address; Pointer to the block of memory whose size is to be
altered

size_t newsize; New size of the block in bytes

Example Call
new_buffer = realloc(old_buffer, old_size+100);

Returns

The realloc function returns the address of the block of mem-


ory. If realloc fails, the pointer will be unchanged and it will re-
turn a NULL.

See Also

€alloc, free, malloc

Example
Line 30 in Example 10-1 uses realloc to enlarge the size of an allo-
cated buffer.
Example 10-1 Illustrate the use of the memory allocation
routines by allocating two buffers, one with
calloc and the other by malloc. Enlarge one of
the buffers by calling realloc. Free the buffers
using free.
#include <stdio.h>
#include <stdlib.h>

main®
{
char *buffer1, *buffere;

— se
of
ef
#8
es /* Allocate room for string and check for NULL */
CONOouUrWN
oe

oy if ((buffer1 = (char *) calloc(100, 80)) == NULL)


10: {
Ais printf("calloc Failed.\n");
er exit(1);
Ue hs
14: printf("Buffer allocated by calloc."

realloc
10—Memory Allocation 135

"Enter string to store: '');


gets (buffer1);
printf('"'\nYou entered: %s\n"',buffer1);

/* Now allocate another buffer using malloc */


if( (buffer2 = (char *)malloc(10)) == NULL )
{
printf('malloc Failed.\n");
exit(1);
}
printf("Buffer allocated by malloc."
"Enter another string to store: ");
gets (buffer2);
printf('"\nYou entered: %s\n"',buffer2);
/* Now enlarge size of buffer and redisplay string */
if( (buffer2 = (char *)realloc((void *)buffer2,
80)) == NULL )
{
printf (''Reallocation Failed.\n');
exit(1);
}
printf("'Buffer still contains: %s\n",buffer2);
/* Free the buffers */
free(buffer1);
free(buffer2);
' ry,
Lo Hom iN,
4

v4

iy i
IV
ANSI C Data Processing

RY)
17
Data Conversion

Introduction
Using computers for information management frequently re-
quires crunching numbers. These numbers are represented in
several forms internally, depending on the type of C variable in
which the value is held. The ANSI C data conversion routines,
declared in the header file stdlib.h, allow conversion back and
forth between the internal form of a C variable and the character
string representations to be read.

Internal Representations of Data


The data conversion routines rely on several internal representa-
tions of a number—as a series of bytes in memory containing a
binary representation as well as a character string (with the val-
ues expressed in decimal, hexadecimal, and other numbering
systems).
All computers store numbers in binary representation in
their memory locations. This is true of all numbers, floating
point or integer. As illustrated in Figure 11-1, the character string
representation of a value depends on the radix, or the base of the
number system in which the value is being expressed. For ex-
ample, decimal 100 is written as 64 in hexadecimal, 144 in octal,
and 1100100 in binary. The figure also shows the internal binary
representations of the value 100 when stored as a short integer
and as an Institute of Electronics and Electrical Engineers (IEEE)
format double-precision floating-point number. The character
string, though, is the form you deal with to obtain numbers from
the user or to format and print numbers calculated by the pro-
gram.

139
140 ANSI C Data Processing

The pattern of bits that represents a value (such as decimal


100) in memory is determined by the type of C variable used to
hold that value. If the variable type is it, which has a size of 2
bytes on the IBM PC, the value will be stored in binary in these
two bytes (Figure 11-1). On the other hand, if you wanted to store
100 in a variable of type double, 8 bytes would be used to hold
the value and the bit pattern would depend on the IEEE format
for double-precision numbers. Most math coprocessors (the
“math whiz” companions of microprocessors) store floating-
point numbers in the IEEE format.

Character String

Radix System String


10 Decimal 100
2 Binary 1100100
8 Octal 144
16 Hexadecimal 64

Binary (when stored as an


int and a double variable)
increasing
4 address
0000 0000
100 as
integer
0110 0100

__| Exponent with


Sign bit | bias of 1,023

oV/100 00007,
7.01014 1001_|
IEEE format
100.0 as
double Mantissa

Address of
double
ae bie —. variable

100 (decimal = 1.1001 x 2


Pe AA
Implicit (not stored) Mantissa Exponent

Figure 11-1. Decimal 100 as a Character String and in


Internal Forms ;
11—Data Conversion 141

Notes on Using the Data Conversion Routines


The ANSI C data conversion routines help us create a bridge be-
tween the two styles of representing numbers: the human read-
able text string and the machine readable binary form. Table 11-1
lists the routines at our disposal.

Table 11-1. Data Conversion Routines

Routine Description

atof Converts a string to a double-precision floating-point value


atoi Converts a string to an integer
atol Converts a string to a long integer
strtod Converts a string to a double-precision floating- a value
strtol Converts a string to a long integer
strtoul Converts a string to an unsigned long integer

These routines are ideal for converting command-line argu-


ments from their string representation to the internal format. For
example, you may want the user to invoke a small calculator util-
ity in the form
cate 4.5 + 3.45

where calc is the name of the program that accepts command-


line arguments of the form <value/) (operator) <value2) and
prints the answer to the operation. In the sample invocation, 7.
95 is the answer. When implementing the program calc, you can
make use of the function atof to convert the second and the
fourth command-line arguments (the first argument is always
the name of the program) to double variables. The code imple-
menting the addition operator might be:

value1 = atof(argv[1]);
value2 = atof(argv[3]);
switch(argv([2][0])
xf

case ‘+’: result = value1 + valued;


break;

}
printf("%f", result);

In this example, a decimal calculator is assumed. If you want a


hexadecimal calculator (so that all input and output is in hexa-
decimal), you can use strtou/ to convert the input arguments to
unsigned long integers.
142 ANSI C Data Processing

Data Conversion Routines by Task


The six data conversion routines perform a single task—con-
verting a string to a specific type of C variable. Table 11-2 shows
the routines grouped according to variable.

Table 11-2. Data Conversion Routines by Conversion Variable

Task Routines

Convert character string to floating-point value atof, strtod


Convert character string to integer atol
Convert character string to long integer atol, strtol
Convert character string to unsigned long integer strtoul

Other Data Conversion Resources


A few other routines in the C library also provide data conver-
sion facilities. You can use the sprintf and the sscanf functions in
the I/O category to convert internal values to strings and strings
back to internal representations, respectively. The sscanf rou-
tine, however, lacks the ability to convert a string to an integer
using an arbitrary radix—only decimal, octal, and hexadecimal
formats are supported.

> atof

Purpose
Use the atof function to convert the argument string into a
double value. A call to atof is equivalent to the call strtod(string,
(char * *)NULL).

Syntax
#include <stdlib.h>
double atof(const char *string);
const char *string; Stringto be converted

Example Call
dbl_value = atof(input_string);

Returns

The atof function returns a double-precision value after conver-


sion,

See Also

atoi, atol, strtod

atof
11—Data Conversion 143

atoi <<

Purpose
Use the ato# function to convert the argument string into an int
value. A call to atoz is equivalent to the call (int)strtol(string.
(char **)NULL, 10).

Syntax
#include <stdlib.h>
int atoi(const char *string);
const char *string; String to be converted

Example Call
int_value = atoi(input_string);

Returns
The atoi function returns the integer value as an int variable.

See Also

atof, atol, strtol, strtoul

atol <4

Purpose
Use the ato/ function to convert the argument string into a long
integer value. A call to @tol is equivalent to the call strtol(string.
(char **)NULL, 10).

Syntax
#include <stdlib.h>
int atol(const char *string);
const char *string; String to be converted

Example Call
long_value = atol(input_string);

Returns

The atol function returns the converted value as a /ong variable.

See Also

atof, atoi, strtol, strtoul

atol
144 ANSI C Data Processing

> strtod

Purpose
Use the strtod function to convert string to a double-precision
value. The string is expected to be of the form
[whitespace][sign][digits. digits]
[exponent _letter][sign][digits]
where whitespace refers to (optional) blanks and tab characters,
sign isa + ora-, and the digits are decimal digits. The exponent__
letter can be any one of d, D, e, or E(no matter which exponent
letter is used, the exponent always denotes a power of 10). If
there is a decimal point without any preceding digit, at least one
digit must follow it. The strtod function begins the conversion
process with the first character of string and continues until it
finds a character that does not fit the above form. Then it sets
endptr to point to the leftover string, provided endpir is not
equal to NULL.

Syntax
#include <stdlib.h>
double strtod(const char *string, char **endptr);
const char *string; Pointer to character array from which double-
precision value will be extracted
.

char **endptr; On return, points to character in string where


conversion stopped

Example Call
dbl_value = strtod(input_string, &endptr);

Returns

The strtod function returns the double-precision value as long as


it is not too large. If it is too large, an overflow occurs and the
return value is the constant HUGE_ VAL, with the same sign as
the number represented in string, and the global variable errno
is set to the constant ERANGE,

See Also

atof, strtol, strtoul

strtod
11—Data Conversion 145

strtol <

Purpose
Use the strtol function to convert string to a long integer value.
The string is expected to be of the form
[whitespace][sign][O][x or X][digits]
where whitespace refers to (optional) blanks and tab characters,
sign is a + Or a-—, and the digits are decimal digits. The string is
expected to contain a representation of the long integer using
the argument radix as the base of the number system. However,
if radix is given as zero, strtol uses the first character in string to
determine the radix of the value. Here are the rules:

Other radixes may be specified via the argument radix. The let-
ters a through z (or A through Z) are assigned values 10 through
35. For a specified radix, strto/l expects only those letters whose
assigned values are less than the radix.
The sirtol function begins the conversion process with the
first character of string and continues until it finds a character
that meets the above requirements. Before returning, strfol sets
endptr to point to that character, provided it is nota null pointer.

Syntax
#include <stdlib.h>
long strtol(const char *string, char **endptr, int radix);
const char *string; Pointer to character array from which the long
integer value will be extracted

char **endptr; On return, points to character in string where


conversion stopped

int radix; Radix in which the value is expressed in the string (radix
must be between 2 and 36)

Example Call
value = strtol(input, &endptr, radix);

strtol
146 ANSI! C Data Processing

Returns

The strto/ function returns the long integer value except when it
would cause an overflow. In case of overflow, strtol sets errno to
ERANGE and returns either LONG__MIN or LONG_ MAX, de-
pending on whether the value was negative or positive, respec-
tively.

See Also
atol, strtoul

> strtoul

Purpose
Use strtoul to convert a character string to an unsigned long inte-
ger.

Syntax
#Hinclude <stdlib.h>
unsigned long strtoul(const char *xstring, char **endptr,
int radix);

const char *string; Pointer to character array from which the


y unsigned long value will be extracted

char *xendptr; On return, points to character in string where


conversion stopped

int radix; Radix in which the value is expressed in the string (radix
must be between 2 and 36)

Example Call
value = strtoul(input_string, &stop_at, radix);

Returns

The strtoul function returns the unsigned long integer value ex-
cept when it would cause an overflow. In case of overflow, strtoul
sets errno to ERANGE and returns the value ULONG_
MAX.

See Also
atol, strtol

Example
Example 11-1 shows a hexadecimal calculator program that uses
strtoul to read hexadecimal values from the command-line argu-
ments (lines 14 and 15).

strtoul
11—Data Conversion 147

Example 11-1 This example shows a hexadecimal calculator


designed to be invoked with the command-
line calc operand__1 operation operand _2
where calc is the name of the program, opera-
tion is one of +, -, *, or /, and operand
_1
and operand _2 are the hexadecimal oper-
ands. The program uses strtoul to read the
operands.
1:#include <stdio.h>
2:#include <stdlib.h>
Si
4:static char command[80] = '' "';
55
6:main(int argc, char **argv)
at
8: unsigned long opi, op2;
9: if(arge < 4)
10: {
alae printf("Usage: %s <operand1> <operation> "'
V2 "<operand2>\n'"', argv[0]);
13° }
14: op1 = strtoul(argv[1], (char **)NULL, 16);
45% op2 = strtoul(argv[3], (char **)NULL, 16);
16:
aes switch (argv(2](0])
18: {
19: Casemrt ss
20: printf("%LX Chex)\n'", op1 + op2);
7 \3 break;
22: ale
23: printf ("'%LX Chex)\n'', op1 - op2);
24: break;
25: case '*':
26: printf ("%LX Chex)\n'', op1 * op2);
aoe break;
28: case '/':
29: if(op2 == OL)
305 ae
Si printf('"'Can't divide by zero!\n');
32: }
55) else
34: printf("%LX Chex)\n'', opt / op2);
555 break;
36: }
hh, ‘ae +e ween) £i
‘Venf
iy St ae s tea
. =
= *

a
y

—— “

:
es + 3 ih j ‘apne toni no
> a
A u = EM og @

~.
i ma co)! Ne‘a; sere <
= pe Chee 3) a
, : ’ , — “ OMS
has alt xeds ae Triaiay- i 7
ee RAT ~~ SeRey
; : ae. oe
*% " eS 7

oer pare oe 1 es &


Math Functions

Introduction
In addition to the support for basic floating-point operations in
the language, the ANSI C library includes a set of math functions
to perform such common mathematical operations as the sine
and the cosine.

Floating-Point Operations
Floating-point variables hold floating-point numbers, which are
numbers with fractional parts. When you write such numbers,
there is usually a decimal point somewhere, for example, 1.2345
x 10°. This notation of writing floating-point numbers is known
as scientific or engineering notation. In fact, any floating-point
number can be represented in this form: a “mantissa” (the num-
ber’s significant digits) multiplied by 10 raised to the power of an
integer “exponent.” The mantissa and exponent form is how
floating-point numbers are represented in ANSI C, except that
instead of the exponent representing a power of 10, it represents
a power of 2, since base 2 is a computer’s natural format.

Precision: Single or Double


The number of bytes used to represent a floating-point number
depends on the precision of the variable. The C variable type
float is used to declare single-precision floating-point variables.
The type double denotes double-precision values. As shown in
Figure 12-1, the single-precision float variables require 4 bytes of
storage while double variables use 8 bytes. The representation of
the mantissa and the exponent in the variables is in accordance
with the IEEE floating-point standards. This representation is
used in most C compilers.

149
150 ANSI C Data Processing

Sign bit Biased eee Implicit 1 53- y mantissa (last bit implicit)

63 52 51 F 0
double precision or “long real”
Biased 24-bit mantissa
Sign bit exponent Implicit 1 (last bit not stored)
4

float
4 bytes
31 23 22 0
single precision or “short real”

Figure 12-1. IEEE Format for Binary Representation of


Floating-Point Numbers

IEEE Format for Floating-Point Numbers


The IEEE format expresses a floating-point number in the binary
form known as “normalized.” Normalization involves adjusting
the exponent so that the “binary” point (the binary analog of
the “decimal” point) in the mantissa always lies to the right of
the most significant nonzero digit. In binary representation, this
means that the most significant digit of the mantissa is always a 1.
This property of the normalized representation is exploited by
the IEEE format when storing the mantissa.
Consider an example of generating the normalized form of
a floating-point number. Suppose you want to represent the dec-
imal number 5.375. Since this can be written as:
4+1+14+ 6
the binary form will be
101.011
Then the normalized form is obtained by adjusting the exponent
until the decimal point is to the right of the 1 in the most signifi-
cant position. In this case, the result is

1.01011 x 27
The IEEE format for floating-point storage uses a sign bit, a man-
tissa, and an exponent representing the power of two. The sign
bit denotes the sign of the number: a 0 represents a positive
number and a 1 denotes a negative value. The mantissa is repre-
sented in binary. Constraining the floating-point number to be in
normalized form results in a mantissa whose most significant bi-
nary digit is always 1. The IEEE format takes advantage of this by
12—Math Functions 151

not storing this bit at all. The exponent is an integer stored in


unsigned binary format after adding a positive integer bias to en-
sure that the stored exponent is always positive. The value of the
bias depends upon the precision of the floating-point represen-
tation.
The single-precision float variable uses 4 bytes (32 bits)
comprising 1 sign bit, 7 bits for the exponent, and a 24-bit man-
tissa, which can be stored in the rest of the 23 bits because the
most significant bit is always 1 (Figure 12-1). The exponent is
stored with a bias of 127. Thus, the smallest positive value you
can store in a float variable is 2~'*°, which is approximately 1.175
x 10~-°8. The largest positive value is 2'’°, which is about 3.4 x
10**. About seven significant decimal digits can be handled in a
float variable.
The double-precision double variable uses 8 bytes providing
64 bits of storage. As shown in Figure 12-1, the first bit is used for
the sign bit and the next 11 bits hold the exponent, which has a
bias of 1,023 added to it. The rest of the 52 bits contain the 53-bit
mantissa. This representation allows about 15 significant decimal
digits and the smallest positive value is 2~'°*?, which is approxi-
mately 2.23 x 10~°°°. The largest positive value that can be held in
a double variable is 2!°*4, which is approximately 1.8 x 10°,
The IEEE format also specifies certain bit patterns that rep-
resent special conditions such as infinite values or NANs (for
“not a number’), but you need not get into the details if you just
want to use the C library math functions.

Error Conditions in Math Functions


Two types of errors can occur in the math functions: domain and
range. A “domain” error occurs when the arguments to a function
are outside the domain of values for which that function is de-
fined. When this occurs, the global error indicator errno (defined
in errno.h) is set to the constant EDOM. A “range” error occurs
when the result of a math function cannot be represented as a
double value. If the result is large enough to cause an overflow,
the function returns the constant HUGE _ VAL (defined in float. h)
and sets errno: to ERANGE. If the value is too small (causing an
underflow), the function returns zero. (In this case, an implemen-
tation may optionally set errno to ERANGE.)

Using the Math Functions


Table 12-1 catalogs the math functions available in the ANSI C
library. These functions are declared in the header files math.b
and stdlib.h.
152 ANSI C Data Processing

Table 12-1. Math Functions

Routine Description

abs Returns the absolute value of an integer argument


acos Computes the arc cosine of a value between —1 and 1 and returns an
angle between 0 and = radian
asin Computes the arc sine of a value between —1.and 1 and returns an
angle between - 72/2 and 2/2 radians
atan Computes the arc tangent of a value and returns an angle between
-— 7/2 and 2/2 radians
atan2 Computes the arc tangent of one argument divided by another and
returns an angle between - a and z radians
ceil Finds the smallest integer larger than or equal to the function’s floating-
point argument
cos Evaluates the cosine of an angle in radians
cosh Evaluates the hyperbolic cosine of its argument
div Divides one integer by another and returns an integer quotient and an
integer remainder
exp Computes the exponential of a floating-point argument
fabs Returns the absolute value of a floating-point argument
floor Finds the largest integer smaller than or equal to the function’s floating-
point argument
fmod Computes the floating-point remainder after dividing one floating-point
value by another so that the quotient is the largest possible integer for
that division
frexp Breaks down a floating-point value into a mantissa between 0.5 and 1
and an integer exponent so that the value is equal to the mantissa times
2 raised to the power of the exponent
labs Returns the absolute value of a long integer argument
Idexp Computes a floating-point value equal to a mantissa times 2 raised to the
power of an integer exponent
ldiv Divides one long integer by another and returns a long integer quotient
and a long integer remainder
log Evaluates the natural logarithm of its floating-point argument
log10 Evaluates the logarithm to the base 10 of its floating-point argument
modf Breaks down a floating-point value into its integer part and its
fractional part
pow Computes the value of one argument raised to the power of a
second one
rand Returns a random integer between 0 and RAND_MAX
(defined in stdlib.h)
sin Evaluates the sine of an angle in radians
sinh Evaluates the hyperbolic sine of its argument
sqrt Computes the square root of a positive floating-point number
srand Sets the starting point for the sequence of random numbers generated
by rand
tan Evaluates the tangent of an angle in radians
tanh Evaluates the hyperbolic tangent of its argument
12—Math Functions 153

The Math Functions by Task


Categorizing the math functions in terms of the tasks they per-
form (Table 12-2) shows that several important kinds of compu-
tations are supported in the library.

Basic Math Functions


The trigonometric functions cos, sin, tan, acos, asin, atan, and
atan2 evaluate the cosine, sine, and tangent and the inverses of
any angle in radian. You will find these routines useful for such
tasks as transforming from rectangular to polar coordinates,
which often occurs in graphics programs. Other commonly
needed functions include sqrt to compute square roots. The log
and /og/0 return the logarithm, natural and to the base 10, re-
spectively, of an argument. Exponentials (for example, e*) can be
computed by exp. The abs and fabs functions return the abso-
lute value of an argument. The ceil and floor routines find the
nearest integer larger or smaller than a given floating-point num-
ber.

Integer Arithmetic
Four routines use integer arguments to handle arithmetic. The
abs and labs routines return the absolute value of an integer and
a long integer, respectively. The div function divides one integer
by another and returns the integer quotient and an integer re-
mainder. The /div function operates similarly, but with long inte-
ger arguments.

Generating Random Numbers


If you need to generate random numbers for a random screen
pattern, a game, or a Statistical analysis problem, for instance,
the ANSI C library includes a routine named rand that can gener-
ate a random positive integer in the range from 0 to RAND_
MAX, which is a constant defined in stdlib.h. Using it is like
throwing a die with RAND_MAX+1 faces. The numbers are
generated by a fixed algorithm which, given the starting number,
always generates the same sequence of numbers. So instead of a
truly random sequence, rand generates a pseudorandom one. If
the algorithm used to generate the numbers is good, the se-
quence will have good properties, for instance not repeating it-
self too soon or enabling any of the numbers between 0 and
RAND_ MAX to appear with equal probability. (A poor algo-
rithm will be analogous to a loaded die.) A function named
srand sets the starting point of the random sequence.
Sometimes you need to pick a random sequence of random
numbers. For example, you wouldn’t want a card game to deal
the same hands each time. ANSI C does not provide a routine to
generate a random seed, but you can use something like the
value returned by the time function as the argument to srand to
set a new random seed for rand.
154 ANSI C Data Processing

Table 12-2. Math Functions by Task


Task Routines

Evaluate trigonometric functions acos, asin, atan, atan2, cos, sin, tan
Evaluate powers and logarithms exp, frexp, Idexp, log, log10, pow
Compute square root sqrt
Compute magnitudes and absolute values abs, fabs
Find integer limits (lower and upper) for ceil, floor
floating-point numbers
Evaluate hyperbolic functions cosh, sinh, tanh
Break down floating-point number into modf
integer and fraction
Find floating-point remainder fmod
Perform integer arithmetic abs, div, labs, Idiv
Generate random numbers rand, srand

Further Reading
If you need to use the trigonometric functions often, you will
find the handbook by Abramowitz and Stegun! a good reference
for these and many other mathematical functions. The IEEE
standard for binary floating-point arithmetic is described in a
reference booklet’ that can be obtained from Global Engineer-
“ing Documents, 2805 McGaw Ave., Irvine, CA 92174.
1. Milton Abramowitz and Irene A. Stegun, Editors, Handbook
of Mathematical Functions with Formulas, Graphs and
Mathematical Tables, Dover Publications, New York, NY,
1972, 1,046 pages.
2. IEEE Standard for Binary Floating-Point Arithmetic
(ANSI/IEEE Std 754-1985).

I SN Ry

> abs

Purpose
Use the abs function to get the absolute value of the integer argu-
ment 7.

Syntax
#include <stdlib.h>
int abs(int n);
int n; Integer whose absolute value is returned

abs
12—Math Functions 155

Example Call
x = abs(-5); /* x will be 5 now */

Returns

The integer returned by abs is the absolute value of n.

See Also
fabs, labs

Se
eae
acos <4

Purpose
Use the acos function to compute the arc cosine of an argument
x whose value lies in the range —1 to 1. The result is an angle with
value between 0 and = radians.

Syntax
#include <math.h>
double acos(double x);
double x; Argument whose arc cosine is to be computed

Example Call
angle = acos(0.5); /* angle is "pi''/3 */

Returns

When the value of the argument x is in the valid range of —1 to 1,


acos returns the arc cosine. Otherwise, a domain error occurs.

See Also
cos

asin <4

Purpose
Use the asin function to compute the arc sine of the argument x
provided its value lies in the range —1 to 1. The result is an angle
with a value between —7/2 and 7/2 radians.

Syntax
#include <math.h>
double asin(double x);
double x; Argument whose arc sine is to be computed

asin
156 ANSI C Data Processing

Example Call
angle = asin(0.707) /* angle is roughly "pi''/4 */

Returns

For a valid argument x with values between —1 and 1, asin re-


turns an angle whose sine is equal to x. If the argument’s value
lies outside the acceptable range, however, a domain error Oc-
curs.

See Also ~-

sin

> atan

Purpose
Use the atan function to compute the arc tangent of the argu-
ment x. The result is an angle with a value between —7/2 and /2
radians.

Syntax
#include <math.h>
double atan(double x);
“double x; Argument whose arc tangent is to be computed

Example Call
angle = atan(1.0) /* angle is "pi''/4 */

Returns

The atan function returns the angle in the range —7/2 and 2/2
whose tangent is equal to x.

See Also

atan2, tan

> atan2

Purpose
Use the atan2 function to compute the arc tangent of the ratio of
the arguments y/x. The result will be an angle with value be-
tween —7 and @ radians. In contrast to atan which takes a single

atan2
12—Math Functions 157

argument, atan2 can use the sign of the two arguments to deter-
mine the quadrant (a quadrant is a 90° sector in Cartesian coor-
dinates) in which the angle should lie.

Syntax
#include <math.h>
double atan2(double y, double x);
double x, y; Arc tangent of y/x will be computed

Example Call
angle = atan2(y, x);

Returns

Provided both arguments x and y are nonzero, atan2 returns an


angle whose tangent is equal to x. If both arguments are zero,
though, a domain error may occur.

See Also

atan, tan

ceil <4

Purpose
Use the ced/ function to find the ceiling of a double argument x.
The “ceiling” is the smallest integral value that is equal to or just
exceeds x. This can be used in rounding a double value up to the
next integer.

Syntax
#include <math.h>
double ceil(double x);
double x; Variable whose ceiling is to be returned

Example Call
x_ceiling = ceil(4.1); /* x_ceiling is 5.0 */

Returns

The return value is the ceiling of xexpressed as a double.

See Also

floor

ceil
158 ANSI C Data Processing

> cos

Purpose
Use the cos function to compute the cosine of double argument
x

Syntax
#include <math.h>
double cos(double x);
double x; Angle in radians whose cosine is to be computed

Example Call
cos_angle = cos(ang_radian);

Returns

The cos function returns the cosine of x. If the value of x is large


in magnitude, the result may be quite imprecise.

See Also

acos, sin

Example
‘See Example 12-1 at the end of the chapter. Line 14 in that ex-
ample computes the cosine of an angle.

> cosh

Purpose
Use cosh to compute the hyperbolic cosine of x.

Syntax
#include <math.h>
double cosh(double x);
double x; Variable whose hyperbolic cosine is to be computed

Example Call
result = cosh(x);

Returns

Normally, cosh returns the hyperbolic cosine of x. If the value of


the result is too large (a double variable can be as large as 103°), a
range error occurs.

cosh
12—Math Functions 159

See Also
sinh

BS LE a cc ci
div <

Purpose
Use the div function to divide the first integer (numer) by the
second one (denom) and get the resulting quotient and remain-
der in a structure of type div__t. The structure of type div_t is
defined in stdlib.h as
typedef struct
x
int quot; /* The quotient */
int rem; /* The remainder */
} div_t;

Syntax
#include <stdlib.h>
div_t div(int numer, int denom);
int numer; Numerator
int denom; Denominator

Example Call
result = div(32, 5);
/* result.quot = 6 and result.rem = 2 */

Returns

The div function returns a structure of type div__t containing


the quotient and remainder of the division.

See Also
ldiv

exp <4
Purpose
Use the exp function to compute the exponential of the double
variable x. The exponential of a variable x is e* where e is the
base of natural logarithm (e = 2. 7182818).

Syntax
#include <math.h>

exp
160 ANSI C Data Processing

double exp(double x);


double x; Variable whose exponential ts to be computed

Example Call
y = exp(x);

Returns .

Normally, exp returns the exponential of x. In case of overflow, a


range error Occurs.

See Also
log

(a ae

> fabs

Purpose
Use the fabs function to obtain the absolute value of its argu-
ment x.

Syntax
#include <math.h>
double fabs(double x);
*

double x; Variable whose absolute value is to be returned

Example Call
y = fabs(-5.15); /* y will be 5.15 */

Returns

The return value is of type double with a positive value that is


the absolute value of x.

See Also

abs

> floor

Purpose
Use the floor function to get the floor of a double argument x.
The “floor” is the largest integral value that is less than or equal
to x. This can be used in rounding a double down to the next
lower integer.

floor
12—Math Functions 161

Syntax
#include <math.h>
double floor(double x);
double x; Variable whose floor is to be returned

Example Call
x = floor(4.15); /* x will be 4.0 */

Returns

The return value is the floor of x expressed as a double.

See Also

ceil

fmod <4

Purpose
Use the fmod function to compute the floating-point remainder
after dividing the floating-point number x by y and ensuring that
the quotient is the largest possible integral value. If this quotient
is n, then fmod returns the value r computed from the expres-
sionr=x-—n * y. The entire operation is equivalent to
double n, r;

ase'=
=) floor(x/y);
b= "x = ney

Syntax
#include <math.h>
double fmod(double x, double y);
double x, y; The remainder after the division xly is returned

Example Call
rem = fmod(24.95, 5.5); /* rem will be 2.95 */

Returns

When y is zero, fmod returns a zero. Otherwise, it returns the


remainder.

See Also

floor

fmod
162 ANSI C Data Processing

ne

> frexp

Purpose
Use the frexp function to break down the floating-point number
x into a mantissa m whose absolute value liés between 0.5 and
1.0, and an integer exponent 7, so that x = m x 2”. The integer
exponent 7 is stored by frexp in the location given in the argu-
ment expptr.-If x is 0, the exponent will also be 0.

Syntax
#include <math.h>
double frexp(double x, int *expptr);
double x; Floating-point argument to be decomposed

int *expptr; Pointer to an integer where the exponent is returned

Example Call
mantissa = frexp(5.1, &exponent);
/* mantissa will be 0.6375, exponent = 3 */

Returns

Normally frexp returns the mantissa m. When x is zero, frexp


returns a zero as the mantissa.

See Also

ldexp, modf

> labs

Purpose
Use /abs to get the absolute value of the long integer 7.

Syntax
Hinclude <stdlib.h>
long Labs(long n);
long n; Long integer whose absolute value is returned

Example Call
lresult = lLabs(-65540L); /* result will be 65540 */

Returns

The long integer returned by /abs is the absolute value of n.

labs
12—Math Functions 163

See Also
abs, fabs

a SD

Idexp <4

Purpose
Use the /dexp function to compute and obtain the floating-point
number equal to x x 2°,

Syntax
#include <math.h>
double ldexp(double x, int exp);
double x; Floating-point value of the mantissa
int exp; Integer exponent

Example Call
value = ldexp(0.6375, 3); /* value will be 5.1 */

Returns
Normally /dexp returns the value described above. When the re-
sult is too large, a range error may occur.

See Also
frexp, modf

Idiv <

Purpose
Use the /div function to divide one long integer (”~umer) by an-
other (denom) and get the resulting quotient and remainder in a
structure of type /div__t. The structure type /div_t is defined in
Sstdlib.h as
typedef struct
{
long quot; /* The quotient */
long rem; /* The remainder */
+ ldiv_t;

Syntax
#include <stdlib.h>
ldiv_t ldiv(long numer, long denom);
long numer; Numerator

Long denom; Denominator

Idiv
164 ANSI C Data Processing

Example Call
Lresult = ldiv(65540L, 65536L);
/* lresult.quot = 1, lresult.rem = 4 */

Returns
The /div function returns a structure of type /div_t containing
the quotient and remainder of the division.

See Also
div

> log, log10

Purpose
Use Jog and log /0 to compute the natural logarithm and logarithm
to the base 10, respectively, of the positive double variable x.

Syntax
#include <math.h>
double log(double x);
double log10(double x);
double x; Variable whose logarithm is to be computed

Example Call
y = log(2); /* y = 0.693147 */
a = logi0(2); /* a = 0.30103 */

Returns

For positive x, Jog and /og/0 return the logarithm ofx. Ifx is neg-
ative, a domain error occurs. If x is zero, a range error Occurs.

See Also

exp, POW

> modf

Purpose
Use the modf function to separate the floating-point number x
into its fractional part and its integral part. The integer is re-

modf
12—Math Functions 165

turned as a floating-point value in the location given in the argu-


ment intptr.

Syntax
#include <math.h>
double modf (double x, double *intptr);
double x; Floating-point value to be decomposed

double *intptr; Integral part of x is returned here

Example Call
fraction = modf(24.95, &int_part); /* fraction is .95 */

Returns

The modf function returns the signed fractional part of x.

See Also

frexp, ldexp

pow <4

Purpose
The pow function computes the value of x raised to the power y.
The arguments x and y cannot both be zero. When x is negative,
y must be an integer.

Syntax
#include <math.h>
double pow(double x, double y);
double x, y; Computes x raised to the power y

Example Call
x = pow(2.0, 3.0); /* x will be 8.0 */

Returns

When both x andy are nonzero positive numbers, pow returns


the value x raised to the power y. If x is nonzero andy is 0, the
return value is 1.

See Also

log, logi0, sqrt

pow
166 ANSI C Data Processing

___._ eee
Se

> rand

Purpose
The rand function generates a pseudorandom integer with a
value between 0 and the constant RAND__MAX defined in
stdlib.b. The seed, or starting point, of the pseudorandom inte-
gers can be set by calling srand.

Syntax
#include <stdlib.h>
int rand(void);

Example Call
random_value = randQ);

Returns
The rand function returns the pseudorandom integer it gener-
ates.

See Also
srand

Example
Line 14 in Example 12-2 shows how rand can be used to get a
random number.

> sin

Purpose
Use the sin function to compute the sine of double argument x,
which represents an angle in radians.

Syntax
#include <math.h>
double sin(double x);
double x; Angle in radians whose sine is to be computed

Example Call
y = sin(x);

Returns

The sin function returns the sine of x. Depending on your im-


plementation, if the value ofx is of too great magnitude, the re-
sult may be quite imprecise.

sin
12—Math Functions 167

See Also

asin, cos

Example
Line 15 in Example 12-1 computes the sine of an angle.

sinh <4

Purpose
Use sinh to compute the hyperbolic sine of a double variable x.

Syntax
#include <math.h>
double sinh(double x);
double x; Variable whose hyperbolic sine is to be computed

Example Call
a = cosh(b);

Returns

Normally, sinh returns the hyperbolic sine of x. If the result is


too large (a double variable can be as large as approximately
10°), a range error Occurs.

See Also

cosh, tanh

sqrt <4

Purpose
Use sqrt to compute the square root of a non-negative double
variable x.

Syntax
#include <math.h>
double sqrt(double x);
double x; Variable whose square root is to be computed

Example Call
sqrt.2 = sqrt(2.0); /* sqrt_2 = 1.414 */

sqrt
168 ANSI C Data Processing

Returns
The sqrt function returns the square root of x. If x is negative, a
domain error occurs.

See Also
pow

> srand

Purpose
Use the srand function to set the seed, or starting point, of the
random number generation algorithm used by the function
rand. If seed is 1, the random number generator is initialized to
its default starting point. This generates the sequence that is pro-
duced when rand is called without a prior call to srand. Any
other value of seed sets a random starting point for the pseudo-
random sequence that is generated by rand.

Syntax
#include <stdlib.h>
void srand(unsigned seed);
unsigned seed; Starting point for random number generator

‘Example Call
srand(new_seed) ;

See Also

rand

Example
Line 11 in Example 12-2 shows how srand is used with the time
function to obtain a random starting point for a pseudorandom
sequence of numbers.

> tan

Purpose
Use the tan function to compute the tangent of an angle x whose
value is expressed in radians.

Syntax
#include <math.h>

tan
12—Math Functions 169

double tan(double x);


double x; Angle in radians whose tangent is to be computed

Example Call
y = tan(x);

Returns

The tan function returns the tangent of x. Depending on your


implementation, if the value of x is of too great magnitude, the
result may be quite imprecise.

See Also

atan, atan2, cos, sin

Example
Line 16 in Example 12-1 computes the tangent of an angle.

tanh <

Purpose
Use tanh to compute the hyperbolic tangent of a double variable
NX

Syntax
#include <math.h>
double tanh(double x);
double x; Variable whose hyperbolic tangent is to be computed

Example Call
a = tanh(b);

Returns

The tanh function returns the hyperbolic tangent of x.

See Also
cosh, sinh

Example 12-1 This program prints a table showing the co-


sines, sines, and the tangents of the angles be-
tween 0 and 180° in steps of 10°.
4:/* Print a table of cosines, sines, and tangents */
2:#include <stdio.h>
3:#include <math.h>
4:#include <errno.h> /* errno is defined here */
S:#define R_TO_D 57.29578 /* radians to degrees */

tanh
170 ANSI C Data Processing

6:main()
it
8: double angle, radians, cresult, sresult, tresult;
9:
10: printf (''Angle\t\tCosine\t\tSine\t\tTan\n");
AT: for(angle = 0.0; angle <= 180.0; angle += 10.0)
12: {
13% radians = angle / R_TO_D;
14: cresult = cos(radians);
15: sresult = sin(radians);
16: tresult = tan(radians);
100s if(errno != ERANGE)
18: {
19: printf("%f deg. \tzt\t%Zt\t%f\n",
20: angle, cresult, sresult, tresult);
21: }
22: }
Osa

Example 12-2 This example uses rand and srand to gener-


ate a random sequence of the numbers be-
tween 1 and 20. This means that the sequence
must contain only the numbers 1 through 20
in a random order with no number appearing
more than once. You can use such a random
sequence to assign tasks to workers in a
group.
1s
“Os/* Generate random sequence of random numbers */
3:#include <stdio.h>
4:#include <stdlib.h>
5:#include <time.h> /* time() used for random seed */
6:#define MAXNUM 20 /* maximum number in sequence */
7:main()
8:¢
9: int seql20], count=0, i, randnum;
10:/* Initialize the random number generator */
173 srand((unsigned)time(NULL)) ;
25 while(count < 20)
1S {
14: randnum = (rand() % MAXNUM) + 1;
15:/* Is this number already present in seql] */
16: for(i=0; i<count; i++)
AER {
18: if(randnum == seqlil]) break;
19: }
20: if(@>=count) /* Not in seql] */
21: f
ees seqlcount] = randnum;
23: count++;
24: }
Zos
12—Math Functions 171

26:/* Print the random sequence */


208 printf ("Random sequence (1-%d) = \n'', MAXNUM);
28: for(i=0; i<count; i++) printf('"%d ", seqlil]);
29: printf("\n');
30:}
aes —

ied 2
> ae
ae
rene
ss ne tn.

é

ee
a

wee wi art:
_ stake een
sy . A, eo
a52 -_ ‘3a

= .

J31Q > : 7

oe te a
ee ae teed) on ma pe
d ae | $ Z we) a ee Shi .«“tr AAT
ana
iae. t=

a ee
“rt ri oej
‘?
{

" My
= , re jad sie “)-
Character Classification and
Conversion

Introduction
ANSI C specifies two character sets for programs: the “‘source”
character set in which programs are written, and the “execu-
tion” character set that a running program understands. The
header file ctype.b contains several functions that are useful for
classifying and converting the execution characters. The behav-
ior of these functions is affected by the LC_CTYPE category of
the current locale (see Chapter 8 for more on locales).

Using the Character Classification and


Conversion Functions
Table 13-1 shows a catalog of functions available for character
classification and conversion.

Table 13-1. Character Classification Functions

Function Description

isalnum Tests if a character is alphanumeric


isalpha Tests if a character is alphabetic
iscntrl Tests if a character belongs to the set of control characters
isdigit Tests if a character is a numerical digit
isgraph Tests if a character is printable (excluding the space character)
islower Tests if a character is lowercase
isprint Tests if a character is printable (including the space character)
ispunct Tests if a character belongs to the set of punctuation characters
isspace Tests if a character belongs to the set of whitespace characters
isupper Tests if a character is uppercase

173
174 ANSI C Data Processing

Table 13-1. (cont.)


Dennen

Function Description

iSxdigit Tests if a character is a hexadecimal digit


tolower Converts a character to lowercase only if that character is an
uppercase letter
toupper Converts a character to uppercase only if that Character is a
lowercase letter

Classifying and Converting


The character classification routines include routines that clas-
sify characters into categories and convert them from one case to
another. Table 13-2 shows the routines grouped according to
task.

Table 13-2. Character Classification Routines by Task


Task Functions

Classify a character isalnum, isalpha, iscntrl, isdigit, isgraph,


islower, isprint, ispunct, isspace, isupper,
isxdigit
Convert from uppercase to lowercase _ tolower
Convert from lowercase to uppercase — toupper
>

> isalnum

Purpose

Use the isa/num function to check if the character c is alphanu-


meric. This is the same as testing if ‘salpha or isdigit is true for c.

Syntax
#include <ctype.h>
int isalnum(int c);
inte. Character being tested

Example Call
ifCisalnum(c) != 0) printf("'%c is alphanumeric\n", c);

Returns

The tsalnum function returns a nonzero value if the c is indeed


an alphanumeric character. Otherwise, it returns a zero.

isalnum
13—Character Classification and Conversion 175

See Also
isalpha, isdigit

a at oa
es
Sie

isalpha <4

Purpose
Use isalpha to check if the character c is a letter. If the locale is
not C, the behavior is dependent upon the character set in use.

Syntax
#include <ctype.h>
int isalpha(int c);
int c; Character being tested

Example Call
ifCisalpha(c) != 0) printf ('%c is letter\n", c);

Returns
The tsalpha function returns a nonzero value if c is a letter. Oth-
erwise, it returns a zero.

See Also
islower, isupper

iscntrl, isdigit, isgraph, islower, isprint, <4


ispunct, isspace, isupper, isxdigit

Purpose
Use this group of functions to check for specific properties of
the character c, such as whether it is a control character, a digit,
lowercase, printable, and so on. Table 13-3 shows the test per-
formed by each function.

Table 13-3. Character Classification Tests

Function __ Tests for

iscntrl control character


isdigit decimal digit
isgraph printable character, excluding the space
islower lowercase letter
isprint printable character, including the space

iscntrl, isdigit, isgraph, islower, isprint,


ispunct, isspace, isupper, isxdigit
176 ANSI C Data Processing

Table 13-3. (cont.)

Function Tests for

ispunct punctuation character


isspace whitespace character (space; formfeed, \f; newline, \n; carriage
return, \r; horizontal tab, \t; and vertical tab, \v)
isupper uppercase letter :
isxdigit hexadecimal digit

Syntax
#include <ctype.h>
lint. 1scntrl (int c's
int isdigit(int c);
int isgraph(int c);
int islower(int c);
int isprint(int c);
int ispunct(int c);
int isspace(int c);
int isupper(int c);
int isxdigit(int c);
int ¢} Character to be tested

Example Call
ifCisprint(c) != 0) printf(''%c is printable\n", c);
if(isdigit(c) != 0) printf ("%ec is a digit\n", c);
ifCisentrl(c) != 0) printf("%d is a control char\n", c);

Returns
Each function returns a nonzero value if c satisfies the criterion
for that function. Otherwise it returns a zero.

See Also
isalnum, isalpha

> tolower

Purpose
Use the tolower function to convert the uppercase letter C to
lowercase.

Syntax
#include <ctype.h>
int tolower(int c);
Inte ce Character to be converted

tolower
13—Character Classification and Conversion 177

Example Call
c = tolower('Q'); /* c will become ‘q' */

Returns

The tolower function returns the lowercase letter corresponding


to c if there is one. Otherwise, the argument is returned un-
changed.

See Also

toupper

toupper <4

Purpose
Use the toupper function to convert the lowercase letter c to up-
percase.

Syntax
#include <ctype.h>
int toupper(int c);
int c; Character to be converted

Example Call
c = toupper('q'); /* c will become ‘Q' */

Returns

The toupper function returns the uppercase letter correspond-


ing to c if there is one. Otherwise, the argument is returned un-
changed.

Example
Example 13-1 reads a line and converts it to uppercase. It calls
toupper on line 12.
Example 13-1 This example reads a line and converts it to
uppercase.
1:/* Read a line and convert it to uppercase */
2:#include <stdio.h>
3:#include <ctype.h>
4:
5:main®
6:f
7: char input(81], *p_in;
8: puts("Enter a line:");
OE gets (input);

toupper
178 ANSI C Data Processing

10:/* Convert the Line to uppercase using ‘toupper' */


Habe for(p_in = input; *p_in != ‘\O'; p_int+)
Nes *p_in = toupper(*p_in);
13:/* Display the result */
14: printf("\n%s\n", input);
ois)
String and Buffer
Manipulation

Introduction
Manipulating text is a major part of many computer applications.
The manipulation might involve text editing, word processing, or
that part of your application that reads commands typed by the
user and interprets them. Typically, you read a single line of com-
mand into a C string and interpret it. Depending on the syntax of
your application’s command set, the interpretation will involve
chores such as extracting the commands and parameters from the
string, comparing the command against entries in a stored table,
or copying the parameters into separate strings for later use. Al-
though C has no built-in operators for handling strings, the ANSI
C standard specifies a set of string manipulation routines that pro-
vides all the capabilities needed to process strings.

Strings in C
C has no basic data type for strings. Instead, strings are treated as
arrays of characters, each occupying a byte. By convention, the
end of a string in C is marked by a byte containing a null charac-
ter (\0). Because of this, C strings are known as null-terminated
strings or ASCIIZ (ASCII characters with a zero marking the end)
strings.

Declaring Strings in C
Since strings are treated as an array of characters, they can be de-
clared in your programs by a statement such as
char str1([81], str2(J="A string";

Here, str1 will be a string with room for 81 characters, but since

179
180 ANSI C Data Processing

one position is always used by the terminating null, s¢r/ can


hold 80 characters at most. The second string, str2, does not
show a size, but the compiler can guess its size since it is being
initialized. In this case str2 will take 9 bytes ince the termi-
nating null (see Figure 14-1).

char str2 [ ]

strlen(str2) =8
char *p__-str2 i j NULL byte marks
the end

Figure 14-1. Strings in C

Another way of accessing a string is through a “pointer,”


which can hold the address of a variable (see Chapter 1). If you
wanted to access the string str2 using a pointer named p__str2,
the C code fragment
char str2C] = "A string";
char *p_str2;
p_str2 = str2;

would do the job. Once p__str2 is initialized, it can be used to


.access the string in the same manner as str2 is used (see Figure
14-1). Of course, the pointer requires some additional storage
space.
You can also declare and initialize a string at the same time
with
char *p_str = "A string";
in which the character pointer
p str is initialized to the address
of the “A string” constant.

Lexicographic Ordering
The string comparison routines compare and order strings as
they would have appeared in a dictionary. This ordering is
known as “‘lexicographic” ordering. The comparison is based
on the collating sequence of the characters in corresponding
bytes of the two strings. For the ASCII character set, the collating
sequence of the letters corresponds to their place in the lexicon.

Multibyte and Wide Character Strings


ANSI C uses the notion of two character sets that are relevant to a
C program: the source character set in which the program is
14—String and Buffer Manipulation 181

written and the execution character set that is understood by the


program when it runs. Both character sets may contain mul-
tibyte encoding of characters—meaning the code representing a
single character may take more than one byte to store. ANSI C
also provides for a data type wchar_t, which stands for “wide
character type.” The wchar_t data type is an implementation-
dependent, integer-valued data type whose range of values is
large enough to represent all members of the largest extended
character set supported by the compiler. For example, if the larg-
est character set has more than 256 but fewer than 32,767 char-
acters, a short type could be used as wchar_t to hold the wide
characters.

Using the String and Buffer Manipulation


Routines
The string and buffer manipulation routines (see Table 14-1 fora
catalog) provide a host of capabilities. If you group the capabili-
ties into major categories, you find that most routines are for
comparing two strings or buffers, copying one string or a buffer
into another, or searching for the occurrence of a character ina
string. (See Table 14-2 for a list by task.) Most of these routines
are defined in string.h, a few are from stdlib.h. This section will
describe the general usage of the string and buffer manipulation
routines.

Table 14-1. String and Buffer Manipulation Routines


Routine Description

mblen Returns the number of bytes that makes up a single multibyte


character.
mbtowc Converts a multibyte character to wchar_t type.
mbstowcs — Converts a sequence of multibyte characters into a sequence of codes
of wchar_ttype.
memchr Searches for a specific character in a given number of bytes of
the buffer.
memcmp Compares a specified number of bytes of two buffers.
memcpy Copies a specified number of bytes from one buffer to another (not for
overlapping source and destination).
memmove Copies a specified number of bytes from one buffer to another
(handles overlapping source and destination).
memset Sets a specified number of bytes of a buffer to a given value.
strcat Appends one string to another.
strchr Locates the first occurrence of a character in a string.
strcmp Compares one string to another and differentiates between lowercase
and uppercase letters.
strcoll Compares two strings using a collating sequence specified by the LC__
COLLATE category of current locale.
182 ANSI C Data Processing

Table 14-1. (cont.)

Routine Description

strcpy Copies one string to another.


strespn Returns the position in the string of the first character that belongs to
a given set of characters.
strerror Returns a string containing the system error message corresponding
to an error number.
strlen Returns the length of a string as the number of bytes in the string
excluding the terminating null.
strncat Appends a specified number of characters of one string to another.
strnacmp Compares a specified number of characters of two strings while
maintaining the distinction between lowercase and uppercase letters.
strncpy Copies a specified number of characters from one string to another.
(Note: resulting string will not automatically have a null character
appended.)
strpbrk Locates the first occurrence of any character from one string in
another.
strrehr Locates the last occurrence of a character in a string.
strspn Returns the position in the string of the first character that does not
belong to a given set of characters.
strstr Locates the first occurrence of one string in another.
strtok Returns the next token in a string with the token delimiters specified in
a string.
strxfrm Transforms a string to a new form so that if strcmp is applied to two
i transformed strings the returned result is the same as that returned
when strcoll is applied to the original strings.
wctomb Converts a character of wchar_ttype to a multibyte character.
wcstombs — Converts a sequence of codes of wchar_t type sequence of multibyte
characters.

Table 14-2. String and Buffer Manipulation Routines by Task


Task Routines

Find length of a string mblen, strlen


Compare two strings or buffers memcemp, strcmp, strncmp, strcoll,
strxfrm
Copy and append memcpy, memmove, strcat, strcpy,
strneat, strncpy
Search for a character or a substring memchr, strchr, strcspn, strpbrk,
strrchr, strspn, strstr
Extract tokens from a string strtok
Load the same character into every memset
position in a buffer
Prepare error message in a string strerror
Convert between multibyte and wide mbtowc, mbstowcs, wctomb, wcstombs
character type
14—String and Buffer Manipulation 183

Finding Length of a String


The length of a C string is the number of bytes in the string not
counting the terminating null byte. The string str2 in F igure 14-1
is 8 bytes long, for example, although 9 bytes are needed to store
the entire string. You can use strlen to find the length of a C
string. Use mblen to find the number of bytes in a single mul-
tibyte character.

Comparing Strings and Buffers


Five functions in the library are used for comparing Strings or
buffers: memcmp, strcmp, strncmp, strcoll, and strxfrm. Each
function returns a zero for a perfect match. A negative value indi-
cates that the first argument is less than the second, which
means that it appears before the second one in a dictionary of
words in that character set. Similarly, a positive return value indi-
cates that the first argument is greater than the second.
The routine strcmp compares the lengths of two strings and
it differentiates between lowercase and uppercase letters. The
memcmp and strncmp functions behave like strcmp, but they
only compare a specified number of characters from the begin-
ning of each string. The strcol/ function is meant for comparing
strings using a collating sequence determined by the LC_COL
LATE category of the locale (see Chapter 8 for more on locales).
The strxfrm function is a utility routine that transforms a string
into a new form such that if strcmp were used to compare two
transformed strings the result would be identical to that re-
turned by sércoll applied to the original strings.

Copying and Appending


The memcpy, memmove, strcat, strcpy, strncat, and strncpy
functions are for copying and concatenating strings and buffers.
The memcpy and memmove functions are for copying one
buffer into another, but only the latter works properly when the
source and destination buffers overlap.
The strcat function appends a second string argument to a
first one and produces a null-terminated string as the result. The
strncat function is a version of strcat that copies only a specified
number of characters from the second string to the first.
The strcpy function copies a second string argument to a
first one. While strcpy copies the entire string, strncpy copies
only a specified number of bytes. When strncpy does not copy
the entire string, it does not automatically append a null to the
result. You must ensure that there is enough room in the first
string to hold the second one. You can do this either by declar-
ing an array of characters or by allocating memory at run-time.
184 ANSI C Data Processing

Parsing a Command Line: Extracting Tokens


Earlier we alluded to the need for interpretation of application
commands. To enable interpretation, you need to separate the
command string into its component parts. For example, if you
chose a command syntax of the form
<COMMAND> <PARAMETER_1> <PARAMETER_2>

your command strings will consist of a command word fol-


lowed by two parameters with blank spaces or tabs as the charac-
ters that separate the different parts of the command. Now you
read a command line of the form
copy xX y
which to your application means copy the value of x into y. In
this case, the parts are
<COMMAND> = copy
<PARAMETER_1> = x
<PARAMETER_2> = y

The process of separating the command line into these compo-


nents is known as ‘“‘parsing.’ Each component is a “token.”

Extracting Tokens
The C library has routines that help parse a string. The striok
function can get the tokens one by one. If you prefer, you can
use the routines strcspn and strspn to construct your own
parser, especially if your command language is much more com-
plicated than the one in our example. The strcspn function re-
turns the index of the first character (its location in the array) that
matches any one of the characters in a second string, while
strspn does just the opposite, returning the first character that
does not belong to the second string.
The strpbrk routine functions the same way as strcspn, but
it returns a pointer to the matched character rather than the in-
dex. The strstr function searches for the occurrence of one
string in another, and strchr and strrchr locate a single character
in a string. The strchr function searches from the string’s begin-
ning for the character, and strrchr searches from the end.

Conversion Between Multibyte and Wide Characters


ANSI C provides functions to convert extended characters and
strings to and from multibyte and wide character representa-
tions. The functions mbtowc and wctomb handle single charac-
ters while mbstowcs and wcstombs are meant for extended
character strings. The behavior of these routines is affected by
the LC_CTYPE category of the current locale. See setiocale in
Chapter 8 for more details on locales.
14—String and Buffer Manipulation 185

Cautions
& When allocating memory for a string, remember to count
the null character. If you are allocating memory to hold an-
other copy ofa specific string named, say, str, you can com-
pute the number of bytes you need by adding 1 to the value
returned from the call strlen(str).
& When copying a string to another, you must ensure that the
destination string has enough room to hold the incoming
characters. You will see no error messages if the copy opera-
tion continues beyond the last character of the destination
string, but the program is likely to fail in an unpredictable
way.
> If you use sirncpy to copy a specific number of bytes, less
than the length of the source string, to another one, the re-
sulting string will not have a null character automatically ap-
pended to it. So, you must append a \0 to convert the result
to a valid C string.

mblen <

Purpose
Use the mbien function to obtain the number of bytes that con-
stitute a multibyte character.

Syntax
#include <stdlib.h>
int mblen(const char *s, size_t n);
const char *s; Pointer to multibyte character whose length is to be
determined

size_t n; Maximum number of bytes expected to compose a multibyte


character (MB_CUR _MAX is a good choice for this
argument)

Example Call
mbsize = mblen(p_mbchar, MB_CUR_MAX);

Returns

If s is NULL, mblen returns a zero or a nonzero depending on


whether multibyte encodings have state dependencies or not. If
sis not NULL, mblen returns the number of bytes that compose
the multibyte character, provided the next 7 or fewer characters
form a valid multibyte character. Otherwise, it returns —1.

See Also
mbtowc, mbstowcs, wctomb, wcstombs

mblen
186 ANSI C Data Processing

ee

> mbstowcs

Purpose
Use the mbstowcs function to convert a sequence of multibyte
characters in mbs into a sequence of codes of wchar_t type and
store, at most, 7 codes in the array pwes.

Syntax ae
#include <stdlib.h>
size_t mbstowcs(wchar_t *pwcs, const char *mbs, size_t n);
wcha r_t *pwcs; Pointer to array where wide character results will be
stored

const char *mbs; Pointer to array of multibyte characters being


converted to wide characters

size_t n; Maximum number of wide characters to be stored in pwcs

Example Call
mbstowcs(wc_array, mb_array, 10);

Returns

If successful, mbstowcs returns the number of wide characters it


stored in pwes. If it encountered less than 7 multibyte charac-
ters. it returns —1 cast-as*s7ze 7:

See Also
mblen, mbtowc, wctomb, wcstombs

> mbtowc

Purpose
Use the mbtowc function to convert a multibyte character at s to
wchar__t type and store the result in the array pwchar. If pwchar
is NULL, mbtowc will not save the resulting wide character. Also,
mbtowc will check at most characters in s when trying to lo-
cate a valid multibyte character.

Syntax
Hinclude <stdlib.h>
int mbtowc(wchar_t *pwchar, const char *s, size_t n);
wchar_t *pwchar; Pointer to array where the wide character equivalent
of the multibyte character will be stored

mbtowc
14—String and Buffer Manipulation 187

const char *s; Pointer to multibyte character to be converted to wide


character format

si Zentin; Maximum number of bytes expected to compose a multibyte


character (MB_CUR_MAX is a good choice for this
argument)

Example Call
mdc_size = mbtowc(pwc, mbchar, MB_CUR_MAX);

Returns

If sis NULL, mbtowc returns a zero or a nonzero depending on


whether multibyte encodings have state dependencies or not. If
s is not NULL, mbtowc returns the number of bytes that com-
pose the multibyte character, provided the next 7 or fewer char-
acters form a valid multibyte character. Otherwise, it returns —1.

See Also

mblen, mbstowcs, wctomb, wcstombs

memchr <<

Purpose
Use the memchr function to search the first count bytes in the
buffer at the address buffer to find the first occurrence of the
character c.

Syntax
#include <string.h>
void *memchr(const void *buffer, int c, size_t count);
const void *buffer; Pointer to buffer in which search takes place

int c; Character to look for

size_t count; Maximum number of bytes to be examined

Example Call
/* Look for the first occurrence of ‘I’ in a 100 byte buffer
*/
first_i = memchr(start_address, ‘I', 100);

Returns

If memchr finds the character c, it returns a pointer to this char-


acter in buffer. Otherwise, memcbhr returns a NULL.

See Also

memcmp, strchr

memchr
188 ANSI C Data Processing

nl

> memcmp

Purpose
Use the memcmp function to compare the first count bytes of
buffer1 and buffer2.

Syntax
#include <string.h>
int memcmp(const void *buffer1, const void *buffer2,
size_t count);
const void *buffer1; Pointer to first buffer

const void *buffer2; Pointer to second buffer

size_t count; Number of bytes to be compared

Example Call
if (memcmp(buffer1, buffer2, sizeof(buffer1)) == 0)
printf("'The buffers are identical\n");

Returns
The memcmp function returns an integer less than, equal to, or
greater than zero according to whether the string buffer/ is lexi-
cographically less than, equal to, or greater than the string
buffer2.

See Also
strcoll, strcmp, strncmp

> memcpy
Purpose
Use the memcpy function to copy count bytes from the buffer at
address source to another buffer at dest. The behavior of
memcpy is undefined if the source and destination buffers over-
lap.

Syntax
#include <string.h>
void *memcpy(void *dest, const void *source, size_t count);
void xdest; Pointer to buffer to which data will be copied

const void *source; Pointer to buffer from which data will be copied

size_t count; Maximum number of bytes to be copied

memcpy
14—String and Buffer Manipulation 189

Example Call
memcpy(dest, src, 80); /* Copy 80 bytes from dest to src */

Returns

The memcpy function returns a pointer to the destination buffer


dest.

See Also

memmove, strcpy, strncpy

SS

memmove <4

Purpose
Use the memmove function to copy count bytes from the buffer
at address source to another buffer at dest. The source and desti-
nation buffers may overlap.

Syntax
#include <string.h>
void *memmove(void *dest, const void *source, size_t count);
void *dest; Pointer to buffer to which data will be copied

const void *source; Pointer to buffer from which data will be copied

size_t count; Maximum number of bytes to be copied

Example Call
memmove(dest, src, sizeof(src));

Returns
The memmove function returns a pointer to the destination
buffer dest.

See Also
memcpy, strcpy, strncpy

memset <

Purpose
Use the memset function to set the first count bytes in the buffer
to the character c.

memset
190 ANSI C Data Processing

Syntax
#include <string.h>
void *memset(void *buffer, int c, size_t count);
void *buffer; Pointer to memory where bytes are to be set

Tint ees Each byte in buffer will be set to this character

size_t count; Maximum number of bytes to be set

Example Call
memset
(big buffer, ‘\O0', 2048);

Returns

The memset function returns the argument buffer.

See Also

memcpy, memmove, strcpy, strncpy

> streat

Purpose
Use the strcat function to append string2 to string1. The initial
character of string2 overwrites the null character at the end of
String].

Syntax
#include <string.h>
char *strcat(char *string1, const char *string2);
char *string1; Destination string

const char *stringe; String to be appended

Example Call
char metool[7] = ''Me '';
strcat(metoo, "too'); /* Result is "Me too! */

Returns

The strcat function returns a pointer to the concatenated string


string1.

See Also

strcpy, strncat, strncpy

Example
See Example 14-1 at the end of the chapter for a use of strcat to
concatenate strings.

strcat
14—String and Buffer Manipulation 191

eee ee a ee
Strchr <4

Purpose
Use the strcbr function to search for the first occurrence of the
character c in string. The terminating null character is included
in the search and may also be the character to be located.

Syntax
#include <string.h>
char *strchr(const char *string, int c);
const char *string; String to be searched

int c; Character to be located

Example Call
cost_is = strchr("Estimated cost = $120", '$');
/* Now cost_is will be the string ''$120" */

Returns

If the character c is found, strchr returns a pointer to its first oc-


currence in string. For example,
printf(''%s", strchr("Annual salary = $35,750", ‘$'));
prints $35, 750. If the search fails, strchr returns a NULL.

See Also

strcspn, strpbrk, strrchr, strstr

strcmp <

Purpose
Use the strcmp function to compare the strings string/ and
string2 lexicographically.

Syntax
#include <string.h>
int strcemp(const char *string1, const char *string2);
const char *string1; First string

const char *string2; Second string

Example Call
if( strcmp(username, "root") != 0 ) exit (EXIT_FAILURE);

strcmp
192 ANSI C Data Processing

Returns

The strcmp function returns an integer greater than, equal to, or


less than zero according to whether string/ is greater than, equal
to, or less than string2.

See Also
memcmp, strcoll, strncmp

> streoll

Purpose
Use the strcoll function to compare the strings string1 and
string2 after interpreting both according to the character collat-
ing sequence selected by the LC_COLLATE category of the cur-
rent locale.

Syntax
#include <string.h>
int strcoll (const char *string1, const char *string2);
const char *string1; First string

const char *string2; Second string

Example Call
if( strcoll(username, rootname) != 0 ) exit (EXIT_FAILURE);

Returns

The strcoll function returns an integer greater than, equal to, or


less than zero according as string] is greater than, equal to, or
less than string2 when both are appropriate to the current lo-
cale.

See Also

memcmp, strncmp

> strcpy

Purpose
Use the strcpy function to copy the string string2 to the string
string!. The terminating null character of the second string is
also copied so that string/ becomes a copy of string2.

strcpy
14—String and Buffer Manipulation 193

Syntax
#include <string.h>
char *strcpy(char *string1, const char *string2);
char *string1; Destination string

const char *string2; String to be copied to the first one

Example Call
strcpy(command, "resize"');

Returns

The strcpy function returns a pointer to the copied string


(string1).

See Also
memcpy, memmove, strncpy

strcspn <<

Purpose
Use the strcspn function to compute the length of the maximum
initial segment of string/ that consists entirely of characters not
in string2. This is the first substring in string/ that does not span
the character set string2.

Syntax
#include <string.h>
size_t strcspn(const char *string1, const char *string2);
const char *string1; String to be searched

const char *string2; String describing set of characters to be located

Example Call
first_q = strcspn("soliloquy", "q"'); /* first_q = 6 */

Returns

If successful, the strcspn function returns the length of the seg-


ment.

See Also
strchr, strpbrk, strspn, strrchr

strcespn
194 ANSI C Data Processing

ne

> strerror

Purpose

Use the strerror function to obtain the systenrerror message cor-


responding to the error number given in the argument errnum.
Note that strerror only returns the error message; printing the
message is up to you.

Syntax
#include <string.h>
char *strerror(int errnum);
int errnum; Error number

Example Call
error_message = strerror(errno);

Returns

The strerror function returns a pointer to the error message. The


text of the message is implementation dependent.

See Also
perror
.

> strien

Purpose
Use strlen to find the length of string in bytes, not counting the
terminating null character.

Syntax
#include <string.h>
size_t strlen(const char *string);
const char *string; String whose length is returned

Example Call
length = strlen(name);

Returns

The strlen function returns the number of characters in string


that precede the terminating null character.

strien
14—String and Buffer Manipulation 195

See Also
strcspn

strncat <4

Purpose
Use the strncat function to append the first m characters of
string2 to string, and terminate the resulting string with a null
character. The terminating null of the first string is removed and
string1 becomes the concatenation of the old string/ and the
first 2 characters of string2.

Syntax
#include <string.h>
char *strncat(char *string1, const char *string2, size_t n);
char *string1; Destination string

const char *string2; String whose first n characters are to be


appended to the first one

size_t n; Number of characters of string2 to be appended to string1

Example Call
char id[16] = "ID = ";
strncat(id, name, 10); /* id is first 10 char of name */

Returns
The strncat function returns a pointer to the concatenated
string, string/.

See Also
strcat, strcpy, strncpy

Example
Example 14-2 uses strncat to print a generate of characters.

——_____.___

strncmp

Purpose
Use the strncmp function to compare, at most, the first 2 charac-
ters of the strings string/ and string2.

strncmp
196 ANSI C Data Processing

Syntax
#include <string.h>
int strncmp(const char *string1, const char *string2, size_t
n);
const char *string1; First string
const char *string2; Second string :

size_t n; Number of characters to be compared

Example Call
if(strncmp(command, "quit", 4) == 0) quit_program();

Returns

The strncmp function returns an integer greater than, equal to,


or less than zero according to whether the first 7 characters of
string! are greater than, equal to, or less than string2.

See Also
memcmp, strcmp, strcoll

> strncpy
»

Purpose
Use the strncpy function to copy the first 7 characters of the
string string2 to the buffer whose address is given by string/.
The copy is placed at the first character position of string/. Ifn
is less than the length of string2, no terminating null character is
appended to string1. However, if m exceeds the length of
string2, string1 is padded with enough null characters to make
it 2 bytes long. You should avoid situations where the 7 bytes
following string1 overlap string2, because the behavior of
strcpy with such arguments is not guaranteed to be correct.

Syntax
#include <string.h>
char *strncpy(char *string1, const char *string2, size_t n);
char *string1; Destination string

const char *string2; String whose first n characters are to be copied


to the first one

size_t n; Number of characters to be copied

Example Call
strncpy(fname, '"'tmp12345678", 8); /* fname = "tmp12345" */

strncpy
14—String and Buffer Manipulation 197

Returns

The strncpy function returns a pointer to String1.

See Also

memcpy, memmove, strcat, strncat, strcpy

gee ee ee ss a re tae
strpbrk <4

Purpose
Use the strpbrk function to locate the first occurrence in string/
of any character in string2.

Syntax
: ON
#include <string.h>
char *strpbrk(const char *string1, const char *string2);
const char *string1; String to be searched

const char *string2; String describing set of characters to be located

Example Call
first_vowel = strpbrk(word, "aeiou'');

Returns
If successful, the strpbrk function returns a pointer to the first
occurrence of any character from string2 in string1. If the
search fails, strpbrk returns a NULL.

See Also
strchr, strcspn, strrchr, strspn

Example
Example 14-3 uses strpbrk to extract the first syllable in a word.

strrchr <4

Purpose
Use the strrchr function to locate the last occurrence of the char-
acter c in the string string. The terminating null character is in-
cluded in the search and it can be the character to be located.

Syntax
#include <string.h>

strrchr
198 ANSI C Data Processing

char *strrchr(const char *string, int c);


const char *string; String to be searched

antec. Character to be located

Example Call
char line_costl[] = '10 units at $1.20 ea. = $12.00";
total_cost = strrchr(line_cost, '$');
/* Now total_cost will be the string "$12.00" */

Returns
If cis found, strrchr returns a pointer to the last occurrence of it
in string. If the search fails, strrcbr returns a NULL.

See Also
strchr, strcspn, strpbrk, strspn

> strspn

Purpose
Use the strcspn function to compute the length of the maximum
initial segment of string/ that consists entirely of characters
from string2. This is the first substring in string/ that spans the
character set string2.

Syntax
Hinclude <string.h>
size_t strspn(const char *string1, const char *string2);
const char *string1; String to be searched

const char *string2; String describing set of characters to be found

Example Call
char *input = "280ZX";
first_nondigit_at = strspn(input, '1234567890") ;
/* first_nondigit_at will be 3 */

Returns

The strspn function returns the length of the segment.

See Also

strcspn, strpbrk

strspn
14—String and Buffer Manipulation 199

reer ee ee a ee

strstr <4

Purpose
Use strstr to locate the first occurrence of String string2 in
String1.

Syntax
#include <string.h>
char *strstr(const char *string1, const char *string2);
const char *string1; String to be searched

const char *string2; String to be located

Example Call
char input(J="The account number is ACEG-88-07-11";
acc_no = strstr(input, '"ACEG'');
/* Now the string acc_no will be "ACEG-88-07-11"' */

Returns

If successful, the strstr function returns a pointer to the first oc-


currence of string2 as a substring in string/. If the search fails,
strstr returns a NULL.

See Also
strchr, strcespn, strpbrk

strtok <4

Purpose
Use the strtok function to retrieve a token, or substring, from
string1. The token is marked by delimiting characters given in
the second string argument string2. All tokens in a particular
string (string/) can be extracted through successive calls to
strtok in the following way. Make the first call to strtok with the
string to be “‘tokenized” as the first argument. As the second ar-
gument, provide a string comprising the delimiting characters.
After that, call strtok with a NULL as the first argument and the
delimiting characters appropriate for that token in the second
string. This tells strtok to continue returning tokens from the old
stringl.
Note that the set of delimiters can change in each call to
strtok. Also, in the process of separating tokens, strtok modifies
string/. It inserts null characters in the place of delimiters to
convert tokens to strings.

strtok
200 ANSI C Data Processing

Syntax
#include <string.h>
char *strtok(char *string1, const char *string2);
char *string1; String from which tokens are returned .

const char *stringé; String describing set of characters that delimit


tokens :

Example Call
next_token = strtok(input, "\t, ');

Returns

The first call to strtok with the argument string/ returns a


pointer to the first token. Subsequent calls with a NULL as the
first argument return the next token. When there are no more
tokens left, strtok returns a NULL.

See Also
strcspn, strpbrk, strspn

Example
Example 14-4 shows a simple program that extracts tokens from
a String.

> strxfrm

Purpose
Use the strxfrm function to transform string2 to a new form
(string1) so that if strcmp is applied to the two transformed
strings the returned result is the same as that returned when
strcoll is applied to the original strings. You can place no more
than maxchr characters in string. lf maxcbr is 0, string] can be
a NULL. In this case, the return value is the length of the trans-
formed version of string2.

Syntax
#include <string.h>
size_t strxfrm(char *string1, char *string2, size_t maxchr);
char *string1; String where transformed version of string2 is returned
char *string2; String to be transformed
size_t maxchr; Maximum number of characters to be placed in string]

Example Call
strxfrm(s_xfrm, s_original);

strxfrm
14—String and Buffer Manipulation 201

Returns

The strxfrm function returns the length of the transformed


string, not counting the terminating null character. If the return
value is maxchr, the contents of string/ may be unusable.

See Also

strcmp, strcoll

ee ee IN Ca ANT IS
wctomb <4

Purpose
Use the wctomb function to convert wchar, a character of wchar_t
type to a multibyte character and store the result in the array s. At
most, MB_CUR_MAX characters are stored in the array s.

Syntax
#include <stdlib.h>
int wetomb(char *s, wchar_t wchar);
char *s; Pointer to start of array where the multibyte equivalent of
wchar is returned

wehar_t wechar; Wide character to be converted to multibyte format

Example Call
wetomb(mb_char, wchar);

Returns

If sis NULL, wctomb returns a zero or a nonzero, depending on


whether multibyte encodings have state dependencies. Ifs is not
NULL, wctomb returns the number of bytes that compose the
multibyte character corresponding to the wide character wchar.
If wchar does not correspond to a valid multibyte character, it
returns —1.

See Also

mblen, mbtowc, mbstowcs, wcstombs

westombs <

Purpose
Use the wcstombs function to convert a sequence of codes of
wchar__t type, given in the array pwes, into a sequence of mul-
tibyte characters and to store, at most, ” bytes in the array mbs.

westombs
202 ANSI C Data Processing

Syntax
#include <stdlib.h>
size_t wcstombs(char *mbs, const wchar_t *pwes, size_t n);
const char *mbs; Pointer to array where mulibyte characters will be
stored

wchar_t *pwcs; Pointer to array of wide characters to be converted to


multibyte format

size_t n; Maximum multibyte characters to be stored in mbs

Example Call
westombs(mb_array, wc_array, 10*MB_CUR_MAX);

Returns

If successful, the wcstombs function returns the number of bytes


it stored in mbs, not including a terminating null character. If
westombs encounters a wide character code that does not corre-
spond to a valid multibyte character, it returns —1 cast as size_t.

See Also

mblen, mbtowc, mbstowcs, wctomb

Example 14-1 This program prompts the user for a first


name, last name, and middle initial. Then it
uses strcat to construct the full name and
. print a message.
1:#include <stdio.h>
2:#include <string.h>
3:main()
:f
De char fullname[80], last{40], middle[10];
6: printf("Enter your first name: ");
iC: gets(fullname);
8: printf("'Last name: '');
9: gets(last);
10: printf("'Middle initial: '");
Wilts gets (middle);
12:/* Append the parts together to get full name */
AS strcat(fullname," '');
14: strcat (fullname, middle);
15: strcat(fullname," ");
16: strcat(fullname, last);
divs printf("Greetings! %s\n"', fullname);
18:}
Example 14-2 This program uses strncat to generate and
print this sequence of strings.
a
ab
abc

wcstombs
14—String and Buffer Manipulation 203

abcd
abcde

abcdefghi jklmnopqrstuvwxyz

1:#include <stdio.h>
2:#include <string.h>
3:char result(40) = ''a!'s
4:char rest(] = "bcdefghi jklmnopqrstuvwxyz''s
Ssunsigned length = sizeof(rest)/sizeof(char);
6:main()
7:
8: unsigned i;
9: for(i = 0; i<length; i++, result(1}='\0')
10: {
ARIE strncat(result, rest, i);
12:/* Show the current result */
AS printf('"'%s\n", result):
14: }
{heres

Example 14-3 This example uses strpbrk to locate the first


occurrence of a vowel in a word and to print
the word up to and including the vowel (this
tends to extract the first syllable from the
word).
1:#include <stdio.h>
2:#include <string.h>
3:char *vowels = "aeiou'';
4:mainQ
Dt
6: char stri1[80], *result;
as printf("Enter a word: ");
8: gets(str1);
9: if ((result = strpbrk(str1, vowels)) == NULL)
10: {
aie printf('"'No vowels in word\n'');
fs 3
1535 else
14: {
iD: printf("First syllable in %s ", str1);
16:/* Put a null character just after the first vowel */
nites result+t+;
18: *xresult, =, \05;
19: printf("is: %s\n", str1);
20: }
204 ANSI C Data Processing

Example 14-4 This program reads a string and separates it


into tokens. Assume that the tokens are sepa-
rated by blank spaces, tabs, or commas. This
process of converting the input strings to to-
kens (parsing) is one of the first things any
command interpreter or compiler has to do.
1:#include <stdio.h>
2:#include <string.h>
3:char tokensep[] =" \t,";
4:mainQ) >
Set
6: int i = 0;
is char buf[80], *token;
8: printf("Enter a string of tokens separated by comma’
Oe "or blank:');
10: gets (buf);
11:/* Call strtok once to get first token and initialize it */
fi2: token = strtok(buf, tokensep);
13:/* Keep calling strtok to get all tokens */
14: while(token != NULL)
15: {
16: i++;
Tes printf("Token %d = %s\n"', i, token);
18: token = strtok(NULL, tokensep);
19: }
Searching and Sorting

Introduction
Searching and sorting are commonplace. All commercial data
base programs have these capabilities, for instance. If you are im-
plementing your own data base program, you invariably need
search and sort capabilities. For example, if your data base con-
tains the names and addresses of the customers of your com-
pany, you might want to search the data base for information
about a certain customer. And you might want to print labels for
a mailing for all entries in your data base sorted by zip code. If
you are developing your data base in C, the ANSI C standard
eases your job by providing two library routines for sorting and
searching lists in memory.

Searching and Sorting


Many algorithms perform searching and sorting; some are meant
for arrays that fit into memory and others that are meant to han-
dle files much too large to fit into the memory of the computer.
The ANSI C library sort and search functions are suitable for in-
memory operations only.

Sorting
The typical sort operation you will encounter involves a data lay-
out like that shown in Figure 15-1. You have an array of pointers,
each of which contains the address of a data structure (for ex-
ample, a structure with fields containing the name, address, and
zip code for a customer). Sorting is done not by rearranging the
data records themselves, which would be inefficient, but by re-
arranging the pointers to cause a particular field in the data struc-

205
206 ANSI C Data Processing

ture (called the “key” for the sort) to appear in either ascendant
or descendant position. Figure 15-1 shows the original list and
the list after it was sorted with the zip code (the key field) ascen-
dant. Notice that only the pointers were rearranged; the data
structures stayed put. This improves sorting speed because the
pointers are much smaller than the structures themselves, even
though the pointers require extra storage space.

Address:
Zip: 94115

Original Pointers after


pointers
Zip: 20904 sy

Name:

Zip: 10020 B

. Address:
Zip: 95066 y

Zip: 98073

Figure 15-1. Sorting

In its sort and search routines the ANSI C library supplies


the basic algorithms but you supply the starting address of the
array, the number of elements in it, the size (in bytes) of each ele-
ment, and a pointer to a function that performs the comparison
of two elements.
You write the function that compares two elements from
the array. The function receives the pointers to the two elements
and returns an integer value. A positive return value signifies that
the first element is greater than the second one. A zero signifies
equality, and a negative value means that the first element is less
than the second one. You define what less than and greater than
mean. In the name and address data base example, you could
compare the zip code field of the two structures and return a
value based on which zip is higher. If you wanted to sort by the
name field, you could compare the names alphabetically. With
15—Searching and Sorting 207

your definition, the sort function gsort will sort the array in
as-
cending order.
Although the ANSI standard does not specify which algo-
rithm to use, typical implementations of qsort use the well-
known “quicksort” algorithm, a popular, general-purpose sort
algorithm invented by C. A. R. Hoare in 1962.

Searching
The ANSI C library includes the bsearch function, which
searches an array for an item using a binary search algorithm. Al-
though the ANSI standard does not enforce a specific search al-
gorithm, most compilers implement bsearch. Like quicksort,
binary search uses a divide-and-conquer approach analogous to
looking up a word in the dictionary. You flip to a page around the
middle of the dictionary and if the words on that page occur
later in alphabetic order than the word you are looking for, you
repeat the search in the first half of the dictionary. Ofcourse, this
method works only because the dictionary is already sorted ina
particular order.
The ANSI standard does require that the array must be
sorted in ascending order of the key field to be searched. This is
necessary for the binary search algorithm. The binary search be-
gins by comparing the value of the key field in the middle entry
of the array with the value being sought. If the entry has a value
either too high or too low, this search step is repeated on the
upper half or lower half of the array, respectively. Thus at every
step of the search you reduce the length of the array to be
searched by half, allowing a large array to be searched very
quickly.

Using the Search and Sort Routines


Of the two routines in this category, gsort is meant for sorting an
array of elements and bsearch is for searching that, or another,
array of elements for a given value. These routines are designed
to be used in a standard way. Figure 15-2 shows the arguments
you must pass to the routines. These include the starting address
of the array; the number of elements in it; the size (in bytes) of
each element; and a pointer to a function, compare(_), that per-
forms the comparison of two elements. Figure 15-2 also shows
sorting or searching the command-line arguments that are
passed to the main function in your program. For a declaration
of the form main(int argc, char * *argu), the number of argu-
ments are in argc (this is the standard way a program can access
its command-line arguments) and the starting address of the ar-
ray is argv. Each element is a pointer to a C string, so the size of
each element is given by sizeof(char *). Finally, the comparison
function is called as compare(char * *elem1, char * *elem2)
with two arguments, each a pointer to a variable that points to a
208 ANSI C Data Processing

string. You can use a routine such as strcmp to perform the com-
parison inside compare( ).

Information
you provide |
Size of each element |
size = sizeof(char*)——+
|__
|
|
Comparison |
routine |
compare PEE ERAN
|
(char**
x* | Command-line
ona | arguments
|

|
Base of array _
char*

Number
of elements

_ unsigned” | numelem

Figure 15-2. Sorting and Searching Command-Liine


Arguments

Further Reading
Search and sort algorithms are covered in every computer Ssci-
ence text On data structures and algorithms. An entire volume by
Knuth! deals with sort and search algorithms alone. For a shorter
introduction to these algorithms, consult the books by Sedge-
wick? and Tremblay and Sorenson’.
1. Donald E. Knuth, The Art of Computer Programming, Vol-
ume 3: Sorting and Searching, Addison-Wesley Publishing
Co., Reading, MA, 1973, 744 pages.
2. Robert Sedgewick, Algorithms, Addison-Wesley Publishing
Co., Reading, MA, 1983, 551 pages.
3. Jean-Paul Tremblay and Paul G. Sorenson, An Introduction
to Data Structures with Applications, Second Edition,
McGraw-Hill, Inc., New York, NY, 1984, 861 pages.
15—Searching and Sorting 209

bsearch <

Purpose
Use the bsearch function to search a sorted array beginning at
the address base and comprising num elements, each of a size of
width bytes. The argument key points to the value being sought.
See the tutorial section for more on the function pointer com-
pare that you must provide to bsearch. Note that you can use the
qsort routine to sort the array before calling bsearch.

Syntax
#include <stdlib.h>
void *bsearch(const void *key, const void *base, size_t num,
size_t width,
int (*compare) (const void *elem1, const void
xelem2));

const void *key; Pointer to value being searched for

const void *base; Pointer to beginning of array being searched

size_t num; Number of elements in array

size_t width; Size of each element in bytes

int (*compare) (const void *elem1, const void *elem2);


Pointer to a function that compares two elements elem1 and elem2, each
of type const void *

Example Call
int mycompare(const void *, const void *);
result = (char **) bsearch((const void *) keyword
(const void *)envp,
(size_t)count,
(size_t)sizeof(char *),
mycompare);

Returns
The bsearch function returns a pointer to the first occurrence of
the value ey in the array. If the value is not found, bsearch te-
turns a NULL.

See Also
qsort

Example
Line 29 in Example 15-1 calls bsearch to search fora keywordina
sorted array.

bsearch
210 ANSI C Data Processing

> qsort

Purpose
Use the gsort function to sort an array beginning at the address
base and comprising num elements, each of size width bytes.
During the sort, gsort compares pairs of elements from the array
by calling a routine whose address you provide in the argument
compare. This function should accept two arguments, elem1
and elem2, each a pointer to an element in the array. See the tuto-
rial section for information on how this function should behave.

Syntax
#include <stdlib.h>
void qsort(const void *base, size_t num, size_t width,
int (*compare) (const void *elem1, const void
xelem2));
const void *base; Pointer to beginning of array being sorted

size_t num; Number of elements in array

size_t width; Size of each element in bytes

int (*compare) (const void *elem1, const void *elem2);


Pointer to a function that compares two elements, elem1 and elem2, each
of type const void *

Example Call
int compare(const void *, const void *);
qsort((void *) envp, (size_t)count,
(size_t)sizeof(char *), compare);

See Also

bsearch

Example
Line 19 in Example 15-1 calls gsort to sort an array.
Example 15-1 In Microsoft C under MS-DOS, the main func-
tion is invoked with three arguments, the first
two give the number of strings in the com-
mand line and the command line itself. The
third argument is the MS-DOS environment
table, which is also an array of strings. Write a
program that accepts a keyword on the com-
mand line and uses bsearch to search for the
string beginning with this keyword in the en-
vironment table. The program first sorts the
environment table using gsort, and then
prints it and then calls bsearch to perform the

qsort
15—Searching and Sorting 211

search. Note that the end of the environment


table is marked by a NULL entry. Use this in-
formation to count the number of entries in
the table.
1:#include <stdio.h>
2:#include <string.h>
3:#include <stdlib.h>
4:int mycompare(const void *, const void *);
S:mainCint argc, char **argv, char **envp)
6:f
Gs unsigned int i, count;
8: char **p_table, **result;
Oe if(arge < 2)
10: {
tals printf("'Usage: %s <KEYWORD>\n", argv[0]);
We exit (0);
1335 }
14:/* Find length of environment table */
i/555 for(count = 0, p_table = envp;
16: *p_table != NULL;
Ute p_tablet++, count++); /* a null loop */
18:/* Sort the environment table using "'qsort'' */
19: qsort((void *) envp, (size_t)count,
20: (size_t)sizeof(char *), mycompare);
21:/* Print sorted environment table */
22: printf ("===== Sorted environment table =====\n!'');
(oes for(i = 0, p_table = envp; i < count; i++)
24: {
25: printf(''%s\n'"', *p_table);
26: p_tablet++;
hs }
28:/* Search for the KEY variable in the environment */
29: result = (char **) bsearch((const void *)&argv[1],
30: (const void *)envp,
Sis (size_t)count,
32: (size_t)sizeof (char *),
SEIS mycompare);
34: if(result != NULL)
35% {
36: printf('"'\nFound %s in\n%s\n", argvl[1], *result);
372 :
38: else
39: {
40: printf("'\n%s not found.\
41:Try with uppercase keyword\n", argv[1]);
42: }
43:}
OS ne ea */
45:int mycompare(char **arg1, char **arg2)
46:{
47:/* Compare two strings up to the length of the key */
212 ANSI C Data Processing

48: return(strncmp(*arg1, *arg2, strlen(*arg1)));


49:}
50:

Here is a sample output (assuming that you saved, the executable


program in the file BSEARCH.EXE):
C:\ACEG\EX>bsearch PROM
===== Sorted environment table =====
COMSPEC=C: \COMMAND. COM
INCLUDE=c:.\include
LIB=c:\lib
PATH=C:\;C:\DOS3.1;C:\BIN;C:\MSK229;C:\TURBOC;C:
\MASM
PROMPT=$p$g
TMP=c: \tmp

Found PROM in
PROMPT=$p$g
Time and Date Functions

Using the Time and Date Routines


The ANSI C library includes a set of routines for obtaining and
displaying date and time information. These routines are de-
clared in the header file t2me.h. The time function is at the heart
of these routines. It returns the current date and time in an im-
plementation-defined encoded form. There are library routines
which convert this time into a printable string and otherwise ma-
nipulate it. Table 16-1 catalogs the date and time functions and
they are classified by task in Table 16-2.

Table 16-1. Time and Date Routines

Routine Description

asctime Converts time from a structure of type tm to a string.


clock Returns the elapsed processor time in number of ticks.
ctime Converts time from a value of type time__tto a string.
difftime Computes the difference of two values of type time_t.
gmtime Converts time from a value of type time__tto a structure of type tm
which corresponds to the Greenwich Mean Time.
localtime Converts time from a value of type time_tto a structure of type tm
which corresponds to the local time.
mktime Converts the local time from a structure of type tm to a value of type
time_t.
stritime Prepares a string with date and time values from a tm structure,
formatted according to a specified format.
time Returns the current date and time, encoded as a value of type time_t.
The encoding is implementation dependent.

213
214 ANSI C Data Processing

Table 16-2. Time and Date Routines by Task


Task Routines

Get current date and time time


Convert time from one form to another —_asctime, ctime, gmtime, localtime, mktime
Compute elapsed time Clock, difftime.

Time in Many Forms


Figure 16-1 depicts the different formats of date and time and
conversions among them. The basic function time returns a
value of type time __t which is defined in the time.h header file.
This t#me_t value can be converted to a structure named tm (de-
fined in the time. h header file) by the routines gmtime and local-
time. The gmtime function sets all fields in the tm structure to
correspond to Greenwich Mean Time (GMT) while localtime
sets them to the local time. The mktime function converts time
from a structure tm to a value of type time _t.

System dat
end time

implementation
dependent encoded

ctime( )

int tm__sec
inta a a _
Thu Nov 26 17:02:39 1987 \n \0 5
int tn__mday ‘| asctime( ) String

eae
pe
wee.

int tm__wday Ve

int tm__isdst ~ | Structure tm

Figure 16-1. Conversion Among Different Forms


of Date and Time

Printing Date and Time


The asctime function converts the value in a structure of type tm
to a C string that you can print. The ctime function can convert
the output of time directly to a string.
16—Time and Date Functions 215

Elapsed Time
Sometimes you have to compute the time elapsed between two
events. The difftime function returns the difference of two val-
ues Of type time _t in seconds. The clock function returns the
number of clock ticks used by the process so far. The number of
ticks per second is defined in the constant CLK_TCK (in file
time.h). Its actual value is implementation dependent.

Cautions
Pm The functions gmtime and localtime use a single structure
of type tm to store the time. Each call to either function
Overwrites the result of the previous call.
Pe The ctime and asctime functions also use a single character
string to store results. Thus a call to one overwrites the re-
sult of the previous call.

asctime <<

Purpose
Use the asctime function to convert to a character string the
value of a time stored in the structure of type tm at the address
time. The structure tm is defined in time.h as
struct tm
{
int tm_sec; /* seconds after the minute - Shera

int tm_min; /* minutes after the hour - [0,59] */

int tm_hour; /* hours since midnight - [0,23] */

int tm_mday; /* day of the month - [1,31] */

int tm_mon; /* months since January - [0,11] */

int tm_year; /* years since 1900 */

int tm_wday; /* days since Sunday - [0,6] */

int tm_yday; /* days since January 1 - [0,365] ¥*/

int tm_isdst; /* daylight savings time flag */

i;

asctime
216 ANSI C Data Processing

The string prepared by asctime is 26 characters long, counting


the null character at the end, and has the form
Thu Jul 21 19:02:39 1988\n\0
As the example shows, a 24-hour clock is used for the time.

Syntax
#include <time.h>
char *asctime(struct tm *time);
struct tm *time; Pointer to a structure containing time to be converted
to a string

Example Call
printf("'The time is %s\n", asctime(&timedata));

Returns

The asctime function returns a pointer to the static data area


where the string is stored.

See Also

ctime, gmtime, localtime, time

> clock

Purpose
Use clock to obtain the amount of processor time used by the
current process in “number of ticks.” The constant CLK_TCK,
defined in time. h, is the number of ticks per second, so the value
returned by clock should be divided by CLK_TCK to get the
elapsed processor time in seconds.

Syntax
Winclude <time.h>
clock_t clock(void);

Example Call
ticks_now = clock();

Returns

If processor time is available to clock, it returns the current time


in ticks, Cast as a value of type clock__t which is defined in time.
b. Otherwise, it returns the value —1, cast as clock_t.

See Also

difftime, time
16—Time and Date Functions 217

SSS

ctime <<

Purpose
Use the ctime function to convert to a character String the value
of time stored in the variable of type time_t at the address
timer. Calling ctime is equivalent to the call asctime(localtime
(timer)).

Syntax
#include <time.h>
char *ctime(const time_t *timer);
const time_t *timer; Pointer to calendar time

Example Cali
printf("Current time = %s\n", ctime(&bintime));

Returas

The ctime function returns the pointer to the string containing a


formatted version of the date and time.

See Also
asctime, time

Example
See Example 16-1 at the of the chapter. Line 11 in that example
uses clime to convert an encoded time _t value to a string.

ditttime<

Purpose
Use the difftime function to compute the difference between
two time values, time2 and time1, both of type time _t.

Syntax
#include <time.h>
double difftime(time_t time2, time_t time);
time_t time2; Value of time from which time will be subtracted

time_t time; Value of time to be subtracted from time2

Example Call
seconds_used = difftime(oldtime, newtime);
218 ANSI C Data Processing

Returns
The difftime function returns the elapsed time, time2-time1/, in
seconds as a double-precision number.

See Also
clock, time

a gmtime

Purpose
Use the gmtime function to break down a time value of type
time __t stored at the location time into year, month, day, hour,
minutes, seconds, and several other fields that it saves in a struc-
ture of type tm, which is maintained internally. The structure tm
is defined in time.b and shown in asctime. The fields set up by
gmtime correspond to GMT.

Syntax
#include <time.h>
struct tm *gmtime(const time_t *time);
const time_t *time; Pointer to calendar time

¥ Example Call
t_gmt = gmtime(&bintime);

Returns

The gmtime function returns a pointer to the tm structure where


the converted time is stored. If GMT is not available, it returns a
NULL.

See Also

asctime, localtime, time

aa a TEE

> localtime

Purpose
Use the /ocaltime function to break down the value of time of
type time_t stored at the location time into year, month, day,
hour, minutes, seconds, and several other fields that it saves in a
structure of type ¢m, which is maintained internally. The struc-
ture ¢m is defined in time. and is shown in the reference pages

localtime
16—Time and Date Functions 219

on asctime. The fields set up by localtime correspond to the lo-


cal time.

Syntax
#include <time.h>
struct tm *localtime(const time_t *time);
const time_t *time; Pointer to stored calendar time

Example Call
t_local = localtime(&bintime);

Returns

The /ocaltime function returns a pointer to the tm structure


where the converted time is stored.

See Also

asctime, gmtime, time

Example
Line 14 in Example 16-2 uses /ocaltime to convert a time _t value
into its component parts.

mktime <4

Purpose
Use the mktime function to convert the local time in the struc-
ture of type tm at the address timeptr to a value of type time _t.
Essentially, the local time given in components of year, month,
day, and so on, is converted to number of seconds elapsed since
00:00:00 hours GMT, January 1, 1970. This is the same format in
which time returns the current time and is the format used in the
argument to the functions ctime, difftime, and localtime.
Two fields in the structure of type tm are ignored by
mktime. These are the tm_wday and tm_yday fields, denoting
the day of the week and the day of the year, respectively. The
mktime function sets the fields in the t7 structure to appropriate
values before returning.

Syntax
#include <time.h>
time_t mktime(struct tm *timeptr);
struct tm *timeptr; Pointer to structure of type tm where local time is
stored

Example Call
bintime = mktime(&timebuf) ;

mktime
220 ANSI C Data Processing

Returns

If successful, mktime returns the current contents of timeptr,


encoded as a value of type time_t. If the local time in timeptr
cannot be handled by mktime, the return value is a — 1 cast to the
type time _t.

See Also
asctime, time

Example
Example 16-2 uses mktime to implement a utility that prints the
date it will be any number of days from the current day.

> stritime

Purpose
Use the strftime function to format a time broken down to com-
ponents in a tm structure whose address is in timeptr into a
string whose address is provided in str. At most, maxsize charac-
ters are placed in the string. The formatting is done according to
codes, listed in Table 16-3, which are given in the string format_
string. The argument format_string is expected to be in mul-
* tibyte characters. Like sprintf, the formatting codes begin with a
% . Characters that do not begin with a % are copied unchanged
to str. The LC_ TIME category of the program’s locale affects the
behavior of strftime.

Syntax
#include <time.h>
size_t strftime(char *str, size_t maxsize, const char
*format_string,
const struct tm *timeptr);
char *str; Pointer to array of characters where result is placed

size_t maxsize; Maximum number of characters in st


const char *format_string; Formatting codes for converting the
time to a string

const struct tm *timeptr; Pointer to structure containing time


broken down to components

Example Call
/* Produce the standard output: Thu Jul 21 19:02:39 1988
strftime(s, 80, "%a %b %c\n", &tptr);/
16—Time and Date Functions 221

Table 16-3. Formatting Codes for strftime


Format Replaced by
Ste etc ee ee ee eee ens
ha Current locale’s abbreviated name for the weekday
~”A Current locale’s full name for the weekday
%b current locale’s abbreviated name for the month
%B current locale’s full name for the month
%eC date and time representation appropriate for the locale
%d day of the month as a decimal number (01-31)
%H hour in a 24-hour clock as a decimal number (00-23)
%l hour in a 12-hour clock as a decimal number (01-12)
%j day of the year as a decimal number (001-366)
%m month as a decimal number (01-12)
%M minute as a decimal number (00-59)
%P current locale’s AM/PM indicator
%~S second as a decimal number (00-60)
%*U week of the year as a decimal number (Sunday taken as the first day of a
week) (00-53)
%w weekday as a decimal number (Sunday is 0), (0-6)
%W week of the year as a decimal number (Monday taken as the first day of a
week) (00-53)
%X date representation for current locale
%X time representation for current locale
Ay year without the century as a decimal number (00-99)
*AY year with the century as a decimal number
%z name of time zone (or nothing, if time zone is unknown)
%% percent sign

Returns

The strtime function returns the total number of characters it


placed in str, including the terminating null character. If the
number of characters exceeds maxsize, strftime returns zero
and the contents of the array str are indeterminate.

See Also
asctime, ctime, gmtime, localtime, time

time<4

Purpose
Use the time function to get the current date and time (calendar
time) encoded as an implementation-dependent value of type

time
222 ANSI C Data Processing

time _t. If the pointer timeptr is not null, the encoded time is
copied to the location whose address is in timeptr.

Syntax
#include <time.h>
time_t time(time_t *timeptr); 3
time_t *timeptr; Pointer to variable where result is returned

Example Call
time(&bintime);

Returns

The time function returns the calendar time encoded in an im-


plementation-dependent manner.

See Also

ctime, gmtime, Localtime

Example
Line 7 in Example 16-1 and line 13 in Example 16-2 call time to
get the current calendar time in encoded form.
Example 16-1 This program prints the current date and
time.
* 1:#include <stdio.h>
2:#include <time.h>
3:main()
4:{
53 time_t tnow;
6:/* Get the time in encoded form */
(3 time(&tnow);
8:/* Convert the time to a string and print it. This
9: * will be your local time.
TORR #Y)
Aine printf("'Current time = %s\n"', ctime(&tnow));
eRe

Here is a sample output:


Current time = Sun Jul 24 16:50:47 1988
Example 16-2 The mktime function does not care if the
fields in the tm data structure are within the
valid range or not. In other words, you can
set the number of days since the first of the
month to 45 and mktime adjusts other fields
(such as making it the next month) to bring all
entries to valid ranges. In this example this
feature sets up a utility program that prints
the date a specified number of days from to-

time
16—Time and Date Functions 223

day. The program accepts as a command-line


argument the number of days to look ahead.
1:#include <stdio.h>
2:#include <time.h>
3:main(int argc, char **argv)
4:{
SR time_t tresult, tnow;
6: struct tm *tmnow;
is if Cargc<2)
8: {
9: printf("Usage: %s <number of days>\n'', argv(0]);
10: exit(0);
11: }
12:/* Get today's date and convert it to a "'tm'' structure */
WEI time (&tnow) ;
14: tmnow = localtime(&tnow) ;
15:/* Adjust the number of days */
16: tmnow->tm_mday += atoi(argv[1]);
17:/* Now call ''mktime" to set everything in tmnow */
18: if((tresult = mktime(tmnow)) == (time_t)-1)
19: {
20: printf('"'mktime failed\n");
744) }
22: else
23: {
24: printf('%d days from now it'll be %s\n",
(255 atoi(argv[1]), ctime(&tresult));
26: }
27:}

When run with 4 as the argument on Sun Jul 24 10:50:52


1988, the program produces the output:
4 days from now it‘Ll be Thu Jul 28 16:50:52 1988
f

' ai

Ta my
oh \ i.

7 ine) cay <6 Chi, BP


ite = thecth ime 3

Edsmiple van :

eae |
aattiivens hnteonat| vo9
Weivoe OA

‘i ~ boleg
ty Fhe ee ee
a s i J ji6 we Wire

:
BZ « ‘ a

" Va, & io FFTAS


ye pores A} Psi aia
sonic
are k
th :leets? = Teonthatn
eh
8
G vs Cneraplt kr ae
prrdcs: cumardcgl edt tinive
ta pean jinn
nie

“wifes ad \i"ad Wor mow” 35


* ti o atcha {RNY hoo sa rams $C
rie q had > 7 _

ahead a a

RSME bial, uaete agen


> clue sto
a a -9p0 erme
Mowe) SE20RGt. BS jut wd od ir tine
| an to 6 atch ait Gen ¥.)
“ils was 6 i? Ta
Je a
ie “tert oe. OF) sae
y ie
ey rte fe fant e \? : be ’

uf PS. yee U ‘y the ALS sa re . _ ==

nena RGN sek ad mets


trong’ he14ae tae, pedas.
Cit Fes vive 2 Print re “eat Me

ra prvel 45ye managing


are Gs tube a FONT
; io ¥ a Ai Wn ht a
iver Yer Bite Ai nily phe aen iy

ihe aes resting near g

te an i, ;
! See Exclamation points AND operators, 26-27
” See Double quotes Appending
# See Pound sign opening files for, 74
% See Percent sign of strings, 182-183, 202-203
& See Ampersands Arguments. See Parameters
” See Single quotes Arithmetic operators, 25-26
( ) See Parentheses Arrays, 18-19
* See Asterisks elements of, 26
+ See Plus sign memory allocation for, 130
, See Commas and pointers, 20
— See Minus sign sorting and searching of,
. See Periods 205-208
/ See Slashes strings as, 179-180
: See Colons ASCIIZ strings, 179
; See Semicolons Asctime function, 213-216
« See Less than sign Asin function, 152, 153, 155-156
= See Equal sign Assert function, 113-114
> See Greater than sign Assert. standard header file, 49
? See Question marks Assignment operators, 26-28
] See Square brackets Associativity of operators, 27-28
See Backslashes Asterisks (*)
* See Carets in format specifications, 91
— See Underscore for indirection, 26-27
{ } See Braces — for multiplication, 25, 27
| See Vertical bars Atan function, 152, 153, 156
~ See Tildes Atan2 function, 152, 153,
156-157
A Atexit function, 112-113, 115, 123
Atof function, 141-142
\a for alert, 10 Atoi function, 141, 143
A file access mode, 74 Atol function, 141, 143
%a format code for time, 221 Auto storage class, 23, 32-33
Abort function, 60, 112-114
Abs function, 152-155
Access modes, file, 74 B
Acos function, 152, 153, 155
Addition, 25, 27 \b for backspace, 10
Address operator, 19, 26-27 B file access mode, 74
Addresses and pointers, 19 %b format code for time, 221
Alert, escape sequence for, 10 Backslashes (\)
Ampersands (&) escape sequence for, 10
as address operator, 19, 26-27 for escape sequences, 9
in AND operators, 26-27 trigraph sequences for, 9
226 Essential Guide to ANSI C

Backspace, escape sequence for, Colons (:) with conditional oper-


10 ator, 27
Bases, number, 139 Command-line arguments, in cal-
Binary files and streams, 60 culator program, 146-147
functions for, 64 Command lines, parsing of, 184
opening of, 74 Commas (,) and sequential evalu-
Binary representation of data, ation, 27
139-140 Comparison of strings and buf-
Binary searches, 207-208 fers, functions for, 182-183
Bitwise operators, 26-27 Compilers and compilation, 10,
Blocks 13-14
memory, allocation of, 129-131 Complements, bitwise, 26
program, 28 Compound assignment opera-
Body of functions, 8 tors, 26
Braces ({ }) Concatenation of strings,
for blocks, 28 182-183, 202-203
trigraph sequences for, 9 Conditional compilation, 13-14
Break statement, 28, 33, 45 Conditional operator, 27
Bsearch function, 207-209 Const modifier, 23-24, 34-35
Buffers Continue statements, 28, 35
flushing of, 112-113 Control-C, program to handle,
functions for, 65 123-124
manipulation of, 179-185 Conversions
with stream I/O, 60-62 of characters, 173-178
BUFSIZ constant, 50, 63 of coordinates, 153
of data, 139-142
with time, 214
Cc Coordinates, functions to con-
Vert, 1535
%c format code
Coprocessors, math, 140
for I/O, 86, 91
Copying of strings and buffers,
for time, 221
functions for, 182—183, 185
Calculator program, hexadecimal, Cos function, 152, 158
147
Cosh function, 152, 158-159
¥
Calloc function, 43, 130, 132
Country-dependent formats, 10,
Carets (‘)
111-113
for exclusive OR operator,
26-27.
Creation of files, functions for, 64
Ctime function, 213-215, 217
with scanf, 91
Ctype.h standard header file, 49,
trigraph sequences for, 9
Carriage return
17S
escape sequence for, 10
D
in text streams, 59-60
Case statement, 34, 44-45 %d format code
Ceil function, 152, 153, 157 for I/O, 66, 86, 91
Char data type and characters, for time, 221
Data access operators, 26
classification and conversion Data types, 17-18
of, 142, 173-178 conversions of, 139-142
format specifications for, 86, internal representation of,
91 139-140
1/O functions for, 64-65 user-defined, 21
loading of, into memory, 182 Date
multibyte, 9-10, 180-182, 184 functions for, 213-215
nonprintable, 9 macros for, 15
wide, 9, 180-182, 184 =. DAT EAS macrowls
See also Strings DBL_DIG constant, 50
CHAR_ BIT constant, 50 DBL_ EPSILON constant, 50
CHAR_MAX constant, 50 DBL_MANT_DIG constant, 50
CHAR_MIN constant, 50 DBL_ MAX constant, 50
Classification, character, 173-178 DBL_MAX_ 10_EXP constant,
Clearerr function, 63, 69 50
CLK_TCK constant, 50, 215 DBL_MAX_ EXP constant, 50
Clock function, 213, 215-216 DBL_MIN constant, 50
Clock_t data type, 54 DBL_MIN_ 10_EXP constant,
Closing of files, function for, 64 50
Index 227

DBL_MIN_EXP constant, 50 Exclamation points (!)—cont


Decimal points and locale, 112 in trigraph sequences, 9
Declarations, 17-21 Exclusive OR operator, 26-27
of functions, 8, 24-25 Executable character sets, 173,
of strings, 179-180 181
of variables, 8 Exit function, 25, 112-113,
Decrement operation, 25 115-116
Default statement, 35, 45 EXIT_FAILURE status code, 51
#define directive, 8, 14 EXIT _SUCCESS status code, 51
Definitions for functions, 30-32 Exp function, 152, 153, 159-160
Deletion of files, function for, 64 Exponents, 149-151, 162
Difftime function, 213, 215, Expressions, 8, 27-28
217-218 Extern variables and declarations,
Dimensions, array, 19 8, 23, 37-38
Directives, preprocessor, 8, 11-14
Disk files, buffers for, 60
Display, standard stream for, 62 i@
Division and div function, 25,
1525 15624159 \f for form feed, 10
Div_t data structure, 54 %f format code for 1/O, 66-67,
Do-while loops, 28, 33, 35-36 86, 91
Domain errors, 151 Fabs function, 152, 153, 160
Double data type and double-pre- Fclose function, 63, 69-70
cision numbers, 17-18, 36, Feof function, 63, 70-71
149, 151 Ferror function, 63, 71
formatted I/O of, 66-67, 86, 91 Fflush function, 63, 71-72
Double quotes (”), escape se- Fgetc function, 63, 72
quence for, 10 Fgetpos function, 63, 73
Dynamic allocation of memory, Fgets function, 63, 73-74
19-20 FILE data type, 51
HL macro n5
19 ee pointers to, 60,
2
%e format code for I/O, 86, 91 ee constant, 51,
EDOM constant, 51, 151 3
Elapsed time, functions for, 214 Files, 59-62
Elements, array, 26 Sprintf for, 66
#elif directive, 13-14 inclusion of, 8, 11-12, 15
#else directive, 13-14 I/O for, 62-67, 99-104
Else statement, 36-37, 39 standard header, 49-50
#endif directive, 13-14 Flags field in format specifica-
Engineering notation, 149 tions, 85
Enum data type, 18, 37 Float data type and floating-point
Environments and processes, numbers, 38
109, 113 format specifications for, 66,
EOF constant, 51, 63 86, 91
Equal sign (=) IEEE format for, 17, 139,
as assignment operator, 26-28 149-151
in relational operators, 26-27 math operations for, 149-151
in trigraph sequences, 9 Float.b standard header file, 18,
ERANGE constant, 51, 151 49, 151
Errno variable, 54, 151 Floor function, 152, 153, 160-161
Errno.h standard header file, 49, FLT __DIG constant, 51
151 FLT __EPSILON constant, 51
Error conditions FLT_MANT_DIG constant, 51
functions for, 65, 113 FLT _MAX constant, 51
handling of, 110-111, 123-124 FLT __MAX_ 10__EXP constant, 51
in math functions, 151 FLT_MAX_ EXP constant, 51
messages for, 62, 104-105, 182 FLT _MIN constant, 51
signals for, 109-110 FLT __MIN_ 10__EXP constant, 51
#error directive, 14 FLT __MIN_EXP constant, 51
Escape sequences, 9—10 FLT __RADIX constant, 51
Exceptions, signals for, 109-110 FLT __ROUNDS constant, 51
Exclamation points (!) Flushing of buffers, 60, 65,
in relational and logical opera- 112-113
tors, 26-27 Fmod function, 152, 161
228 Essential Guide to ANSI C

Fopen function, 60, 62-63, Hoare, C. A. R., quicksort routine


74-75 by, 207
FOPEN_MAX constant, 52, 63 Horizontal tab, escape sequence
For loops, 29, 33, 39 for, 10
Form feed, escape sequence for, HUGE_ VAL constant, 52, 151
0 Hyperbolic functions, 154
Formattin:
of I/O, 62, 64-67, 85-87,
90-92 % i format code
of time, 220 ‘ for I/O, 86, 91
Fpos_t data type, 5 for time, 221
Fprintf function, 63, 65-66, IEEE (Institute of Electrical and
75-76 Electronic Engineers), float-
Fputc function, 63, 76 ing-point format of, 17, 139,
Fputs function, 63, 76-77 149-151
Fread function, 62-63, 77-78, #if directive, 13-14
101-104 If statements, 29, 36, 39-40
Free function, 130-133 #ifdef directive, 12-14
Freopen function, 63, 78 #ifndef directive, 13, 15
Frexp function, 152, 162 #include directive, 8, 11-12, 15
Fscanf function, 63, 65, 67, 79 Increment operation, 25
Fseek function, 63, 79-80 Indices, array, 19
Fsetpos function, 63, 80-81 Indirection, 26
Ftell function, 63, 81 {nt data type and integers, 17-18,
Functions 40
declarations of, 8, 17, 24-25 arithmetic with, 153
definitions for, 30-32 conversions with, 142
external, 37 format specifications for, 86,
math, 149-154
91
parentheses for, 27 Internal representation of data,
pointers to, 31-32 139-140
and static qualifier, 43 Internationalization, 10, 111-113
Fuwrite function, 62-63, 81-82, INT _MAX constant, 52
¥
101-104
INT_MIN constant, 52
_IOFBF constant, 52
G _IOLBF constant, 52
%g format code for I/O, 86, 91 _IONBEF constant, 52
Getc function, 64, 82-83 Isalnum function, 173-175
Getchar function, 25, 64, 83 Isalpba function, 173, 175
Getenv function, 109, 113, 116 Iscntri function, 173, 175
Gets function, 64, 83-84 Isdigit function, 173, 175
Global declarations and variables, Isgrapb function, 173, 175
8, 22, 62-63 Islower function, 173, 175
Gmtime function, 213-214, 218 Isprint function, 173, 175
Goto statement, 29, 39 Ispunct function, 173, 176
Greater than sign ()) Isspace function, 173, 176
in arrow operator (-)), 26-27 Isupper function, 173, 176
as relational operator, 26-27 Isxdigit function, 174, 176
as shift operator ())), 26-27
in trigraph sequences, 9 J
Greenwich Mean Time, function %j format code for time, 221
for, 214 Jmp _buf array data type, 54, 110
Jumps
H with goto, 29, 39
nonlocal, 110-111, 113
%h format code
Justification with printf, 85
for 1/O, 85, 91
for time, 221
K
Header files, standard, 49-50
Hexadecimal numbers, 139 Keyboards
calculator program for, inputting characters from, 9
146-147 standard stream for, 62
escape sequence for, 10 Keys for sorting, 206
format specifications for, 86, Keywords, 32
92 K&R standard, 4, 10
Index 229

L Loops
and continue, 35
L qualifier in format specifica- do-while, 28, 33, 35-36
tions, 67, 85, 91 for, 29, 33, 39
Labels while, 30, 33, 35, 48
with goto, 29 Lowercase, conversion of charac-
with switch, 34-35, 44-45 ters to, 174
Labs function, 152, 153, 162-163 L_tmpnam constant, 52, 63
LC_ALL constant, 52, 112
LC_COLLATE constant, 52, 112, M
183 %m format code for time, 221
ee constant, 52, 112, Macros
18 in #include directives, 12
LC_MONETARY constant, 52, library, 50-55
112 predefined, 15
LC_NUMERIC constant, 52, 112 processing of, 12-13
Lconv structure, 54, 112, 117 variable argument, 125-128
LC_TIME constant, 52, 112 Main function, 8, 30
LDBL_ DIG constant, 52 Malloc function, 25, 130, 133
LDBL_ EPSILON constant, 52 Mantissas in floating-point num-
LDBL_MANT_DIG constant, 52 bers, 149-151, 162
LDBL_ MAX constant, 52 Math coprocessors, 140
LDBL_MAX_ 10_ EXP constant, Math functions, 149-154
52 Math.h standard header file, 49,
LDBL_MAX_ EXP constant, 52 151
LDBL_MIN constant, 52 Matrices, 19
LDBL_MIN_ 10_EXP constant, MB_CUR_MAX constant, 53
53 Mblen function, 181, 183, 185
LDBL_MIN_
EXP constant, 53 MB_LEN_
MAX constant, 53
Ldexp function, 152, 163 Mbstowcs function, 181, 184,
Ldiv function, 152, 153, 163-164 186-187
Ldiv_t data structure, 54, 163 Mbtowc function, 181, 184, 186
Length of strings, functions for, Members of structures, 21, 26
182-183 Memcbr function, 181, 187
Less than sign (<) Memcmp function, 181, 183, 188
as relational operator, 26-27 Memcpy function, 181, 183,
as shift operator (<<), 26-27 188-189
in trigraph sequences, 9 Memmove function, 181, 183, 189
Lexicographic ordering, 180 Memory allocation, 8, 17,
Library, standard, 49-55 129-131
Lifetime of variables, 17, 22-25 dynamic, 19-20
Limits.b standard header file, 18, for strings, 185
49 Memset function, 181, 189-190
#line directive, 15 Microsoft C 5.1, 10
Line 1/O, functions for, 64 Minus sign (—)
_ _LINE_ _ macro, 15 in arrow operator (—)), 26-27
Local declarations and variables, for decrement operation (—),
Se 25252 Ze
Locale of programs, 111-113 for left justification, 85
Localeconv function, 112-113, for negation, 26-27
116-118 for subtraction, 25, 27
Locale.b standard header file, 49, in trigraph sequences, 9
111, 117 Mktime function, 213-214,
Localtime function, 213-214, 219-220, 222-223
218-219 Modf function, 152, 164-165
Log function, 152, 153, 164 Modularity and file inclusion, 11
Log10 function, 152, 153, 164 Modulo operation, 25
Logical operators, 26-27 Monetary formatting and /o-
Long qualifier, 17-18, 40-41, 66, caleconv, 112
85, 91 Multibranching with switch,
conversions with, 142 44-45
Longjmp function, 113, 118, Multibyte characters, 9-10,
123-124 180-182, 184
LONG
_ MAX constant, 53 Multidimensional arrays, 19
LONG _MIN constant, 53 Multiplication, 25, 27
230 Essential Guide to ANSI C

N Plus sign (+)—cont


for addition, 25, 27
%n format code for I/O, 86, 92 in file access modes, 74
\n for newline character, 9-10 in format specifications, 85
Natural logarithms, 153, 154 for increment operation (++),
NDEBUG and assert, 53 Dye 2H,
Negation, 26 for unary plus, 26-27
Newline character Pointers, 19-20
escape sequence for, 9-10 to FILE structures, 60, 62 —
in text streams, 59-60 format specifications for, 86,
Nonlocal jumps, 110-111, 113
92
Nonprintable characters, escape to functions, 31-32
sequences for, 9
for memory allocation,
Normalization of floating-point 130-131, 134
numbers, 150
returning of, 31
NOT operator, 26 and sorting, 205-206
Null characters for strings, 19, and strings, 180
179, 185 void, 47
NULL constant, 53, 63 Polar coordinates, conversion
Null statements, 29 functions for, 153
Portability, 7, 10
O Pound sign (#)
%o format code for I/O, 86, 92 in format specifications, 85
Octal numbers, 139 for preprocessor directives, 11
escape sequence for, 10 with string-izing operators, 13
format specifications for, 86, trigraph sequences for, 9
92 Pow function, 152, 154, 165
Offsetof macro, 54 #pragma directive, 14-15
Opening of files Precedence of operators, 27-28
access modes for, 74 Precision, 149-151
functions for, 64 with formatted I/O, 66, 85
Operating system commands, ex- Predefined macros, 15
¥ ecution of, 112-113 Preprocessor directives, 8, 11-14
Operators, 25-27 Printf function, 64-66, 84-87
precedence of, 27-28 Processes, control functions for,
string-izing, 13 109-113
token-pasting, 12-14 Programs
Optimization and volatile modi- locale of, 111-113
fier, 47 and processes, 109
OR operators, 26-27 structure of, 7-9
Overflow with unsigned data Prototype functions, 24
types, 46 Pseudorandom numbers,
153-154
P Ptrdiff__t data type, 54
%p format code Putc function, 64, 87-88
for I/O, 86, 92 Putchar function, 64, 87-88
for time, 221 Puts function, 64, 88
Parameters, 30
function, 24-25 Q
for macros, 12 Qsort function, 207, 210-212
variable, 125-128 Question marks (?)
Parentheses( ) with conditional operator, 27
as function operator, 27, 30 escape sequence for, 10
for macros, 12
in trigraph sequences, 9
in trigraph sequences, 9 Quicksort routine, 207-208
with type casting, 27
Parsing of command lines, 184
Percent sign (%) R
for format specifications, 66, \r for carriage return, 10
84, 91 R file access mode, 74
for modulo operation, 25, 27 Radixes, 139, 145
Periods (.) as member operators, Raise function, 110, 113, 119
26=27 Rand function, 152, 153, 166,
Perror function, 113, 118-119 170-171
Plus sign (+) RAND _MAX constant, 53, 153
Index 231

Random numbers, 153-154, SIGTERM signal, 54, 110


170-171 Sin function, 152, 153, 166-167
Range errors, 151 Single-precision numbers, 38,
Readability 149, 151
and macros, 12 Single quotes (’)
and typedef, 31 escape sequence for, 10
Reading of files in trigraph sequences, 9
functions for, 64 Sinh function, 152, 167
opening for, 74 Size field in format specifica-
Realloc function, 130-131, tions, 85, 91
133-135 Sizeof operator, 25-27, 42-43,
Rectangular coordinates, conver- 130
sion functions for, 153 Size __t data type, 25, 54
Register variables, 23, 41 Slashes (/) for division, 25, 27
Relational operators, 26-27 Sorting, 205-208
Remove function, 64, 89 Source character sets, 173,
Rename function, 64, 89 180-181 .
Return statement and types, 29, Spaces in format specifications,
30-31, 41 85
Rewind function, 64, 90 Sprintf function, 64-66, 94, 142
Sqrt function, 152, 153, 167-168
S Square brackets ([ ])
%s format code for array elements, 26-27
for I/O, 66,92 * with scanf, 91
for time, 221 trigraph sequences for, 9
Scanf function, 64-65, 67, 90-92 Srand function, 152, 153, 168,
SCHAR_ MAX constant, 53 170-171
SCHAR_MIN constant, 53 Sscanf function, 64-65, 67,
Scientific notation, 149 94-95, 142
Scope of variables, 22-25 Standard header files, 49-50
Searching, 182, 205-208 Statements, 8, 28-30
Seeds for random numbers, 153 Static qualifier, 22, 31, 43-44
SEEK__CUR constant, 53, 79 Stdarg.b standard header file, 50,
SEEK __END constant, 53, 79 125
SEEK _SET constant, 53, 79 SSD Came. Macro. lo
Semicolons (;) with statements, Stddef.h standard header file, 50
28-29 Stderr stream, 54, 62, 104-105
Sequential evaluation, 27 Stdin stream, 54, 62, 90
Setbuf function, 64, 92-93 Stdio.h standard header file, 11
Setjmp function, 113, 120, Stdlib.h standard header file, 50,
123-124 109, 139, 151, 181
Setjmp.h standard header file, 50, Stdout stream, 55, 62, 66, 84
110 Streat function, 181, 183, 190,
Setlocale function, 111, 113, 202-203
120-121 Strchr function, 181, 191
Setvbuf function, 64, 93-94 Strcemp function, 181, 183,
Shift operators, 26-27 191-192
Short qualifier, 17-18, 42, 85, 91 Strcoll function, 112, 181, 183,
SHRT_MAX constant, 53 192
SHRT_ MIN constant, 53 Strepy function, 182, 183,
SIGABRT signal, 53, 110 192-193
Sig__atomic_t data type, 54 Strcespn function, 182, 184, 193
SIG __DFL constant, 53, 110, 121 Streams, 59-62, 62-67
SIG __ERR constant, 53, 122 Strerror function, 182, 194
SIGFPE signal, 53, 110 Strftime function, 112, 213, 220
SIG_IGN constant, 53, 110, 121 String. standard header file, 50,
SIGILL signal, 53, 110 181
SIGINT signal, 53-54, 110, 123: Strings, 19
Sign bits in floating-point num- conversion of, to numbers, 142
bers, 150-151 conversion of, to time, 214
Signal function, 113, 121-122 I/O of, 65
Signal.h standard header file, 50 manipulation of, 179-185,
Signals, 109-110, 113 202-204
Signed qualifiers, 42 nonprintable characters in, 9
SIGSEGV signal, 54, 110 operator for, 13-14
232 Essential Guide to ANS! C

Strings—cont TurboiG 55, 10


preprocessor replacement Of, Two-dimensional arrays, 19
12-13 Type casting, 27
sprintf for, 66 Typedef statement, 21, 31, 45
Strien function, 182-183, 185,
194-195 U
Strncat function, 182-183, 195
%u format code
Strncmp function, 182-183, for I/O, 86, 92
195-196 for time, 221
Strnepy function, 182-183, 185,
CHAR_MAX constant, 54
196-197 INT_ MAX constant, 54
Strpbrk function, 182, 184, 197,
LONG _ MAX constant, 54
203 = nary operators, 26-27
Strrcbr function, 182, 184, undef directive, 14-15
197-198
c nderscore (_) for macros, 15
Crs.
eee
Strspn function, 182, 184, 198
Ungetc function, 64, 96-97
Strstr function, 182, 184, 199
Union and unions, 21, 46
Strtod function, 141, 144
UNIX library, 10
Strtok function, 182, 184,
Unsigned qualifier, 17-18, 46, 66,
199-200
86, 142
Strtol function, 141, 145-146
Uppercase, conversion of charac-
Strtoul function, 141, 146-147
ters to, 174
Struct and structures, 20-21, 31,
User-defined data types, 21
44
USHRT_MAX constant, 54
Structure of C programs, 7-9
Strxfrm function, 112, 182-183,
Vv
200-201
Subtraction, 25 \v for vertical tab, 10
Switch statement, 29-30, 33-35, Va __arg macro, 125-128
44-45 Va_end macro, 125-128
System function, 112-113, 122 Va_list data type, 55
Variable arguments, 125-128
T Variables
and blocks, 28
At for horizontal tab, 10
const and volatile modifiers
Tabs, escape sequence for, 10
for, 23-24, 34, 47
Tan function, 152, 153, 168-169
declarations of, 8, 17
Tanh function, 152, 169
environment, 109
Temporary files, functions for, 65
external, 37
Termination of processes,
register, 41
112-113
Text streams, 59-60 scope and lifetime of, 22-25
Va __start macro, 125-128
Tildes (~)
Vertical bars (|)
for bitwise complements,
26-27 for OR operators, 26-27
trigraph sequences for, 9 trigraph sequence for, 9
Time function, 153, 213-214, Vertical tab, escape sequence for,
221-223
10
— SIME Macro, 15 Vfprintf function, 64, 97
Time.h standard header file, 50, Visibility of variables, 17, 22-25
214 Void data type, 24-25, 47
Time __t data type, 55, 214 Volatile modifier, 23-24, 47
Tm structure, 55, 214 Vprintf function, 64, 98
Tmpfile function, 64, 95 Vsprintf function, 64, 66, 98-99
TMP_MAX constant, 54, 63
Tmpnam function, 64, 96 Ww
Tokens W file access mode, 74
functions to extract, 182, 184, %w format code for time, 221
204 Wchar_t data type, 9, 55, 181,
operators for, 12-14 201
replacement of, 12-13 Wcstombs function, 182, 184,
Tolower function, 174, 176-177 201-202
Toupper function, 174, 177-178 Wctomb function, 182, 184, 201
Trigonometric functions, While loops, 30, 33, 35, 48
153-154, 169-170 Whitespace in data conversions,
Trigraph sequences, 9 144-145
Index 233

Wide characters, 9, 180-182, 184 X with strtol, 145


Width field in format specifica-
tions, 85, 91 NG
Writing to files
functions for, 64 %y format code for time, 221
opening for, 74
1
x %z format code for time, 221
Zeroes
%x format code
for I/O, 86, 92 in format specifications, 85
for octal numbers, 145
for time, 221
\x for hexadecimal digits, 10
The Waite Group’s The Waite Group’s
Microsoft® C Programming Turbo C® Programming for
for the IBM® the IBM®
Robert Lafore, The Waite Group Robert Lafore, The Waite Group
Programmers using the Microsoft C This entry-level text teaches read-
compiler can learn to write useful ers the C language while also
and marketable programs with this helping them write useful and
entry level book on Microsoft C marketable programs for the IBM
programming. PC, XT, AT, and PC/2.
This title is a tutorial geared specifi-
This tutorial is based on :
Borland’s new Turbo C compiler
cally to the IBM PC family of com- with its powerful integrated en-
puters. Unlike other introductory C vironment that makes it easy to
titles, it is written for the Microsoft C edit, compile, and run C pro-
compiler. It provides special coverage grams. The author's proven
of IBM features such as sound, color hands-on intensive approach
graphics including CGA and EGA, includes example programs, exer-
keyboard, telecommunications, and cises, and questions and answers
character graphics. and cover CGA and EGA graphic
modes.
Topics covered include: Topics covered include:
@ Getting Started @ C Building Blocks
@ Building Blocks @ Loops
®@ Loops @ Decisions
@ Decisions @ Functions
@ Functions @ Arrays and Strings
@ Arrays and Strings @ Pointers
@ Pointers @ Keyboard and Cursor
@ Structures, Unions, and ROM
@ Keyboard and Cursor
BIOS
@ Structures, Unions, and ROM @ Memory and the Character
BIOS. Display
@ Memory and the Monochrome @ CGA and EGA Color Graphics
Display @ Files
@ CGA and EGA Color Graphics @ Larger Programs
@ Files Preprocessor @ Advanced Variables
@ Serial Ports and Telecommuni- @ Appendices: References,
cations Hexadecimal Numbering, Bib-
liography, ASCII Chart, and
@ Larger Programs Answers to Questions
640 Pages, 742 x 934, Softbound
608 Pages, 74 x 954, Softbound
ISBN: 0-672-22515-8
ISBN: 0-672-22614-6
No. 22515, $24.95 No. 22614, $22.95
Visit your local book retailer, use the order form
provided, or call 800-428-SAMS.
Programming in C, Programming in ANSI C
Revised Edition Stephen G. Kochan
Stephen G. Kochan
This comprehensive tutorial assumes
This timely revision provides com- no previous exposure to the C
plete coverage of the C language, language. It teaches programmers, sys-
including language features and over tems analysts, and students, how to
90 program examples. The compre- write, compile, and execute C pro-
hensive tutorial approach teaches the grams and how to write applications.
beginner how to write, compile, and
The book provides a complete intro-
execute programs and teaches the
duction to ANSI standard C and con-
experienced programmer how to write
tains over 90 program examples with
applications using features unique to
step-by-step explanations of each
procedure. Written in a clear, in-
Topics covered include: structive style with end-of-chapter
@ Introduction and Fundamentals exercises, it is ideal for self-study or
@ Writing a Program in C classroom use.
® Variables, Constants, Data Topics covered include:
Types, and Arithmetic Expressions @ Some Fundamentals
@ Program Looping @ Writing a Program in ANSI C
®@ Making Decisions @ Variables, Data Types, and Arith-
@ Arrays metic Expressions
@ Functions @ Program Looping
@ Structures @ Making Decisions
@ Character Strings @ Arrays, Functions, and Structures
@ Pointers @ Character Strings and Pointers
@ Operations on Bits @ Operations on Bits
@ The Preprocessor @ The Preprocessor
@ Working with Larger Programs @ More on Data Types
@ Input and Output @ Working with Larger Programs
@ Appendices: Language Summary, @ Input and Output
ANSI Standard C, Common @ Miscellaneous Features and Topics
Programming Mistakes, the UNIX
C Library, Compiling Programs 450 Pages, 7% x 9%, Softbound
Under UNIX, the Program LINT, ISBN: 0-672-48408-0
the ASCII Character Set No. 48408, $24.95

476 Pages, 7% x 9%, Softbound


ISBN: 0-672-48420-X
No. 48420, $24.95

Visit your local book retailer, use the order form


provided, or call 800-428-SAMS.
Advanced C Tips and Portability and the C
Techniques Language
Paul Anderson and Gail Anderson Rex Jaeschke
This in-depth book on C looks at Portability, the feature that distin-
portability, execution efficiency, and guishes C from other programming
programming application techniques. languages, is thorough defined and
Examples and techniques are portable explained in this definitive reference
across today’s popular operating sys- work. The book primarily addresses
tems, making it appropriate for the technical issues of designing and
professional programmers, applica- writing C programs that are to be
tions developers, systems level compiled across a diverse number of
engineers, and programming students. hardware and operating system
Entire chapters are devoted to special environments.
areas of C such as debugging tech- Organized around the ANSI C Stand-
niques, C’s run-time environment, and ard, it explains the C preprocessor
arrays and pointers. and the run-time library and tackles
portability from a C language perspec-
Topics covered include:
tive, discussing implementation-
@ C Refresher specific issues as they arise.
@ The Run-Time Environment
Topics covered include:
@ An Array of Choices
“A Closer Look at C @ Introduction and Overview
@ C Debugging Techniques @ The Environment
@ The Source Code for a Memory @ Conversions, Expressions,
Object Allocator Declarations, and Statements
@ New ANSI C Features @ The Preprocessor
@ Appendices: Standard C Under @ Diagnostics, Character Handling,
UNIX System V, Microsoft C Un- Errors
der DOS, Microport System @ Numerical Limits and Localization
V/ATC, Microsoft C Under XENIX, @ Mathematics, Non-Local Jumps,
Turbo C Under DOS Signal Handling
325 Pages, 742 x 954, Softbound
@ Variable Arguments and Common
ISBN: 0-672-48417-X Definitions
No. 48417, $24.95 @ Input/Output, General Utilities,
String Handling
@ Date and Time
400 Pages, 7% x 9%, Softbound
ISBN: 0-672-48428-5
No. 48428, $24.95

Visit your local book retailer or call


800-428-SAMS.
C++ Programming Guide The Waite Group’s
for the IBM Turbo C Bible
John Berry and Mitchell Waite, Naba Barkakati
The Waite Group
Clear and well-written tutorials point
This new guide and tutorial is aimed out the different purposes and
at developers and intermediate-level appropriate uses of each Turbo C
students who already know the C function to make programming more
language. It teaches the use of object- organized, complete, and powerful.
oriented programming skills and The library routines are organized
introduces the major features of the into functional categories with expla-
C++ language with explanations fol- nations that include the purpose, syn-
lowed by practical examples that will tax, example call, includes, common
work on both UNIX and MS-DOS uses, returns, comments, cautions and
systems. pitfalls, and cross-reference for that
The book includes quizzes, exercises, function.
and key words and is ideal for self Topics covered include:
study or as a complete course. @ Overview of the C Language
Topics covered include: @ Turbo C 1.0 Compiler Features
@ Process Control
@ How the C++ Translator @ Variable-Length Argument Lists
Works @ Memory Allocation and
@ New Structure Operators and Management
Data Types @ Buffer Manipulation
@ Input and Output Message @ Data Conversion Routines
Streams in C+ + @ Math Routines
® Pointers and Reference @ Character Classification and
@ Classes and Inheritance Conversion
@ Function and Operator Over- @ String Comparison and Manipu-
loading lation
B® In-line Functions @ Searching and Sorting
@ All About C+ + Pointers
@ Time Routines
® Private and Public Structures @ File and Directory Manipulation
@ The Operator Function @ Input and Output Routines
@ Derived Classes @ System Calls
400 Pages, 7'2 x 954, Softbound @ Graphics Modes
ISBN: 0-672-22619-7 @ Drawing and Animation
No. 22619, $24.95 ® Combining Graphics and Text
950 Pages, 7% x 9%, Softbound
ISBN: 0-672-22631-6
No. 22631, $24.95
Visit your local book retailer or call
800-428-SAMS.
ie ees) Sh a
a : a alate’

‘ie 4 LA “Ry
a -

, ae ee oe a
(a0 a Soh
i
= i Hot BA

, : cen TT} he #3 ; ee z>fren $f =


OS |det lata senaaeiadie me 7 2a ar (habaise5hiParigmeipra
+ ie De ey tee koeet ee epee. se
Ee * to toad te me Doe 5 rpms
oe a ee Lad one aee ele
’ a Me hy hor Saas Algae gene pega ees! «
A — ih Soe, nD \ ko Scat:- spy enn 4 aa

Fi. OHS 1cesinnulie. dae wom


i" , Jed se MORGANS get bind » Fal he shad %

: Ae . Ss t ue cht &:¢- TP te
. 5 ‘ - "°

é ; even aE :
: ‘wae
oP ae j pa
|| 7 wee
py
|
?
2. r
; i
4 ¥

+ re

4 ©
hi ~ \s
by nil
. =,

wo ee
‘ - 7
™~
s mt
>
4
seit :
. . ’ j |
ee a
i "
= 1
4 F " 4

1 ie FF

tok fre 4 t j
~
4 i 4 ‘e 2
“ ie
& ~x j


‘ '

|: rs
. .

‘ 7 i
¥ i]

. 2-% }
i) Balerea a oe i e
Man. aera
= (APA sy WSs +0!
ANSi € Library Routines by Subject

Keywords eye 87 Math strchr, 197


puts, stremp, 191
auto, 32 remove, 89 abs, 154 streoll, 192
break, 33 acos, 155
rename, 89 se strcpy, ‘ 192
case, 34 ;
rewind, 90
asin, 155 ‘
strespn, 193
char, 34 atan, 156 :
scanf, 90 Strerror, 194
const,; 34 setbuf, 92 atan2, 156 :
: strlen, 194
continue, 35 ceil, 157 é
setvbuf, 93 strncat, 195
default, 35 intt. 94 cos, 158
do. 35 sprintf, cosh. $58 strncmp, 195
: sscanf, 94 i strncpy, 196
double, 36 3 div, 159
alse. 36 tmpfile, 95 159 strpbrk, 197
enum, 37
tmpnam, 96 oe
fabs, 160
strrchr, 197
ungetc, 96 strspn, 198
extern, 37 : floor, 160
float. 38 viprintf, 97 fmod. 161 strstr, 199
ne 39 vprintf, 98 f y 162 strtok, 7199
i vsprintf, 98 dias strxfrm, 200
goto, 39 labs, 162 wetomb. 201
if, 39 Idexp, 163 b 201
int, 40
- int, Process Control Idiv, , 163 pe each
long, 40 log, 164
register, 47 abort, 114 log10, 164 Search and Sort
return, 47 assert, 174 modf, 164
_ Short, 42 atexit, 115 pow, 165 bsearch, 209
signed, 42 exit, 115 rand, 166 qsort, 210
sizeof, 42 getenv, 716 sin, 166
static, 43 localeconv, 116 sinh, 167 :
struct, 44 longjmp, 7118 sqrt, 167 Time
switch, 44 perror, 178 srand, 168 cctune 215
typedef, 45 raise, 119 tan, 168 a 316
union, 46 setimp, 120 tanh, 169 pias 217
unsigned, 46 setlocale, 120 difftime 217
void, 47 signal, 127 mitine 278
volatile, 47 system, 122 Character g Aig
while. 48 Classification and —_ocaltime,
, Conversion phd os
: stritime,
; : Variable Arguments isalnum, 174 time, 221
Files and I/ va_arg, 126 isalpha, 175
clearerr, 69 va_end, 126 iscntrl, 175
fclose, 69 va_start, 126 — ‘sdigit, 175
feof, 70 isgraph, 175
ferror. 71 islower, 175
fflush, 77 ‘Memory Allocation sprint, pa
ispunct,
te 73
fgetpos, calloc, 132 isspace,
pose, 175
fgets, 73 free, 132 isupper, 175
fopen, 74 malloc, 133 isxdigit, 175
fprintf, 75 realloc, 133 tolower, 176
fputc, 76 toupper, 177

(puts, 76 Data Conversion


ose String and Buffer
freopen, 78 atof, 142 Masivietion
fscanf, 79 atoi, 143
fseek, 79 atol, 143 mblen, 185
fsetpos, 80 strtod, 144 mbstowcs, 186
ftell, 87 strtol, 145 mbtowc, 186
fwrite, 87 strtoul, 146 memchr, 187
getc, 82 memcmp, 188
getchar, 83 memcpy, 788
gets, 83 memmove, 189
printf, 84 memset, 789
putc, 87 strcat, 190
HOWARD W. SAMS & COMPANY
Essential Guide Series

The Waite Group's


Essential Guide to
ANSI C
Write portable C code that conforms to the new ANSI standard with this ac-
cessible guide which organizes and simplifies the standard’s 146 functions.
The library routines are grouped into four functional categories introduced by
intermediate-level tutorials. Function reference pages follow, presenting pur-
pose, syntax, example call, includes, common uses, returns, comments, cau-
tions and pitfalls, cross-references to related functions, and debugged ex-
amples.
A complete index, plus lists of functions organized alphabetically and by sub-
ject, make the function you are seeking just a page-flip away. The perfect
computerside reference, the Essential Guide
® Details all ANSI functions, including those common to commercial
compilers, such as Microsoft® C versions 3.0, 4.0, 5.1, Microsoft Quickc™
1.5, Borland Turbo C® 2.0, and the UNIX® System V compilers
© Covers most recent ANSI features: const, volatile, void, prototypes,
trigraphs, unary plus, wchar_t, enum, and more
*
© Reveals new areas of C covered by the ANSI standard: new data types
(long double), token pasting, string-izing
¢ Offers succinct tutorials that point out the purposes and appropriate uses
of ANSI C functions to make your programming more organized and
portable
Turbo C Programmers: Be sure to see The Waite Group's Essential Guide to Tur-
bo C which details Turbo C versions 1.0, 1.5, and 2.0.
Microsoft C Programmers: Be sure to see The Waite Group’s Essential Guide to
Microsoft C which details Microsoft C 5.1.
The Waite Group is a developer of computer, science, and technology books.
Acknowledged as a leader in its field, The Waite Group creates book ideas,
finds authors, and provides development support throughout the book cycle,
including editing, reviewing, testing, and production control for each title.
The Waite Group produces 15 to 20 new computer books each has
yearly sales of a half-million books. The Waite Group can be 100
Shoreline Highway, Suite 285, Mill Valley, CA 94941, (415) 331

$7.95 US/22673

Sf ISBN O-b?e2-

HOWARD W. SAMS «
& COMPANY |
A Division of Macmillan, Inc.
4300 West 62nd Street
Indianapolis, Indiana 46268 USA 9 "780672 "226731

You might also like