═══ attach Selection ═══ Please select one of the following functions: o filebuf::attach o fstream::attach ═══ cancel Selection ═══ Please select one of the following functions: o sched::cancel o task::cancel ═══ close Selection ═══ Please select one of the following functions: o fstreambase::close o filebuf::close ═══ cut Selection ═══ Please select one of the following functions: o qhead::cut o qtail::cut ═══ doallocate Selection ═══ Please select one of the following functions: o streambuf::doallocate o strstreambuf::doallocate ═══ draw Selection ═══ Please select one of the following functions: o randint::draw o urand::draw o erand::draw ═══ get Selection ═══ Please select one of the following functions: o istream::get - Extract characters and store in array o istream::get - Extract characters and store in stream o istream::get - Extract character and store in char o istream::get - Extract character and return it o qhead::get - Extract object from queue ═══ o_type Selection ═══ Please select one of the following functions: o object::o_type - return class object type o task::o_type - return class object type o timer::o_type - return class object type o qhead::o_type - return class type o qtail::o_type - return class type o Interrupt_handler::o_type - return class ═══ open Selection ═══ Please select one of the following functions: o filebuf::open o fstream::open o ifstream::open o ofstream::open ═══ overflow Selection ═══ Please select one of the following functions: o streambuf::overflow - Clear Put Area o strstreambuf::overflow - Clear Put Area ═══ pending Selection ═══ Please select one of the following functions: o object::pending - Return object state o sched::pending - Return state o qhead::pending - Is queue empty? o qtail::pending - Is queue full? o Interrupt_handler::pending - Did a signal occur ═══ print Selection ═══ Please select one of the following functions: o object::print o sched::print o task::print o timer::print o qhead::print o qtail::print o Interrupt_handler::print o histogram::print ═══ put Selection ═══ Please select one of the following functions: o streambuf::put o qtail::put ═══ putback Selection ═══ Please select one of the following functions: o istream::putback o qhead::putback ═══ rdbuf Selection ═══ Please select one of the following functions: o ios::rdbuf o fstream::rdbuf o ifstream::rdbuf o ofstream::rdbuf o strstreambase::rdbuf o stdiobuf::rdbuf ═══ rdmax Selection ═══ Please select one of the following functions: o qhead::rdmax o qtail::rdmax ═══ rdmode Selection ═══ Please select one of the following functions: o qhead::rdmode o qtail::rdmode ═══ rdstate Selection ═══ Please select one of the following functions: o ios::rdstate o sched::rdstate ═══ seekoff Selection ═══ Please select one of the following functions: o streambuf::seekoff o filebuf::seekoff o strstreambuf::seekoff ═══ setbuf Selection ═══ Please select one of the following functions: o streambuf::setbuf o filebuf::setbuf o fstreambase::setbuf o strstreambuf::setbuf ═══ setmax Selection ═══ Please select one of the following functions: o qhead::setmax o qtail::setmax ═══ setmode Selection ═══ Please select one of the following functions: o qhead::setmode o qtail::setmode ═══ setwho Selection ═══ Please select one of the following functions: o sched::setwho o task::setwho o timer::setwho ═══ splice Selection ═══ Please select one of the following functions: o qhead::splice o qtail::splice ═══ str Selection ═══ Please select one of the following functions: o strstream::str o ostrstream::str ═══ sync Selection ═══ Please select one of the following functions: o streambuf::sync o istream::sync o filebuf::sync ═══ 1. How to Use the Online Standard Class Library Guide ═══ The IBM C/C++ Tools Standard Class Library Guide is a guide for C++ programmers. It provides information about three standard libraries of predefined C++ classes, including code examples, to enable you to use the classes in your C++ programs. This document is a reference rather than a tutorial. It assumes you are already familiar with C++ programming concepts. The information contained within this document correspond to the three basic class libraries: o The Complex Mathematics Library o The I/O Stream Library o The Task Library Before you begin to use this information, it would be helpful to understand how you can: o Expand the Contents to see all available topics o Obtain additional information for a highlighted word or phrase o Use action bar choices How to Use the Contents When the Contents window first appears, some topics have a plus (+) sign beside them. The plus sign indicates that additional topics are available. To expand the Contents if you are using a mouse, click on the plus sign. If you are using the keyboard, use the Up or Down Arrow key to highlight the topic, and press the plus (+) key. To see additional topics for those headings, click on the plus sign or highlight that topic and press the plus (+) key. To view a topic, double-click on the topic (or press the Up or Down Arrow key to highlight the topic, and then press the Enter key). How to Obtain Additional Information After you select a topic, the information for that topic appears in a window. Highlighted words or phrases indicate that additional information is available. You will notice that certain words and phrases are highlighted in green letters, or in white letters on a black background. These are called hypertext terms. If you are using a mouse, double-click on the highlighted word. If you are using a keyboard, press the Tab key to move to the highlighted word, and then press the Enter key. Additional information then appears in a window. How to Use Action Bar Choices Several choices are available for managing information presented in the C/C++ Tools Online Standard Class Library Guide. There are three pull-down menus on the action bar: the Services menu, the Options menu, and the Help menu. The actions that are selectable from the Services menu operate on the active window currently displayed on the screen. These actions include the following: Bookmark Allows you to set a placeholder so you can retrieve information of interest to you. When you place a bookmark on a topic, it is added to a list of bookmarks you have previously set. You can view the list, and you can remove one or all bookmarks from the list. If you have not set any bookmarks, the list is empty. To set a bookmark, do the following: 1. Select a topic from the Contents. 2. When that topic appears, choose the Bookmark option from the Services pull-down. 3. If you want to change the name used for the bookmark, type the new name in the field. 4. Click on the Place radio button (or press the Up or Down Arrow key to select it). 5. Click on OK (or select it and press Enter). The bookmark is then added to the bookmark list. Search Allows you to find occurrences of a word or phrase in the current topic, selected topics, or all topics. You can specify a word or phrase to be searched. You can also limit the search to a set of topics by first marking the topics in the Contents list. To search for a word or phrase in all topics, do the following: 1. Choose the Search option from the Services pull-down. 2. Type the word or words to be searched for. 3. Click on All sections (or press the Up or Down Arrow keys to select it). 4. Click on Search (or select it and press Enter) to begin the search. 5. The list of topics where the word or phrase appears is displayed. Print Allows you to print one or more topics. You can also print a set of topics by first marking the topics in the Contents list. To print the document Contents list, do the following: 1. Choose Print from the Services pull-down. 2. Click on Contents (or press the Up or Down Arrow key to select it). 3. Click on Print (or select it and press Enter). 4. The Contents list is printed on your printer. Copy Allows you to copy a topic that you are viewing to the System Clipboard or to a file that you can edit. This is particularly useful for copying program samples into the application that you are developing. You can copy a topic that you are viewing in two ways: o Copy copies the topic that you are viewing into the System Clipboard. If you are using a Presentation Manager* (PM) editor (for example, the Enhanced Editor) that copies or cuts (or both) to the System Clipboard, and pastes to the System Clipboard, you can easily add the copied information to your program source module. o Copy to file copies the topic that you are viewing into a temporary file named TEXT.TMP. You can later edit that file by using any editor. TEXT.TMP is placed in the directory where your viewable document resides. To copy a topic, do the following: 1. Expand the Contents list and select a topic. 2. When the topic appears, choose Copy to file from the Services pull-down. 3. The system puts the text pertaining to that topic into the temporary file TEXT.TMP. For information on any of the choices in the Services pull-down, highlight the choice and press the F1 key. The actions that are selectable from the Options menu allow you to change the way your Contents list is displayed. To expand the Contents and show all levels for all topics, choose Expand all from the Options pull-down. You can also press the Ctrl and * keys together. For information on any of the choices in the Options pull-down, highlight the choice and press the F1 key. The actions that are selectable from the Help menu allow you to select different types of help information. You can also press the F1 key for help information about the Information Presentation Facility (IPF). ═══ 1.1. Related Information ═══ o Copyright o Edition Notice o Notices o Trademarks and Service Marks ═══ 1.2. Copyright ═══ Copyright International Business Machines Corporation, 1993. All rights reserved. Note to U.S. Government Users - Documentation related to restricted rights - Use, duplication, or disclosure is subject to restrictions set forth in GSA ADP Schedule Contract with IBM* Corp. ═══ 1.3. Edition Notice ═══ Second Edition, November 1993. This edition applies to Version 2.01 of IBM C/C++ Tools (82G3745, 82G3746, 82G3747) and to all subsequent releases and modifications until otherwise indicated in new editions. This publication could include technical inaccuracies or typographical errors. Changes are periodically made to the information herein; any such changes will be reported in subsequent revisions. Requests for publications and for technical information about IBM* products should be made to your IBM Authorized Dealer or your IBM Marketing Representative. When you send information to IBM, you grant IBM a nonexclusive right to use or distribute the information in any ways it believes appropriate without incurring any obligation to you. ═══ 1.4. Notices ═══ References in this publication to IBM* products, programs, or services do not imply that IBM intends to make these available in all countries in which IBM operates. Any reference to an IBM product, program, or service is not intended to state or imply that only IBM's product, program, or service may be used. Any functionally equivalent product, program, or service that does not infringe any of IBM's intellectual property rights may be used instead of the IBM product, program, or service. Evaluation and verification of operation in conjunction with other products, programs, or services, except those expressly designated by IBM, are the user's responsibility. IBM may have patents or pending patent applications covering subject matter in this document. The furnishing of this document does not give you any license to these patents. You can send license inquiries, in writing, to the IBM Director of Commercial Relations, IBM Corporation, Purchase, NY 10577. This online information may contain coding examples of programs used in daily business operations. To illustrate them as completely as possible, the examples may include the names of individuals, companies, brands, and products. Any such names are fictitious and any similarity to the names and addresses used by an actual business enterprise is entirely coincidental. ═══ 1.5. Trademarks and Service Marks ═══ The following terms, denoted by an asterisk (*) in this publication, are trademarks or service marks of IBM* Corporation in the United States or other countries: C/2 C/C++ Tools C Set ++ C Set/2 CUA IBM Operating System/2 OS/2 Presentation Manager SAA Systems Application Architecture The following terms, denoted by a double asterisk (**) in this publication, are trademarks of another company as follows: AT&T AT&T Corporation UNIX UNIX System Laboratories, Inc. ═══ IBM Trademark ═══ Trademark of the IBM Corporation. ═══ Non-IBM Trademarks ═══ AT&T is a trademark of AT&T Corporation. ═══ 2. General Information ═══ Introduction Introduction to the book's organization, with guidance on how to use the book. Related books are also identified. What Are the Class Libraries? Introduction to the three class libraries that are described in this book: the Complex Mathematics, I/O Stream, and Task Libraries. ═══ 2.1. Introduction ═══ This book describes the standard class libraries included with IBM C/C++ Tools. They provide sets of predefined classes that you can use to perform common functions such as input and output or complex arithmetic. The following information is contained in this chapter: o Who should use this book o How to use this book o A note about examples o Related documentation The three class libraries are: o The Complex Mathematics Library o The I/O Stream Library o The Task Library ═══ 2.1.1. Who Should Use This Book ═══ This book is a reference for people who are experienced in using the C++ language, and understand the characteristics of C++ classes. This book should help you to use the class libraries that are included with C/C++ Tools. ═══ 2.1.2. How to Use This Book ═══ This book has four parts. Part 1 gives general information. Part 2 describes the Complex Mathematics Library. Part 3 describes the I/O Stream Library. Part 4 describes the Task Library. Each of these parts can be read independently. If you need information about the I/O Stream Library, begin by reading Introduction to the I/O Stream Library. It contains important information about the organization of the I/O Stream Library, as well as some essential definitions. This chapter is especially important for you if you are familiar with the AT&T** or UNIX** System Laboratories C++ Language System Iostream Library. New terms are defined in Introduction to the I/O Stream Library to describe certain aspects of the I/O Stream Library. These terms are not used in the corresponding AT&T** documentation for the Iostream Library. ═══ 2.1.2.1. Organization of Chapters ═══ o Part 1. General Information - Introduction, (the chapter you are reading now) describes the organization of the book and how to use it. - What Are the Class Libraries?, introduces the three basic class libraries that are described in this book. o Part 2. The Complex Mathematics Library - complex Class, provides a review of complex arithmetic, and describes complex, the class that lets you manipulate complex numbers. - c_exception Class, describes c_exception, the class that provides runtime error-handling facilities for the Complex Mathematics Library. o Part 3. The I/O Stream Library - Introduction to the I/O Stream Library, lists the classes that make up the I/O Stream Library and the header files that contain their declarations. It also describes the key concept of stream buffers. - streambuf Protected Interface, describes those members of the streambuf class that you need to know about to create your own classes derived from streambuf. - streambuf Public Interface, describes those members of the streambuf class that you can use directly to manipulate an object of filebuf, stdiobuf, or strstreambuf, the predefined classes that are derived from streambuf. - ios Class, describes ios, the base class for the classes that format data that comes from the stream buffer. - istream and istream_withassign Class, describes istream, the class that lets you extract data from a stream buffer. This chapter also describes istream_withassign, a class derived from istream that includes an assignment operator. - ostream and ostream_withassign Classes, describes ostream, the class that lets you insert data into a stream buffer. This chapter also describes ostream_withassign, a class derived from ostream that includes an assignment operator. - iostream and iostream_withassign Classes, describes iostream, the class that is derived from istream and ostream, and iostream_withassign, the class that is derived from istream_withassign and ostream_withassign. - filebuf Class, describes filebuf, the class that adapts streambuf to use files. - fstream, ifstream, and ofstream Classes, describes fstream, ifstream, and ofstream, the classes that adapt istream, ostream, and iostream, respectively, to use files. - strstreambuf Class, describes strstreambuf, the class that adapts streambuf to use an array of bytes in memory as the source or target of data. - strstream, istrstream, and ostrstream Classes, describes istrstream, ostrstream, and strstream, the classes that adapt istream, ostream, and iostream, respectively, to use an array of bytes in memory as the source or target of data. - stdiobuf and stdiostream Classes, describes stdiobuf, the class that lets you mix standard C input and output functions with the C++ I/O Stream Library input and output functions. - Manipulators, describes the manipulators that allow you to use the input operator or the output operator to change the state of the stream that is being used as the source or target of data. o Part 4. The Task Library - Introduction to the Task Library, gives an overview of the Task Library and lists the run-time error messages generated by the Task Library. - Task Handling Classes, describes object, sched, task, and timer, the task handling classes. These classes give you the facilities to create and manage tasks. - Queue Management Classes, describes qhead and qtail, the queue management classes. These classes let you implement a wide range of message-passing and data-buffering schemes. - Interrupt_handler Class, describes Interrupt_handler, the class that allows your tasks to handle external events in the form of signals from the operating system. - Simulation Classes, describes histogram, randint, urand, and erand, the simulation classes. These classes provide utilities for writing program simulations and gathering statistics about them. o Part 5. Appendixes, Glossary, and Index - Extended Complex Mathematics Library Examples, contains examples of how to determine the roots of a complex number and how to define your own complex_error function. - Extended Task Library Examples, contains examples of how to use the Task Library to implement a parallel algorithm and an event-driven simulation. ═══ 2.1.2.2. Organization of Class Descriptions ═══ The chapters that contain detailed descriptions of classes have the following format: o An introduction. o A discussion of how to use the classes, if appropriate. o An excerpt from the appropriate header files that shows the relevant declarations for the classes being described. These excerpts supplement the member function descriptions; they are not complete listings of the header files. If you need to know the value of an element in an enumeration, or any other specific detail about the declaration of a class, you should look at the header file itself. o A description of each member function of each class that the chapter describes. This begins with a description of the constructor and destructor, if they exist. Descriptions of the remaining members follow in alphabetical order. For the more complicated classes like streambuf, the descriptions of members with related operations are grouped together. In most classes, only public and protected members are described. Private members are only described if they are needed to describe a public member. In addition, none of the inherited members in a derived class is described in the discussion of that class, except for virtual functions that do not use the inherited function definition. ═══ 2.1.2.3. How to Find the Description of a Particular Function ═══ The organization of the class libraries can be difficult to understand. The I/O Stream Library, especially, has a complicated hierarchy of classes. A function may be defined in more than one class, and it may be overloaded in a single class. Function name overloading gives C++ many advantages, but it also makes it difficult to describe the functions in a simple, linear fashion. If you know the class in which a function is defined, you can go directly to the chapter where that class is described. There, the functions are grouped according to their purpose and listed alphabetically within each group. If a class has more than one version of a function, all of the versions are described in one section. ═══ 2.1.2.4. Fonts Used in This Book ═══ In this book, C++ code and code fragments appear in special font. Variables that are not used in actual examples, and for which other variable names can be substituted, appear in italics. ═══ 2.1.3. A Note about Examples ═══ The examples in this book explain elements of the C++ class libraries. They are coded in a simple style. They do not try to conserve storage, check for errors, achieve fast run times, or demonstrate all possible uses of a language element. ═══ 2.1.4. Related Documentation ═══ You might want to refer to the following publications for additional information: IBM Publications: IBM C/C++ Tools: C++ Language Reference, S61G-1185, describes the C++ language. IBM C/C++ Tools: Collection Class Library Reference, S61G-1178, describes the C++ collection classes, a set of C++ classes that implement commonly used abstract data types such as sets, stacks, and queues. IBM C/C++ Tools: Application Support Class Library Reference, S82G-3905, describes the C++ application support classes, a set of C++, classes that provide string handling, exception handling, and date and time capabilities to C++ applications. IBM C/C++ Tools: User Interface Class Library Reference, S61G-1179, describes the C++ user interface classes, a set of C++ classes that you can use to create C++ applications with a graphical user interface that conforms to the Common User Access (CUA) interface design. IBM C/C++ Tools: Class Libraries Reference Summary, S61G-1186, lists the member functions of the Standard, Collection, and User Interface class libraries. For each member function, the declaration is provided and the class the function belongs to is indicated. IBM C/C++ Tools: Programming Guide, S61G-1181, describes the C++ component of the common programming interface. The following is a sample of some non-IBM C++ publications that are generally available. It is not an exhaustive list. IBM does not specifically recommend any of these books, and other C++ publications may be available in your locality. C++ Language System Release 3.0 Library Manual, UNIX** System Laboratories. The Annotated C++ Reference Manual by Margaret A. Ellis and Bjarne Stroustrup, Addison-Wesley Publishing Company. The C++ Programming Language (Second Edition) by Bjarne Stroustrup, Addison-Wesley Publishing Company. C++ Primer (Second Edition) by Stanley B. Lippman, Addison-Wesley Publishing Company. ═══ 2.2. What Are the Class Libraries? ═══ This chapter introduces the three class libraries that are described in this book: o The Complex Mathematics Library provides you with the facilities to manipulate complex numbers and perform standard mathematical operations on them. o The I/O Stream Library (also known as the Iostream Library, see History of the Class Libraries). provides you with the facilities to deal with many varieties of input and output. You can derive classes from this library to customize the input and output facilities for your own particular needs. o The Task Library provides you with the facilities to write programs that are made up of tasks. Tasks are lightweight (that is, they require fewer processor resources than standard OS/2 processes) and are nonpreemptive. The Task Library follows the coroutine paradigm. The following sections provide information on using the class libraries: o History of the class libraries o Including a class library in your source code o Other class libraries ═══ 2.2.1. History of the Class Libraries ═══ The basic class libraries described in this book are based on the class libraries from the UNIX** System Laboratories C++ Language System Release 3.0. (Earlier releases of this product are known as the AT&T** C++ Language System.) In the Unix System Laboratories product, the class library that corresponds to the I/O Stream Library is called the Iostream Library. Prior to Release 2.0 of the AT&T** C++ Language System, a class library called the Stream Library provided input and output facilities. The I/O Stream Library includes obsolete functions, described in this book, in order to provide compatibility with the Stream Library. ═══ 2.2.2. Including a Class Library ═══ A class library is a collection of header and library files. The header files provide the interface to the class libraries. To use the classes, functions, and operators available in a class library, you must include the parts of the library's interface that you need in your C++ source program. To include an interface, use the directive #include , where filename is the name of the header file. Place this statement at the beginning of the program that requires any of the classes, functions, or operators defined in the header file. Then, in the body of your program, you can use a class, function, or operator defined in the header file as well as derive new classes and overload the functions and operators. ═══ 2.2.3. Other Class Libraries ═══ In addition to the three standard class libraries, OS/2 C/C++ also supports the Collection Class Library. This library provides you with the facilities to create objects of common data structures such as sets, maps, sequences, trees, and sorted collections. See the Collection Class Library Reference for details about this class library. The C/C++ Tools product also supports the User Interface Class Library, a class library that can be used to create C++ applications with a graphical user interface that conforms to the Common User Access (CUA) interface design. The User Interface Class Library is described in the User Interface Class Library Reference. ═══ 3. The Complex Mathematics Library ═══ complex Class Introduction to the Complex Mathematics Library and review of complex numbers. It describes complex, the class that lets you manipulate complex numbers. c_exception Class Describes c_exception, the class that provides runtime error-handling facilities for the functions and operations in the complex class. ═══ 3.1. complex Class ═══ This chapter reviews the concept of complex numbers, and then describes complex, the class that provides you with the facilities to manipulate complex numbers. Appendix A, "Extended Complex Mathematics Library Examples" contains examples of how you might use the Complex Mathematics Library. The following topics are described in this chapter: o Review of complex numbers o Declarations for the complex class in the complex.h header file o Complex constructors o Complex mathematical operators o Complex input and output operators o Complex mathematical functions o Complex trigonometric functions o Complex magnitude o Complex conversions o Linking to the Complex Library ═══ 3.1.1. Review of Complex Numbers ═══ A complex number is made up of two parts: a real part and an imaginary part. A complex number can be represented by an ordered pair (a,b), where a is the value of the real part of the number and b is the value of the imaginary part. If (a,b) and (c,d) are imaginary numbers, then the following statements are true: o (a,b) + (c,d) = (a+c,b+d) o (a,b) - (c,d) = (a-c,b-d) o (a,b) * (c,d) = (ac-bd,ad+bc) o (a,b) / (c,d) = ((ac+bd) / (c¤+d¤), (bc-ad) / (c¤+d¤)) o The conjugate of a complex number (a,b) is (a,-b) o The absolute value or magnitude of a complex number (a,b) is the positive square root of the value a¤ + b¤ o The polar representation of (a,b) is (r,theta), where r is the distance from the origin to the point (a,b) in the complex plane, and theta is the angle from the real axis to the vector (a,b) in the complex plane. The angle theta can be positive or negative. illustrates the polar representation (r,theta) of the complex number (a,b). Polar Representation of Complex Number (a,b) ═══ 3.1.2. Declarations for complex in complex.h ═══ You must include the following statement in any file that uses the complex class: #include The following is an excerpt from the complex.h header file that shows the relevant declarations for the member functions of the complex class: #include #include #include #define DOMAIN 1 #define SING 2 #define OVERFLOW 3 #define UNDERFLOW 4 #define M_E 2.7182818284590452354 #define M_LOG2E 1.4426950408889634074 #define M_LOG10E 0.43429448190325182765 #define M_LN2 0.69314718055994530942 #define M_LN10 2.30258509299404568402 #define M_PI 3.14159265358979323846 #define M_PI_2 1.57079632679489661923 #define M_PI_4 0.78539816339744830962 #define M_1_PI 0.31830988618379067154 #define M_2_PI 0.63661977236758134308 #define M_2_SQRTPI 1.12837916709551257390 #define M_SQRT2 1.41421356237309504880 #define M_SQRT1_2 0.70710678118654752440 class complex { double re, im; public: complex();. complex(double r, double i = 0.0); friend double real(const complex&); friend double imag(const complex&); friend double abs(complex); friend double norm(complex); friend double arg(complex); friend complex conj(complex); friend complex cos(complex); friend complex cosh(complex); friend complex exp(complex); friend complex log(complex); friend complex pow(double, complex); friend complex pow(complex, int); friend complex pow(complex, double); friend complex pow(complex, complex); friend complex polar(double, double = 0); friend complex sin(complex); friend complex sinh(complex); friend complex sqrt(complex); friend complex operator+(complex, complex); friend complex operator-(complex); friend complex operator-(complex, complex); friend complex operator*(complex, complex); friend complex operator/(complex, complex); friend int operator==(complex, complex); friend int operator!=(complex, complex); void operator+=(complex); void operator-=(complex); void operator*=(complex); void operator/=(complex); }; istream& operator>>(istream&, complex&); ostream& operator<<(ostream&, complex); extern const complex complex_zero(0,0); Note: This header file excerpt, and all of the other header file excerpts in this book, are unpublished proprietary source code of AT&T** and UNIX** System Laboratories. (C) Copyright 1991 AT&T** and UNIX** System Laboratories, Inc. (C)Copyright 1984, 1989, 1990 AT&T**. All rights reserved. ═══ 3.1.2.1. Constants Defined in complex.h ═══ The following table lists the mathematical constants that the Complex Mathematics Library defines (if they have not been previously defined): ┌─────────────────────────────────────────────────────────────────┐ │ Constants Defined in complex.h │ ├──────────────────────────┬──────────────────────────────────────┤ │ CONSTANT NAME │ DESCRIPTION │ ├──────────────────────────┼──────────────────────────────────────┤ │ M_E │ The constant e │ ├──────────────────────────┼──────────────────────────────────────┤ │ M_LOG2E │ The logarithm of e to the base of 2 │ ├──────────────────────────┼──────────────────────────────────────┤ │ M_LOG10E │ The logarithm of e to the base of 10 │ ├──────────────────────────┼──────────────────────────────────────┤ │ M_LN2 │ The natural logarithm of 2 │ ├──────────────────────────┼──────────────────────────────────────┤ │ M_LN10 │ The natural logarithm of 10 │ ├──────────────────────────┼──────────────────────────────────────┤ │ M_PI │ pi │ ├──────────────────────────┼──────────────────────────────────────┤ │ M_PI_2 │ pi / 2 │ ├──────────────────────────┼──────────────────────────────────────┤ │ M_PI_4 │ pi / 4 │ ├──────────────────────────┼──────────────────────────────────────┤ │ M_1_PI │ 1 / pi │ ├──────────────────────────┼──────────────────────────────────────┤ │ M_2_PI │ 2 / pi │ ├──────────────────────────┼──────────────────────────────────────┤ │ M_2_SQRTPI │ 2 divided by the square root of pi │ ├──────────────────────────┼──────────────────────────────────────┤ │ M_SQRT2 │ The square root of 2 │ ├──────────────────────────┼──────────────────────────────────────┤ │ M_SQRT1_2 │ The square root of 1 / 2 │ └──────────────────────────┴──────────────────────────────────────┘ ═══ 3.1.2.2. Constructors for complex ═══ Class: complex There are two versions of the complex constructor: complex(); complex(double r, double i=0.0); If you declare a complex object without specifying any values for the real or imaginary part of the complex value, the constructor that takes no arguments is used and the complex value is initialized to (0, 0). For example, the following declaration gives the object comp the value (0, 0): complex comp; If you give either one or two values in your declaration, the constructor that takes two arguments is used. If you only give one value, the real part of the complex object is initialized to that value, and the imaginary part is initialized to 0. For example, the following declaration gives the object comp2 the value (3.14, 0): complex comp2(3.14); If you give two values in the declaration, the real part of the complex object is initialized to the first value and the imaginary part is initialized to the second value. For example, the following declaration gives the object comp3 the value (3.14, 6.44): complex comp3(3.14, 6.44); There is no explicit complex destructor. ═══ 3.1.2.3. Using the Complex Constructor to Initialize Arrays ═══ You can use the complex constructor to initialize arrays of complex numbers. If the list of initial values is made up of complex values, each array element is initialized to the corresponding value in the list of initial values. If the list of initial values is not made up of complex values, the real parts of the array elements are initialized to these initial values and the imaginary parts of the array elements are initialized to 0. In the following example, the elements of array b are initialized to the values in the initial value list, but only the real parts of elements of array a are initialized to the values in the initial value list. #include void main() { complex a[3] = {1.0, 2.0, 3.0}; complex b[3] = {complex(1.0, 1.0), complex(2.0, 2.0), complex(3.0, 3.0)}; cout << "Here is the first element of a: " << a[0] << endl; cout << "Here is the first element of b: " << b[0] << endl; } This example produces the following output: Here is the first element of a: ( 1, 0) Here is the first element of b: ( 1, 1) ═══ 3.1.3. Mathematical Operators for complex ═══ The complex operators described in this section have the same precedence as the corresponding real operators. The following operators are described: o Addition operator o Subtraction operator o Negation operator o Multiplication operator o Division operator o Equality operator o Inequality operator o Mathematical assignment operators ═══ 3.1.3.1. Addition ═══ Class: complex friend complex operator+(complex x, complex y); The addition operator returns the sum of x and y. ═══ 3.1.3.2. Subtraction ═══ Class: complex friend complex operator-(complex x, complex y); The subtraction operator returns the difference between x and y. ═══ 3.1.3.3. Negation ═══ Class: complex friend complex operator-(complex x); The negation operator returns (- a, - b) when its argument is (a, b). ═══ 3.1.3.4. Multiplication ═══ Class: complex friend complex operator*(complex x, complex y) The multiplication operator returns the product of x and y. ═══ 3.1.3.5. Division ═══ Class: complex friend complex operator/(complex x, complex y) The division operator returns the quotient of x divided by y. ═══ 3.1.3.6. Equality ═══ Class: complex friend int operator==(complex x, complex y); The equality operator "==" returns a nonzero value if x equals y. This operator tests for equality by testing that the two real components are equal and that the two imaginary components are equal. Because both components are double values, the equality operator tests for an exact match between the two sets of values. If you want an equality operator that can test for an absolute difference within a certain tolerance between the two pairs of corresponding components, you can use a function such as the is_equal function defined in Inequality. ═══ 3.1.3.7. Inequality ═══ Class: complex friend int operator!=(complex x, complex y); The inequality operator "! =" returns a nonzero value if x does not equal y. This operator tests for inequality by testing that the two real components are not equal and that the two imaginary components are not equal. Because both components are double values, the inequality operator returns false only when both the real and imaginary components of the two values are identical. If you want an inequality operator that can test for an absolute difference within a certain tolerance between the two pairs of corresponding components, you can use a function such as the is_not_equal function defined in the following example. In the example, the functions is_equal and is_not_equal are defined to test whether two complex values are equal or not equal, respectively, within a certain tolerance. You should use functions like is_equal and is_not_equal, rather than the equality and inequality operators, if you want a reliable comparison between two complex values. #include int is_equal(const complex &a, const complex &b, const double tol=0.0001) { return (abs(real(a) - real(b)) < tol && abs(imag(a) - imag(b)) < tol); } int is_not_equal(const complex &a, const complex &b, const double tol=0.0001) { return !is_equal(a, b, tol); } void main() { complex c1 = complex(1.0, 2.0); complex c2 = c1; complex c3 = complex(3.0, 4.0); if (is_equal(c1, c2)) cout << "c1 is equal to c2" << endl; else cout << "c1 is not equal to c2 - not possible!" << endl; if (is_not_equal(c1, c3)) cout << "c1 is not equal to c3" << endl; else cout << "c1 is equal to c3 - not possible!" << endl; } This example produces the following output: c1 is equal to c2 c1 is not equal to c3 ═══ 3.1.3.8. Mathematical Assignment Operators ═══ Class: complex void operator+=(complex x); void operator-=(complex x); void operator*=(complex x); void operator/=(complex x); The following list describes the functions of the mathematical assignment operators: o x + = y assigns the value of x + y to x. o x - = y assigns the value of x - y to x. o x * = y assigns the value of x * y to x. o x / = y assigns the value of x / y to x. Note: The assignment operators do not produce a value that can be used in an expression. The following code, for example, produces a compile-time error: complex x, y, z; // valid declaration x = (y += z); // invalid assignment causes a // compile-time error ═══ 3.1.3.9. Example of Using the Complex Mathematical Operators ═══ The following example shows how you can use the complex mathematical operators: #include void main() { complex a, b; cout << "enter two complex values" << endl; cin >> a >> b; cout << "The sum of these two numbers is " << a+b << endl; cout << "The difference between these two numbers is " << a-b << endl; cout << "The product of these two numbers is " << a*b << endl; cout << "The first number divided by the second is " << a/b << endl; } If you run this program with the values (1,1) and (2,2) for input, the output will look like this: enter two complex values The sum of these two numbers is ( 3, 3) The difference between these two numbers is ( -1, -1) The product of these two numbers is ( 0, 4) The first number divided by the second is ( 0.5, 0) ═══ 3.1.4. Input and Output Operators for complex ═══ The following topics are described: o The input operator o The output operator o An example of using the input and output operators. ═══ 3.1.4.1. Input Operator ═══ Class: complex istream& operator>>(istream& is, complex& c); The input (or extraction) operator >> takes complex value c from the stream is in the form (a,b). The parentheses and comma are mandatory delimiters for input when the imaginary part of the complex number being read is nonzero. Otherwise, they are optional. In both cases, whitespace is optional. ═══ 3.1.4.2. Output Operator ═══ Class: complex ostream& operator<<(ostream& os, complex c); The output (or insertion) operator << writes complex value c to the stream os in the form (a,b). ═══ 3.1.4.3. Example of Using the Complex Input and Output Operators ═══ #include void main(){ complex x; cout << "Enter a complex number in the form (a,b):" << endl; cin >> x; cout << "Here is the complex value: " << x << endl; } This example produces the following output if you enter the complex value (3,4) at the prompt: Enter a complex number in the form (a,b): Here is the complex value: (3,4) ═══ 3.1.5. Mathematical Functions for complex ═══ The following mathematical functions are described: o exp - Exponent o log - Logarithm o pow - Power o sqrt - Square Root There is also an example of using the complex mathematical functions. ═══ 3.1.5.1. exp - Exponent ═══ Class: complex friend complex exp(complex x); exp() returns the complex value equal to e to the power of x where x is the argument. Results of the Default Error-Handling Procedures shows the values returned by the default error-handling procedure for exp(). ═══ 3.1.5.2. log - Logarithm ═══ Class: complex friend complex log(complex x); log() returns the natural logarithm of the argument x. Results of the Default Error-Handling Procedures shows the values returned by the default error-handling procedure for log(). ═══ 3.1.5.3. pow - Power ═══ Class: complex friend complex pow(double d, complex z); friend complex pow(complex c, int i); friend complex pow(complex c, double d); friend complex pow(complex c, complex z); Note: Exponents in the following text are shown in square brackets. pow() returns the complex value x[y], where x is the first argument and y is the second argument. pow() is overloaded four times. If d is a double value, i is an integer value, and c and z are complex values, then pow() can produce any of the following results: o d[z] o c[i] o c[d] o c[z] ═══ 3.1.5.4. sqrt - Square Root ═══ Class: complex friend complex sqrt(complex x) sqrt() returns the square root of its argument. If c and d are real values, then every complex number (a,b), where: o a = c¤ - d¤ o b = 2cd has two square roots: o (c,d) o (-c,-d ) sqrt() returns the square root that has a positive real part, that is, the square root that is contained in the first or fourth quadrants of the complex plane. ═══ 3.1.5.5. Example of Using the Complex Mathematical Functions ═══ The following program shows how you can use the complex mathematical functions: #include void main() { complex a, b; int i; double f; // // prompt the user for an argument for calls to // exp(), log(), and sqrt() // cout << "Enter a complex value" << endl; cin >> a; cout << "The value of exp() for " << a << " is: " << exp(a) << endl; cout << "The natural logarithm of " << a << " is: " << log(a) << endl; cout << "The square root of " << a << " is: " << sqrt(a) << endl << endl; // // prompt the user for arguments for calls to pow() // cout << "Enter 2 complex values (a and b), an integer (i),"; cout << " and a floating point value (f)" << endl; cin >> a >> b >> i >> f; cout << "a is " << a << ", b is " << b << ", i is " << i; cout << ", f is " << f << endl; cout << "The value of f**a is: " << pow(f, a) << endl; cout << "The value of a**i is: " << pow(a, i) << endl; cout << "The value of a**f is: " << pow(a, f) << endl; cout << "The value of a**b is: " << pow(a, b) << endl; } This program produces the following output when you give it (1,1), (1,1), (1,0), 1, and 1.0 as input: Enter a complex value The value of exp() for ( 1, 1) is: ( 1.46869, 2.28736) The natural logarithm of ( 1, 1) is: ( 0.346574, 0.785398) The square root of ( 1, 1) is: ( 1.09868, 0.45509) Enter 2 complex values (a and b), an integer (i), and a floating point value (f) a is ( 1, 1), b is ( 1, 0), i is 1, f is 1 The value of f**a is: ( 1, 0) The value of a**i is: ( 1, 1) The value of a**f is: ( 1, 1) The value of a**b is: ( 1, 1) ═══ 3.1.6. Trigonometric Functions for complex ═══ The following trigonometric functions are described: o cos - Cosine o cosh - Hyperbolic cosine o sin - Sine o sinh - Hyperbolic sine There is also an example of using the complex trigonometric functions. ═══ 3.1.6.1. cos - Cosine ═══ Class: complex friend complex cos(complex x); cos() returns the cosine of x. ═══ 3.1.6.2. cosh - Hyperbolic Cosine ═══ Class: complex friend complex cosh(complex x); cosh() returns the hyperbolic cosine of x. Results of the Default Error-Handling Procedures shows the values returned by the default error-handling procedure for cosh(). ═══ 3.1.6.3. sin - Sine ═══ Class: complex friend complex sin(complex x); sin() returns the sine of x. ═══ 3.1.6.4. sinh - Hyperbolic Sine ═══ Class: complex friend complex sinh(complex x); sinh() returns the hyperbolic sine of x. Results of the Default Error-Handling Procedures shows the values returned by the default error-handling procedure for sinh(). ═══ 3.1.6.5. Example of Using the Complex Trigonometric Functions ═══ The following example shows how you can use the complex trigonometric functions: #include void main() { complex a = (M_PI, M_PI_2); // a = (pi,pi/2) // display the values of cos(), cosh(), sin(), and sinh() // for (pi,pi/2) cout << "The value of cos() for (pi,pi/2) is: " << cos(a) << endl; cout << "The value of cosh() for (pi,pi/2) is: " << cosh(a) << endl; cout << "The value of sin() for (pi,pi/2) is: " << sin(a) << endl; cout << "The value of sinh() for (pi,pi/2) is: " << sinh(a) << endl; } This program produces the following output: The value of cos() for (pi,pi/2) is: ( 6.12323e-17, 0) The value of cosh() for (pi,pi/2) is: ( 2.50918, 0) The value of sin() for (pi,pi/2) is: ( 1, -0) The value of sinh() for (pi,pi/2) is: ( 2.3013, 0) ═══ 3.1.7. Magnitude Functions for complex ═══ The following magnitude functions are described: o abs - Absolute value o norm - Square magnitude ═══ 3.1.7.1. abs - Absolute Value ═══ Class: complex friend double abs(complex x); abs() returns the absolute value or magnitude of its argument. The absolute value of a complex value (a,b) is the positive square root of a¤+b¤. ═══ 3.1.7.2. norm - Square Magnitude ═══ Class: complex friend double norm(complex x); norm() returns the square of the magnitude of its argument. If the argument x is equal to the complex number (a,b), norm() returns the value a¤+b¤. norm() is faster than abs(), but it is more likely to cause overflow errors. ═══ 3.1.8. Conversion Functions for complex ═══ The conversion functions in the Complex Mathematics Library allow you to convert between the polar and standard complex representations of a value and to extract the real and imaginary parts of a complex value. The following conversion functions are described: o arg - Angle in radians o conj - Conjugation o polar - Polar to complex o real - Extract real part o imag - Extract imaginary part There is also an example of using the complex conversion functions. ═══ 3.1.8.1. arg - Angle in Radians ═══ Class: complex friend double arg(complex x); arg() returns the angle (in radians) of the polar representation of its argument. If the argument x is equal to the complex number (a,b), the angle returned is the angle in radians on the complex plane between the real axis and the vector (a,b). The return value has a range of -pi to pi . See for an illustration of the polar representation of complex numbers. ═══ 3.1.8.2. conj - Conjugation ═══ Class: complex friend complex conj(complex x); conj() returns the complex value equal to (a,-b) if the input argument x is equal to (a,b). ═══ 3.1.8.3. polar - Polar to Complex ═══ Class: complex friend complex polar(double a, double b= 0); polar() returns the standard complex representation of the complex number that has a polar representation (a,b). ═══ 3.1.8.4. real - Extract Real Part ═══ Class: complex friend double real(const complex& x); real() extracts the real part of the complex number x. ═══ 3.1.8.5. imag - Extract Imaginary Part ═══ Class: complex friend double imag(const complex& x); imag() extracts the imaginary part of the complex number x. ═══ 3.1.8.6. Example of Using the Complex Conversion Functions ═══ The following program shows how you can use the complex conversion functions: #include void main() { complex a; // for a value supplied by the user, display the real part, // the imaginary part, and the polar representation cout << "enter a complex value" << endl; cin >> a; cout << "the real part of this value is " << real(a) << endl; cout << "the imaginary part of this value is " << imag(a) << endl; cout << "the polar representation of this value is " << "("<< abs(a)<< ","<< arg(a)<< ")"<< endl; } This program produces the following output for an input of (1,1): enter a complex value the real part of this value is 1 the imaginary part of this value is 1 the polar representation of this value is (1.41421,0.785398) ═══ 3.1.9. Linking to the Complex Library ═══ You must specify the following library names when compiling or linking programs that use the Complex Library: o COMPLEX.LIB - for single-tasking programs o COMPLEXM.LIB - for multitasking programs. No dynamically linkable version of this library is provided. ═══ 3.2. c_exception Class ═══ This chapter describes c_exception, the class that lets you handle errors that are created by the functions and operations in the complex class. o Declarations for c_exception in the complex.h header file o Constructor for c_exception o Data members of c_exception o Errors handled by the Complex Mathematics Library o Errors handled outside of the Complex Mathematics Library Note: The c_exception class is not related to the C++ exception handling mechanism that uses the try, catch and throw statements. ═══ 3.2.1. Declarations for c_exception in complex.h ═══ You must include the following statement in any file that uses members of the c_exception class: #include The following is an excerpt from the complex.h header file that shows the relevant declarations for the members of c_exception: #define DOMAIN 1 #define SING 2 #define OVERFLOW 3 #define UNDERFLOW 4 class c_exception { int type; char *name; complex arg1; complex arg2; complex retval; public: c_exception( char *n, const complex& a1, const complex& a2 = complex_zero); friend int complex_error( c_exception& ); friend complex exp( complex ); friend complex sinh( complex ); friend complex cosh( complex ); friend complex log( complex ); }; ═══ 3.2.2. Constructor for c_exception ═══ c_exception(char *n, const complex& a1, const complex& a2 = complex_zero); The c_exception constructor creates a c_exception object with name member equal to n, arg1 member equal to a1, and arg2 member equal to a2. ═══ 3.2.3. Data Members of c_exception ═══ The following data members are described: o arg1, arg2 - Arguments of the function that caused the error o name - Name of the function that caused the error o retval - Value returned by the default definition of the error handling function o type - Type of error that has occurred ═══ 3.2.3.1. arg1, arg2 - Arguments of the Function that Caused the Error ═══ Class: c_exception complex arg1; complex arg2; arg1 and arg2 are the arguments with which the function that caused the error was called. ═══ 3.2.3.2. name - Name of the Function that Caused the Error ═══ Class: c_exception char *name; name is a string that contains the name of the function where the error occurred. ═══ 3.2.3.3. retval - Value Returned by the Default Definition of the Error Handling Function ═══ Class: c_exception complex retval; retval is the value that the default definition of the error handling function complex_error() returns. You can make your own definition of complex_error() return a different value. ═══ 3.2.3.4. type - Type of Error that Has Occurred ═══ Class: c_exception int type; type describes the type of error that has occurred. It can take the following values that are defined in the complex.h header file: o SING argument singularity o OVERFLOW overflow range error o UNDERFLOW underflow range error ═══ 3.2.4. Errors Handled by the Complex Mathematics Library ═══ The following topics are described: o complex_error - the error-handling function o Results of the default error-handling procedures. ═══ 3.2.4.1. complex_error - the Error-Handling Function ═══ Class: c_exception friend int complex_error(c_exception& ce); complex_error() is invoked by member functions of the Complex Mathematics Library when errors are detected. The argument ce refers to the c_exception object that contains information about the error. You can define your own procedures for handling errors by defining a function called complex_error with return type int and a single parameter of type c_exception&. If you define your own complex_error function and this function returns a nonzero value, no error message will be generated and the external variable errno will not be set. If this function returns zero, errno is given the value of one of the following constants: o ERANGE if the result is too large or too small o EDOM if there is a domain error within a mathematical function. These constants are defined in errno.h. If you define your own version of complex_error, when you compile your program you must: o Ensure that the name of the source file or .OBJ that contains your version of complex_error appears on the command line before complex.lib. o Use the /NOE linker option For example, if the source file containing your definition of complex_error is source1.cpp, then you would invoke the compiler like this: icc source1.cpp complex.lib /B"/NOE" ═══ 3.2.4.2. Results of the Default Error-Handling Procedures ═══ Class: c_exception If you do not define your own complex_error, the default error-handling procedures will be invoked when an error occurs. The results for a given input complex value (a, b) depend on the kind of error and the sign of the cosine and sine of b. The following table shows the return value of the default error-handling procedure and the value given to errno for each function with input equal to the complex value (a, b). Note: The following symbols appear in this table: 1. NA - not applicable. The result of the error depends on the sign of the cosine and sine of b (the imaginary part of the argument) unless "NA" appears in the Cosine b or Sine b columns. 2. HUGE - the maximum double value. This value is defined in math.h. Function Error Cosine b Sine b Return Value errno Value cosh a too large nonneg. nonneg. (+HUGE,+HUGE) ERANGE cosh a too large nonneg. nenneg. (+HUGE,-HUGE) ERANGE cosh a too small nonneg. nonneg. (+HUGE,-HUGE) ERANGE cosh a too small nonneg. nenneg. (+HUGE,+HUGE) ERANGE cosh a too small negative nonneg. (-HUGE,-HUGE) ERANGE cosh a too small negative nenneg. (-HUGE,+HUGE) ERANGE cosh b too large negative nonneg. (-HUGE,+HUGE) ERANGE cosh b too large negative nenneg. (-HUGE,-HUGE) ERANGE cosh b too small NA NA (0,0) ERANGE exp a too large positive positive (+HUGE,+HUGE) ERANGE exp a too large positive positive (+HUGE,-HUGE) ERANGE exp a too large nonpos. positive (-HUGE,+HUGE) ERANGE exp a too large nonpos. positive (-HUGE,-HUGE) ERANGE exp a too small NA NA (0,0) ERANGE exp b too large NA NA (0,0) ERANGE exp b too small NA NA (0,0) ERANGE log a too large positive positive (+HUGE,0) EDOM (a message is also produced) sinh a too large nonneg. nonneg. (+HUGE,+HUGE) ERANGE sinh a too large nonneg. negative (+HUGE,-HUGE) ERANGE sinh a too large negative nonneg. (-HUGE,+HUGE) ERANGE sinh a too large negative negative (-HUGE,-HUGE) ERANGE sinh a too small nonneg. nonneg. (-HUGE,+HUGE) ERANGE sinh a too small nonneg. negative (-HUGE,-HUGE) ERANGE sinh a too small negative nonneg. (+HUGE,+HUGE) ERANGE sinh a too small negative negative (+HUGE,-HUGE) ERANGE sinh b too large NA NA (0,0) ERANGE sinh b too small NA NA (0,0) ERANGE Note: errno is set to EDOM when the error for log() is detected. The message is stored in DDE4.MSG. The message number in DDE4.MSG is 90. When this message is displayed by the C/C++ Runtime Library, it is changed to 5090. For information on binding this message, see "Binding Runtime Messages" in the IBM C/C++ Tools: Programming Guide. ═══ 3.2.5. Errors Handled Outside of the Complex Mathematics Library ═══ There are some cases where member functions of the Complex Mathematics Library call functions in the math library. These calls can cause underflow and overflow conditions that are handled by the matherr() function that is declared in the math.h header file. For example, the overflow conditions that are caused by the following calls are handled by matherr(): o exp(complex(MAXDOUBLE, MAXDOUBLE)) o pow(complex(MAXDOUBLE, MAXDOUBLE), INT_MAX) o norm(complex(MAXDOUBLE, MAXDOUBLE)) MAXDOUBLE is the maximum valid double value. INT_MAX is the maximum int value. Both these constants are defined in limits.h. If you do not want the default error-handling defined by matherr(), you should define your own version of matherr(). ═══ 4. The I/O Stream Library ═══ Introduction to the I/O Stream Library Introduces the I/O Stream Library, its classes and header files, and describes stream buffers. streambuf Protected Interface Describes the protected members of the streambuf class. You can use these members to create classes derived from streambuf. streambuf Public Interface Describes the public members of the streambuf class. You can use these members to manipulate objects of filebuf, stdiobuf, or strstreambuf, the predefined classes derived from streambuf. ios Class Describes ios, the base class for the classes that format data that comes from the stream buffer. istream and istream_withassign Class Describes istream, the class that lets you extract data from a stream buffer, and istream_withassign, a class derived from istream that includes an assignment operator. ostream and ostream_withassign Classes Describes ostream, the class that lets you insert data into a stream buffer, and ostream_withassign, a class derived from ostream that includes an assignment operator. iostream and iostream_withassign Classes Describes iostream, the class derived from istream and ostream, and iostream_withassign, the class derived from istream_withassign and ostream_withassign. filebuf Class Describes filebuf, the class that specializes streambuf to use files. fstream, ifstream, and ofstream Classes Describes fstream, ifstream, and ofstream, the classes that adapt istream, ostream, and iostream, respectively, to use files. strstreambuf Class Describes strstreambuf, the class that specializes streambuf to use an array of bytes in memory as the source or target of data. strstream, istrstream, and ostrstream Classes Describes istrstream, ostrsteam, and strstream, the classes that adapt istream, ostream, and iostream, respectively, to use an array of bytes in memory as the source or target of data. stdiobuf and stdiostream Classes Describes stdiobuf, the class that lets you mix standard C input and output functions with C++ I/O Stream Library functions. Manipulators Describes the parameterized manipulators that allow you to use the input or output operator to change the state of a stream. ═══ 4.1. Introduction to the I/O Stream Library ═══ This chapter describes the overall structure of the I/O Stream Library. This class library provides you with the facilities to deal with many varieties of input and output. The following topics are described in this chapter: o Linking to the I/O Stream Library o The I/O Stream Library and stdio.h in C o Overview of the I/O Stream Library o The I/O Stream Library class hierarchy o The I/O Stream Library header files o Predefined streams o Anonymous streams o Stream buffers ═══ 4.1.1. Linking to the I/O Stream Library ═══ The I/O Stream Library is part of the C/C++ libraries and is linked in automatically unless you specify the /Gn option. ═══ 4.1.2. The I/O Stream Library and stdio.h ═══ In both C++ and C, input and output are described in terms of sequences of characters, or streams. The I/O Stream Library provides the same facilities in C++ that stdio.h provides in C, but it also has the following advantages over stdio.h: o The input or extraction (>>) operator and the output or insertion (<<) operator are typesafe. They are also easy to use. o You can define input and output for your own types or classes by overloading the input and output operators. This gives you a uniform way of performing input and output for different types of data. o The input and output operators are more efficient than scanf() and printf(), the analogous C functions defined in stdio.h. Both scanf() and printf() take format strings as arguments, and these format strings have to be parsed at run time. The bindings for the output and input operators are performed at compile time. ═══ 4.1.3. Overview of the I/O Stream Library ═══ The I/O Stream Library is the standard input and output library for C++. In C++, input and output are described in terms of sequences of characters, or streams. The processing of these streams is done at two levels. The first level treats the data as sequences of characters; the second level treats it as a series of values of a particular type. There are two primary base classes for the I/O Stream Library: 1. The streambuf class and the classes derived from it (strstream, stdiobuf, and filebuf) implement the stream buffers. Stream buffers act as temporary repositories for characters that are coming from the ultimate producers of input or are being sent to the ultimate consumers of output. See Stream Buffers for more details. 2. The ios class maintains formatting and error state information for these streams. The classes derived from ios implement the formatting of these streams. This formatting involves converting sequences of characters from the stream buffer into values of a particular type and converting values of a particular type into their external display format. The I/O Stream Library predefines streams for standard input, standard output, and standard error. See Predefined Streams for more details on the predefined streams. If you want to open your own streams for input or output, you must create an iostream object. The iostream constructor takes as an argument a pointer to a streambuf object. This object is associated with the device, file, or array of bytes in memory that is going to be the ultimate producer of input or the ultimate consumer of output. ═══ 4.1.3.1. Combining Input and Output of Different Types ═══ The I/O Stream Library overloads the input (>>) and output (<<) operators for the built-in types. As a result, you can combine input or output of values with different types in a single statement without having to state the type of the values. The following example shows how values with a variety of types can be combined in a single output statement: #include void main(){ int i = 3; long l = 88888888L; double d = 3.14; float f = 2.1F; char c = 'b'; cout << "A variety of values: int " << i << ", long " << l << ", double "<< d << ",\n" << "float " << f << ", char " << c<< "." << endl; } This example produces the following output: A variety of values: int 3, long 88888888, double 3.14, float 2.1, char b. ═══ 4.1.3.2. Input and Output for User-Defined Classes ═══ You can overload the input and output operators for the classes that you create yourself. Once you have overloaded the input and output operators for a class, you can perform input and output operations on objects of that class in the same way that you would perform input and output on char, int, double, and the other built-in types. The following example shows how you can overload the input and output operators for your own classes. The class circle has two private members that record the center and radius of a circle. In the example, the value of a circle object is printed using the overloaded output operator. The user is then prompted to supply values that are assigned to another circle object. The value of this circle object is then printed. #include class Circle { public: Circle(double c=0.0, double r=0.0): center(c), radius(r){} private: double center; double radius; friend ostream& operator<<(ostream& o, const Circle& c); friend istream& operator>>(istream& i, Circle& c); }; ostream& operator<<(ostream& o, const Circle& c) { o << c.center << " " << c.radius << endl; return o; } istream& operator>>(istream& i, Circle& c) { i >> c.center >> c.radius; return i; } void main() { Circle c(1.5, 3.0); Circle d; cout << "Circle c " << c << endl; cout << "Enter the center and radius of yourcircle: " << endl; cin >> d; cout << "Here is your circle " << d << endl; } If you supply the values 3.0, 5.6 to this program, the following output is produced: Circle c 1.5 3 Enter the center and radius of your circle: Here is your circle 3 5.6 ═══ 4.1.4. The I/O Stream Library Class Hierarchy ═══ The I/O Stream Library has two base classes that correspond to the two levels of processing described in "Overview of the Stream Library": o The streambuf class implements stream buffers (see Stream Buffers). It is the base class for the following classes: - strstreambuf - stdiobuf - filebuf o The ios class maintains formatting and error state information for streams. Streams are implemented as objects of the following classes that are derived from ios: - stdiostream - istream - ostream The classes that are derived from ios are themselves base classes: o istream is the input stream class. It implements stream buffer input, or input operations. The following classes are derived from istream: - istrstream - ifstream - istream_withassign - iostream o ostream is the output stream class. It implements stream buffer output, or output operations. The following classes are derived from ostream: - ostrsteam - ofstream - ostream_withassign - iostream o iostream is the class that combines istream and ostream to implement input and output to stream buffers. The following classes are derived from iostream: - strstream - iostream_withassign - fstream Note: The I/O Stream Library defines other classes in addition to those listed above. These classes include fstreambase and strstreambase. These classes are meant for the internal use of the I/O Stream Library. They are described in this book because their member functions are used directly by one or more of the classes listed above. You should not use these internal classes directly. Derivation Relationships in the I/O Stream Library shows the relationship between the two base classes, ios and streambuf, and their derived classes. In the figure, two classes are connected by an arrow if the class at the pointed end of the arrow is derived from the class at the other end of the arrow. ios ┌──────────┘│└───────────┐ istream stdiostream ostream ┌───────┘ │ │ └──────┐ ┌───────┘ │ │ └──────┐ │ │ └───┐ │ │ ┌───┘ └─┐ │ istream_ │ ifstream │ │ ostream_ │ ofstream withassign │ │ │ withassign │ istrstream │ │ ostrstream iostream ┌──────────┘│└───────────┐ iostream_ strstream fstream withassign streambuf ┌──────────┘│└───────────┐ strstreambuf stdiobuf filebuf Derivation Relationships in the I/O Stream Library ═══ 4.1.5. The I/O Stream Library Header Files ═══ To use a class in the I/O Stream Library, you must include the appropriate header files for that class. The following is a list of the I/O Stream Library header files and the classes that they cover: o iostream.h contains declarations for the basic classes of the library: - streambuf - ios - istream - istream_withassign - ostream - ostream_withassign - iostream - iostream_withassign o fstream.h contains declarations for the classes that deal with files: - filebuf - ifstream - ofstream - fstream o stdiostr.h contains declarations for stdiobuf and stdiostream, the classes that specialize streambuf and ios, respectively, to use the FILE structures defined in the C header file stdio.h. o strstrea.h contains declarations for the classes that deal with character strings. The first "str" in each of these names stands for "string": - istrstream - ostrsteam - strstream - strstreambuf o iomanip.h contains declarations for the parameterized manipulators. Manipulators are values that you can insert into streams or extract from streams to affect or query the behavior of the streams. o stream.h is used for compatibility with earlier versions of the I/O Stream Library. It includes iostream.h, fstream.h, stdiostr.h, and iomanip.h, along with some definitions needed for compatibility with the AT&T** C++ Language System Release 1.2. Only use this header file with existing code; do not use it with new C++ code. Note: If you use the obsolete function form() declared in stream.h, there is a limit to the size of the format specifier. If you call form() with a format specifier string longer than this limit, a runtime message (EDC5091) will be generated and the program will terminate. ═══ 4.1.6. Predefined Streams ═══ In addition to giving you the facilities to define your own streams for input and output, the I/O Stream Library also provides the following predefined streams: o cin is the standard input stream. o cout is the standard output stream. o cerr is the standard error stream. Output to this stream is unit-buffered. Characters that are sent to this stream are flushed after each output operation. o clog is also an error stream, but unlike the output to cerr, the output to clog is buffered. The predefined streams are initialized before the constructors for any static objects are called. You can use the predefined streams in the constructors for static objects. The predefined streams cin, cerr, and clog are tied to cout. As a result, if you use cin, cerr, or clog, cout is flushed. That is, the contents of cout are sent to their ultimate consumer. ═══ 4.1.7. Anonymous Streams ═══ An anonymous stream is a stream that is created as a temporary object. Because it is a temporary object, an anonymous stream requires a const type modifier and is not a modifiable lvalue. Unlike the AT&T** C++ Language System Release 2.1., the C/C++ Tools does not allow a non-const reference argument to be matched with a temporary object. User-defined input and output operators usually accept a non-const reference (such as a reference to an istream or ostream object) as an argument. Such an argument cannot be initialized by an anonymous stream, and thus an attempt to use an anonymous stream as an argument to a user-defined input or output operator will usually result in a compile-time error. In the following example, an object of the class Circle (defined in Input and Output for User-Defined Classes) is declared, and the value of an anonymous stream is assigned to it using the input operator. The following statement: Circle c; istrstream("10 15") >> c; causes the following compile-time error: CIRCLE.C(32:1) : error EDC3070: Call does not match any argument list for "istream::operator>>". ═══ 4.1.8. Stream Buffers ═══ One of the most important concepts in the I/O Stream Library is the stream buffer. The streambuf class implements some of the member functions that define stream buffers, but other specialized member functions are left to the classes that are derived from streambuf: strstreambuf, stdiobuf, and filebuf. Note: The AT&T** and UNIX** System Laboratories C++ Language System documentation use the terms reserve area and buffer instead of stream buffer. ═══ 4.1.8.1. What Does a Stream Buffer Do? ═══ A stream buffer acts as a buffer between the ultimate producer (the source of data) or ultimate consumer (the target of data) and the member functions of the classes derived from ios that format this raw data. The ultimate producer can be a file, a device, or an array of bytes in memory. The ultimate consumer can also be a file, a device, or an array of bytes in memory. ═══ 4.1.8.2. Why Use a Stream Buffer? ═══ In most operating systems, a system call to read data from the ultimate producer or write it to the ultimate consumer is an expensive operation. If your applications can reduce the number of system calls they have to make, they will usually be more efficient. By acting as a buffer between the ultimate producer or ultimate consumer and the formatting functions, a stream buffer can reduce the number of system calls that are made. Consider, for example, an application that is reading data from the ultimate producer. If there is no buffer, the application has to make a system call for each character that is read. However, if the application uses a stream buffer, system calls will only be made when the buffer is empty. Each system call will read enough characters from the ultimate producer (if they are available) to fill the buffer again. ═══ 4.1.8.3. How Is a Stream Buffer Implemented? ═══ A stream buffer is implemented as an array of bytes. For each stream buffer, pointers are defined that point to elements in this array to define the get area, or the space that is available to accept bytes from the ultimate producer, and the put area, or the space that is available to store bytes that are on their way to the ultimate consumer. A stream buffer does not necessarily have separate get and put areas. A stream buffer that is used for input, such as one that is attached to an istream object, has a get area. A stream buffer that is used for output, such as one that is attached to an ostream object, has a put area. A stream buffer that is used for both input and output, such as one that is attached to an iostream object, has both a get area and a put area. In stream buffers implemented by the filebuf class that are specialized to use files as an ultimate producer or ultimate consumer, the get and put areas overlap. The following member functions of the streambuf class return pointers to boundaries of areas in a stream buffer: o base() returns a pointer to the beginning of the stream buffer. o eback() returns a pointer to the beginning of the space available for putback. Characters that are putback are returned to the get area of the stream buffer. o gptr() returns the get pointer, a pointer to the beginning of the get area. The space between gptr() and egptr() has been filled by the ultimate producer. These characters are waiting to be extracted from the stream buffer. The space between eback() and gptr() is available for putback. o egptr() returns a pointer to the end of the get area. o pbase() returns a pointer to the beginning of the space available for the put area. o pptr() returns the put pointer, a pointer to the beginning of the put area. The space between pbase() and pptr() is filled with bytes that are waiting to be sent to the ultimate consumer. The space between pptr() and epptr() is available to accept characters from the application program that are on their way to the ultimate consumer. o epptr() returns a pointer to the end of the put area. o ebuf() returns a pointer to the end of the stream buffer. Note: In the actual implementation of stream buffers, the pointers returned by these functions point at char values. In the abstract concept of stream buffers, on the other hand, these pointers point to the boundary between char values. To establish a correspondence between the abstract concept and the actual implementation, you should think of the pointers as pointing just before the character that they actually point at. The Structure of Stream Buffers shows how the pointers returned by these functions delineate the stream buffer. ┌───────────── ┌──────────────────┐ ────base() │ ├──────────────────┤ │ │ ──── │ │ ├──────────────────┤ ────eback() │ ┌── ├──────────────────┤ ────gptr() │ │ ├──────────────────┤ │ get area ┤ │ ──── │ ─ULTIMATE PRODUCER │ │ ├──────────────────┤ │ └── ├──────────────────┤ ────egptr() stream ┤ │ ──── │ buffer │ ├──────────────────┤ ────pbase() │ ┌── ├──────────────────┤ ────pptr() │ │ ├──────────────────┤ │ put area ┤ │ ──── │ ─ULTIMATE CONSUMER │ │ ├──────────────────┤ │ └── ├──────────────────┤ ────epptr() │ │ ──── │ │ ├──────────────────┤ └───────────── └──────────────────┘ ────ebuf() The Structure of Stream Buffers ═══ 4.2. streambuf Protected Interface ═══ This chapter describes the protected interface of the streambuf class. The protected interface consists of the member functions of streambuf that you need to use to derive your own classes from streambuf. See What Is the streambuf Protected Interface? for more details. The streambuf class implements the concept of stream buffers. A stream buffer acts as a buffer between the ultimate producer or ultimate consumer of data and the member functions of the classes derived from ios (such as istream and ostream) that format this data. See Stream Buffers for a more detailed description of stream buffers. The following topics are described in this chapter: o What is the streambuf protected interface? o Declarations for the streambuf protected interface in iostream.h o Examining pointers in the protected interface o Setting pointers in the protected interface o Other nonvirtual members o Virtual member functions ═══ 4.2.1. What Is the streambuf Protected Interface? ═══ Although streambuf is not defined as a virtual base class, you can think of it as one. You should not create objects of the streambuf class itself, but you can use it in the following ways: o As a base class to implement your own specialized stream buffers. In this sense you can think of streambuf as a virtual base class. The streambuf class only provides the basic functions needed to manipulate characters in a stream buffer. The filebuf, strstreambuf, and stdiobuf classes contain functions that handle the interface with the standard ultimate consumers and producers. If you want to perform more sophisticated operations, or if you want to use other ultimate consumers and ultimate producers, you will have to create your own class derived from streambuf. This chapter describes the members of the streambuf class that you need to know about if you want to create a class derived from streambuf. Collectively, these members are called the protected interface of the streambuf class. o Through a predefined class derived from streambuf. This use of the streambuf class is described in streambuf Public Interface. There are two kinds of functions in the protected interface described in this chapter: o Nonvirtual member functions, which manipulate streambuf objects at a level of detail that would be inappropriate in the public interface. o Virtual member functions, which permit classes that you derive from streambuf to customize their operations depending on the ultimate producer or ultimate consumer. When you define the virtual functions in your derived classes, you must ensure that these definitions fulfill the conditions stated in the descriptions of the virtual functions. If your definitions of the virtual functions do not fulfill these conditions, objects of the derived class may have unspecified behavior. Although most virtual functions are declared as public members, they are described with the protected interface (with the exception of the destructor for the streambuf class) because they are meant to be overridden in the classes that you derive from streambuf. ═══ 4.2.2. Declarations for the streambuf Protected Interface in iostream.h ═══ You must include the following statement in any file that uses the streambuf protected interface: #include The following is an excerpt from the iostream.h header file that shows the relevant declarations for the protected interface of streambuf. Note that this excerpt only shows the declarations in the streambuf class that are relevant to the protected interface. The declarations for the public interface are listed in Declarations for the streambuf Public Interface in iostream.h. class ios { public: enum io_state { goodbit, eofbit, failbit, badbit, hardfail}; enum open_mode { in, out, ate, app, trunc, nocreate, noreplace, bin, binary=bin} ; enum seek_dir { beg, cur, end } ; // . // . // . }; class streambuf { public: void dbp(); virtual int overflow(int c = EOF); virtual int underflow(); virtual int pbackfail(int c); virtual int sync(); virtual streambuf* setbuf(char* p, int len); streambuf* setbuf(unsigned char* p, int len); streambuf* setbuf(char* p, int len, int count); virtual streampos seekoff(streamoff, seek_dir, int=ios::in|ios::out); virtual streampos seekpos(streampos, int = ios::in|ios::out); virtual int xsgetn(char* s, int n); virtual int xsputn(const char* s, int n); protected: char* base(); char* pbase(); char* pptr(); char* epptr(); char* gptr(); char* egptr(); char* eback(); char* ebuf(); int blen() const; void setp(char* p, char* ep); void setg(char* eb,char* g, char* eg); void pbump(int n); void gbump(int n); void setb(char* b, char* eb, int a = 0 ); int unbuffered() const; void unbuffered(int unb); int allocate(); virtual int doallocate(); }; Note: xsgetn() and xsputn() are for the internal use of the I/O Stream Library. They are declared in iostream.h and listed above, but you should not use them directly. ═══ 4.2.3. Functions That Return Pointers in the Protected Interface ═══ This section describes the functions in the protected interface of streambuf that return pointers to boundaries of areas in a stream buffer. Note: The following descriptions assume that the functions are called as part of an object called dsb which is an object of a class that is derived from streambuf. The following functions are described: o base - Return pointer to beginning of stream buffer o eback - Return pointer to beginning of putback area o ebuf - Return pointer to end of stream buffer o egptr - Return pointer to end of get area o epptr - Return pointer to end of put area o gptr - Return pointer to beginning of get area o pbase - Return pointer to beginning of space available for put area o pptr - Return pointer to beginning of put area ═══ 4.2.3.1. base - Return Pointer to Beginning of Stream Buffer ═══ Class: streambuf (protected interface) char* base(); base() returns a pointer to the first byte of the stream buffer. The stream buffer consists of the space between the pointer returned by base() and the pointer returned by ebuf(). ═══ 4.2.3.2. eback - Return Pointer to Beginning of Putback Area ═══ Class: streambuf (protected interface) char* eback(); eback() returns a pointer to the lower bound of the space available for the get area of dsb. The space between the pointer returned by eback() and the pointer returned by gptr() is available for putback. ═══ 4.2.3.3. ebuf - Return Pointer to End of Stream Buffer ═══ Class: streambuf (Protected interface) char* ebuf(); ebuf() returns a pointer to the byte after the last byte of the stream buffer. ═══ 4.2.3.4. egptr - Return Pointer to End of Get Area ═══ Class: streambuf (Protected interface) char* egptr(); egptr() returns a pointer to the byte after the last byte of the get area of dsb. ═══ 4.2.3.5. epptr - Return Pointer to End of Put Area ═══ Class: streambuf (Protected interface) char* epptr(); epptr() returns a pointer to the byte after the last byte of the put area of dsb. ═══ 4.2.3.6. gptr - Return Pointer to Beginning of Get Area ═══ Class: streambuf (Protected interface) char* gptr(); gptr() returns a pointer to the first byte of the get area of dsb. The get area consists of the space between the pointer returned by gptr() and the pointer returned by egptr(). Characters are extracted from the stream buffer beginning at the character pointed to by gptr(). ═══ 4.2.3.7. pbase - Return Pointer to Beginning of Space Available for Put Area ═══ Class: streambuf (Protected interface) char* pbase(); pbase() returns a pointer to the beginning of the space available for the put area of dsb. Characters between the pointer returned by pbase() and the pointer returned by pptr() have been stored in the stream buffer, but they have not been consumed by the ultimate consumer. ═══ 4.2.3.8. pptr - Return Pointer to Beginning of Put Area ═══ Class: streambuf (Protected interface) char* pptr(); pptr() returns a pointer to the beginning of the put area of dsb. The put area consists of the space between the pointer returned by pptr() and the pointer returned by epptr(). ═══ 4.2.4. Functions That Set Pointers in the Protected Interface ═══ This section describes the functions in the protected interface of streambuf that set the boundaries of areas in a stream buffer. The values of these boundaries are returned by the functions described in Functions That Return Pointers in the Protected Interface. Note: The following descriptions assume that the functions are called as part of an object called dsb which is an object of a class that is derived from streambuf. The following functions are described: o setb - Set boundaries of stream buffer o setp - Set boundaries of put area o setg - Set boundaries of get area ═══ 4.2.4.1. setb - Set Boundaries of Stream Buffer ═══ Class: streambuf (Protected interface) void setb(char* startbuf, char* endbuf, int delbuf = 0); setb() sets the beginning of the stream buffer (the pointer returned by dsb.pbase()) to the position pointed to by startbuf, and sets the end of the stream buffer (the pointer returned by dsb.ebuf()) to the position pointed to by endbuf. If delbuf is a nonzero value, the stream buffer will be deleted when setb() is called again. If startbuf and endbuf are both equal to 0, no stream buffer is established. If startbuf is not equal to 0, a stream buffer is established, even if endbuf is less than startbuf. If this is the case, the stream buffer has length zero. ═══ 4.2.4.2. setp - Set Boundaries of Put Area ═══ Class: streambuf (Protected interface) void setp(char* startput, char* endput); setp() sets the beginning of the put area of dsb (the pointer returned by dsb.pptr()) to the position pointed to by startput, and sets the end of the put area (the pointer returned by dsb.epptr()) to the position pointed to by endput. ═══ 4.2.4.3. setg - Set Boundaries of Get Area ═══ Class: streambuf (Protected interface) void setg(char* startput, char* startget, char* endget); setg() sets the beginning of the get area of dsb (the pointer returned by dsb.gptr()) to startget, and sets the end of the get area (the pointer returned by dsb.egptr()) to endget. setg() also sets the beginning of the area available for putback (the pointer returned by dsb.eback()) to startput. ═══ 4.2.5. Other NonVirtual Member Functions in the Protected Interface ═══ This section describes the remaining nonvirtual member functions that make up the protected interface of streambuf. Note: The following descriptions assume that the functions are called as part of an object called dsb which is an object of a class that is derived from streambuf. The following functions are described: o allocate - Set up a stream buffer o blen - Return length of stream buffer o dbp - Record stream buffer status o gbump - Move beginning of get area o pbump - Move beginning of put area o unbuffered - Buffering state ═══ 4.2.5.1. allocate - Set Up a Stream Buffer ═══ Class: streambuf (Protected interface) int allocate(); allocate() attempts to set up a stream buffer. allocate() returns the following values: o 0 if dsb already has a stream buffer set up (that is, dsb->base() returns a nonzero value), or if unbuffered() returns a nonzero value. allocate() does not do any further processing if it returns 0. o 1 if allocate() does set up a stream buffer. o EOF if the attempt to allocate space for the stream buffer fails. allocate() is not called by any other nonvirtual member function of streambuf. ═══ 4.2.5.2. blen - Return Length of Stream Buffer ═══ Class: streambuf (Protected interface) int blen() const; blen() returns the length (in bytes) of the stream buffer. ═══ 4.2.5.3. dbp - Record Stream Buffer Status ═══ Class: streambuf (Protected interface) void dbp(); dbp() writes to standard output the values returned by the following functions: o base() o eback() o ebuf() o egptr() o epptr() o gptr() o pptr() dbp() is intended for debugging. streambuf does not specify anything about the form of the output. dbp() is considered part of the protected interface because the information that it prints can only be understood in relation to that interface. It is declared as a public function so that it can be called anywhere during debugging. The following example shows the output produced by dbp() when it is called as part of a filebuf object: #include void main() { cout << "Here is some sample output." << endl; cout.rdbuf()->dbp(); } If you compile and run this example, your output will look like this: Here is some sample output. buf at 0x90210, base=0x91010, ebuf=0x91410, pptr=0x91010, epptr=0x91410, eback=0, gptr=0, egptr=0 ═══ 4.2.5.4. gbump - Move Beginning of Get Area ═══ Class: streambuf (Protected interface) void gbump(int offset); gbump() offsets the beginning of the get area by the value of offset. The value of offset can be positive or negative. gbump() does not check to see if the new value returned by gptr() is valid. The beginning of the get area is equal to the value returned by gptr(). ═══ 4.2.5.5. pbump - Move Beginning of Put Area ═══ Class: streambuf (Protected interface) void pbump(int offset); pbump() offsets the beginning of the put area by the value of offset. The value of offset can be positive or negative. pbump() does not check to see if the new value returned by pptr() is valid. The beginning of the put area is equal to the value returned by pptr(). ═══ 4.2.5.6. unbuffered - Buffering State ═══ Class: streambuf (Protected interface) int unbuffered() const; void unbuffered(int buffstate); unbuffered() manipulates the private streambuf variable called the buffering state. If the buffering state is nonzero, a call to allocate() does not set up a stream buffer. There are two versions of unbuffered(). The version of unbuffered() that takes no arguments returns the current value of the buffering state. The version that takes an argument, buffstate, changes the value of the buffering state to buffstate. ═══ 4.2.6. Virtual Member Functions in the Protected Interface ═══ This section describes the virtual functions in the protected interface of streambuf. Although these virtual functions have default definitions in streambuf, they can be overridden in classes that are derived from streambuf. The following descriptions state the default definition of each function and the expected behavior for these functions in classes where they are overridden. Note: The following descriptions assume that the functions are called as part of an object called dsb, which is an object of a class that is derived from streambuf. The following functions are described: o doallocate - Allocate space for a stream buffer o overflow - Clear put area o pbackfail - Deal with full putback area o seekoff - Reposition external get or put pointer o seekpos - Reposition external get or put pointer o setbuf - Set up stream buffer o sync - Synchronize stream buffer and ultimate producer or ultimate consumer o underflow - Fill get area. ═══ 4.2.6.1. doallocate - Allocate Space for a Stream Buffer ═══ Class: streambuf (Protected interface) virtual int doallocate(); doallocate() is called when allocate() determines that space is needed for a stream buffer. The default definition of doallocate() attempts to allocate space for a stream buffer using the operator new. If you define your own version of doallocate(), it must call setb() to provide space for a stream buffer or return EOF if it cannot allocate space. doallocate() should only be called if unbuffered() and base() return zero. ═══ 4.2.6.2. overflow - Clear Put Area ═══ Class: streambuf (Protected interface) virtual int overflow(int c = EOF); overflow() is called when the put area is full, and an attempt is made to store another character in it. overflow() may be called at other times. The default definition of overflow() is compatible with the AT&T C++ Language System Release 1.2 version of the stream package, but it is not considered part of the current I/O Stream Library. Thus, the default definition of overflow() should not be used, and every class derived from streambuf should define overflow() itself. The definition of overflow() in your classes derived from streambuf should cause the ultimate consumer to consume the characters in the put area, call setp() to establish a new put area, and store the argument c in the put area if c does not equal EOF. overflow() should return EOF if an error occurs, and it should return a value not equal to EOF otherwise. ═══ 4.2.6.3. pbackfail - Deal With Full Putback Area ═══ Class: streambuf (Protected interface) virtual int pbackfail(int c); pbackfail() is called when both of the following conditions are true: o An attempt has been made to put back a character. o There is no room in the putback area. The pointer returned by eback() equals the pointer returned by gptr(). The default definition of pbackfail() returns EOF. If you define pbackfail() in your own classes, your definition of pbackfail() should attempt to deal with the full putback area by, for instance, repositioning the get pointer of the ultimate producer. If this is possible, pbackfail() should return the argument c. If not, pbackfail() should return EOF. ═══ 4.2.6.4. seekoff - Reposition External Get or Put Pointer ═══ Class: streambuf (Protected interface) virtual streampos seekoff(streamoff so, seek_dir dir, int mode = ios::in|ios::out); seekoff() repositions the get or put pointer of the ultimate producer or ultimate consumer. seekoff() does not change the values returned by dsb.gptr() or dsb.pptr(). The default definition of seekoff() returns EOF. If you define your own seekoff() function, it should return EOF if the derived class does not support repositioning. If the class does support repositioning, seekoff() should return the new position of the affected pointer, or EOF if an error occurs. so is an offset from a position in the ultimate producer or ultimate consumer. dir is a position in the ultimate producer or ultimate consumer. dir can have the following values: o ios::beg: the beginning of the ultimate producer or ultimate consumer o ios::cur: the current position in the ultimate producer or ultimate consumer o ios::end: the end of the ultimate producer or ultimate consumer. The new position of the affected pointer is the position specified by dir offset by the value of so. If you derive your own classes from streambuf, certain values of dir may not be valid depending on the nature of the ultimate consumer or producer. If ios::in is set in mode, the seekoff() should modify the get pointer. If ios::out is set in mode, the put pointer should be modified. If both ios::in and ios::out are set, both the get pointer and the put pointer should be modified. ═══ 4.2.6.5. seekpos - Reposition External Get or Put Pointer ═══ Class: streambuf (Protected interface) virtual streampos seekpos(streampos pos, int mode = ios::in|ios::out); seekpos() repositions the get or put pointer of the ultimate producer or ultimate consumer to the position pos. If ios::in is set in mode, the get pointer is repositioned. If ios::out is set in mode, the put pointer is repositioned. If both ios::in and ios::out are set, both the get pointer and the put pointer are affected. seekpos() does not change the values returned by dsb.gptr() or dsb.pptr(). The default definition of seekpos() returns the return value of the function seekoff(streamoff(pos), ios::beg, mode). Thus, if you want to define seeking operations in a class derived from streambuf, you can define seekoff() and use the default definition of seekpos(). If you define seekpos() in a class derived from streambuf, seekpos() should return EOF if the class does not support repositioning or if pos points to a position equal to or greater than the end of the stream. If not, seekpos() should return pos. ═══ 4.2.6.6. setbuf - Set Up Stream Buffer ═══ Class: streambuf (Protected interface) virtual streambuf* setbuf(char* ptr, int len); streambuf* setbuf(unsigned char* ptr, int len); streambuf* setbuf(char* ptr, int len, int count); There are three versions of setbuf(). The two versions that take two arguments set up a stream buffer consisting of the array of bytes starting at ptr with length len. The version of setbuf() that takes three arguments is obsolete. The I/O Stream Library includes it to be compatible with AT&T C++ Language System Release 1.2. The default definition of setbuf() sets up the stream buffer if the streambuf object does not already have a stream buffer. If you define setbuf() in a class derived from streambuf, setbuf() can either accept or ignore a request for an unbuffered streambuf object. The call to setbuf() is a request for an unbuffered streambuf object if ptr equals 0 or len equals 0. setbuf() should return a pointer to sb if it accepts the request, and 0 otherwise. ═══ 4.2.6.7. sync - Synchronize Stream Buffer and Ultimate Producer or Ultimate Consumer ═══ Class: streambuf (Protected interface) virtual int sync(); sync() synchronizes the stream buffer with the ultimate producer or the ultimate consumer. The default definition of sync() returns 0 if either of the following conditions is true: o The get area is empty and there are no characters waiting to go to the ultimate consumer o No stream buffer has been allocated for sb. Otherwise, sync() returns EOF. If you define sync() in a class derived from streambuf, it should send any characters that are stored in the put area to the ultimate consumer, and (if possible) send any characters that are waiting in the get area back to the ultimate producer. When sync() returns, both the put area and the get area should be empty. sync() should return EOF if an error occurs. ═══ 4.2.6.8. underflow - Fill Get Area ═══ Class: streambuf (Protected interface) virtual int underflow(); underflow() takes characters from the ultimate producer and puts them in the get area. The default definition of underflow() is compatible with the AT&T C++ Language System Release 1.2 version version of the stream package, but it is not considered part of the current I/O Stream Library. Thus, the default definition of underflow() should not be used, and every class derived from streambuf should define underflow() itself. If you define underflow() in a class derived from streambuf, it should return the first character in the get area if the get area is not empty. If the get area is empty, underflow() should create a get area that is not empty and return the next character. If no more characters are available in the ultimate producer, underflow() should return EOF and leave the get area empty. ═══ 4.3. streambuf Public Interface ═══ This chapter describes the public interface of the streambuf class. The public interface consists of the public member functions of streambuf that give you direct access to the predefined classes that are derived from streambuf. The streambuf class implements the concept of stream buffers. A stream buffer acts as a buffer between the source or target of data and the member functions of the classes derived from ios (such as istream and ostream) that format this data. See Stream Buffers for a more detailed description of stream buffers. The following topics are described in this chapter: o What Is the streambuf Public Interface o Declarations for the streambuf public interface in iostream.h o Public members of the streambuf public interface ═══ 4.3.1. What Is the streambuf Public Interface? ═══ Although streambuf is not defined as a virtual base class, you can think of it as one. You should not create objects of the streambuf class itself, but you can use it in the following ways: o Through a predefined class derived from streambuf. You can use objects of filebuf, strstreambuf and stdiobuf (the predefined classes that are derived from streambuf) directly as implementations of stream buffers. The public interface consists of the streambuf public member functions that can be called on objects of these predefined classes. This chapter describes the members of the streambuf class that you need to know about if you want to use the predefined classes derived from streambuf to implement stream buffers directly. streambuf itself does not have any facilities for taking characters from the ultimate producer or sending them to the ultimate consumer. The specialized member functions that handle the interface with the ultimate producer and the ultimate consumer are defined in the filebuf, strstreambuf, and stdiobuf classes. o As a base class to implement your own specialized stream buffers. This use of the streambuf class is described in streambuf Protected Interface. o Through a predefined class derived from streambuf. You can use objects of filebuf strstreambuf, and stdiobuf (the predefined classes that are derived from streambuf) directly as implementations of stream buffers. The public interface consists of the streambuf public member functions that can be called on objects of these predefined classes. This chapter describes the members of the streambuf class that you need to know about if you want to use the predefined classes derived from streambuf to implement stream buffers directly. streambuf itself does not have any facilities for taking characters from the ultimate producer or sending them to the ultimate consumer. The specialized member functions that handle the interface with the ultimate producer and the ultimate consumer are defined in the filebuf, strstreambuf, and stdiobuf classes. Except for the destructor for the streambuf class, the virtual functions are described as part of the protected interface. Although most virtual functions are declared public, they are meant to be overloaded in the classes that you derive from streambuf, and thus they are part of the protected interface. ═══ 4.3.2. Declarations for the streambuf Public Interface in iostream.h ═══ You must include the following statement in any file that uses member functions of the public interface of streambuf: #include The following is an excerpt from the iostream.h header file that shows the relevant declarations for the members of the public interface. Note that this excerpt only shows the declarations in the streambuf class that are relevant to the public interface. The declarations for the protected interface are listed in Declarations for the streambuf Protected Interface in iostream.h. class ios { public: enum io_state { goodbit, eofbit, failbit, badbit, hardfail}; enum open_mode { in, out, ate, app, trunc, nocreate, noreplace, bin, binary=bin} ; enum seek_dir { beg, cur, end} ; // . // . // . }; class streambuf { public : streambuf(); streambuf(char* p, int l); streambuf(char* p, int l,int c); virtual ~streambuf(); int in_avail(); int out_waiting(); int sgetc(); int snextc(); int sbumpc(); void stossc(); int sputbackc(char c); int sputc(int c); int sputn(const char* s,int n); int sgetn(char* s,int n); virtual streambuf* setbuf(char* p, int len); streambuf* setbuf(unsigned char* p, int len); streambuf* setbuf(char* p, int len, int count); int optim_in_avail(); int optim_sbumpc(); int pptr_non_null(); }; Note: 1. pptr_non_null(), optim_in_avail(), and optim_sbumpc() are internal implementation functions. They are declared in iostream.h and listed above, but you should not use them directly. 2. Because setbuf() has both virtual and nonvirtual declarations, it is described as part of the protected interface. See setbuf - Set Up Stream Buffer for more details. ═══ 4.3.3. Public Members of the streambuf Public Interface ═══ Note: The following descriptions assume that the functions are called as part of an object fb of a class derived from streambuf. fb could, for example, be an object of the class filebuf. It could also be an strstreambuf object or an stdiobuf object. The following member functions are described: o Constructors for streambuf o Destructor for streambuf o in_avail - Return Number of Characters in Get Area o out_waiting - Return Number of Characters in Put Area o sbumpc - Move Get Pointer One Character o sgetc - Return Character After Get Pointer o sgetn - Return Characters Following Get Pointer o snextc - Return Character Following Get Pointer o sputbackc - Move Get Pointer Back One Character o sputc - Store Character After Put Pointer o sputn - Store Characters After Put Pointer o stossc - Move Get Pointer Forward One Character ═══ 4.3.3.1. Constructors for streambuf ═══ Class: streambuf (Public interface) streambuf(); streambuf(char* buffer, int len); streambuf(char* buffer, int len, int c); There are three versions of the constructor for streambuf. The version with no arguments constructs an empty stream buffer corresponding to an empty sequence. The values returned by base(), eback(), ebuf(), egptr(), epptr(), pptr(), gptr(), and pbase() are initially all zero for this stream buffer. The version with two arguments constructs an empty stream buffer of length len starting at the position pointed to by buffer. The version of the constructor with three arguments is obsolete. It is included in the I/O Stream Library for compatibility with the AT&T C++ Language System Release 1.2. ═══ 4.3.3.2. Destructor for streambuf ═══ Class: streambuf (Public interface) virtual ~streambuf(); The destructor for streambuf calls sync(). If a stream buffer has been set up and ios::alloc is set, sync() deletes the stream buffer. ═══ 4.3.3.3. in_avail - Return Number of Characters in Get Area ═══ Class: streambuf (Public interface) int in_avail(); in_avail() returns the number of characters that are available to be extracted from the get area of fb. You can extract the number of characters equal to the value that in_avail() returns without causing an error. ═══ 4.3.3.4. out_waiting - Return Number of Characters in Put Area ═══ Class: streambuf (Public interface) int out_waiting(); out_waiting() returns the number of characters that are in the put area waiting to be sent to the ultimate consumer. ═══ 4.3.3.5. sbumpc - Move Get Pointer One Character ═══ Class: streambuf (Public interface) int sbumpc(); sbumpc() moves the get pointer past one character and returns the character that it moved past. sbumpc() returns EOF if the get pointer is already at the end of the get area. ═══ 4.3.3.6. sgetc - Return Character After Get Pointer ═══ Class: streambuf (Public interface) int sgetc(); sgetc() returns the character after the get pointer without moving the get pointer itself. If no character is available, sgetc() returns EOF. Note: sgetc() does not change the position of the get pointer. ═══ 4.3.3.7. sgetn - Return Characters Following Get Pointer ═══ Class: streambuf (Public interface) int sgetn(char* ptr, int n); sgetn() extracts the n characters following the get pointer, and copies them to the area starting at the position pointed to by ptr. If there are fewer than n characters following the get pointer, sgetn() takes the characters that are available and stores them in the position pointed to by ptr. sgetn() repositions the get pointer following the extracted characters and returns the number of extracted characters. ═══ 4.3.3.8. snextc - Return Character Following Get Pointer ═══ Class: streambuf (Public interface) int snextc(); snextc() moves the get pointer forward one character and returns the character following the new position of the get pointer. snextc() returns EOF if the get pointer is at the end of the get area either before or after it is moved forward. ═══ 4.3.3.9. sputbackc - Move Get Pointer Back One Character ═══ Class: streambuf (Public interface) int sputbackc(char c); sputbackc() moves the get pointer back one character. The get pointer may simply move, or the ultimate producer may rearrange the internal data structures so that the character c is saved. The argument c must equal the character that precedes the get pointer in the stream buffer. The effect of sputbackc() is undefined if c is not equal to the character before the get pointer. sputbackc() returns EOF if an error occurs. The conditions that cause errors depend on the derived class. ═══ 4.3.3.10. sputc - Store Character After Put Pointer ═══ Class: streambuf (Public interface) int sputc(int c); sputc() stores the argument c after the put pointer and moves the put pointer past the stored character. If there is enough space in the stream buffer, this will extend the size of the put area. sputc() returns EOF if an error occurs. The conditions that cause errors depend on the derived class. ═══ 4.3.3.11. sputn - Store Characters After Put Pointer ═══ Class: streambuf (Public interface) int sputn(const char* s, int n); sputn() stores the n characters starting at s after the put pointer and moves the put pointer to the end of the series. sputn() returns the number of characters successfully stored. If an error occurs, sputn() returns a value less than n. ═══ 4.3.3.12. stossc - Move Get Pointer Forward One Character ═══ Class: streambuf (Public interface) void stossc(); stossc() moves the get pointer forward one character. If the get pointer is already at the end of the get area, stossc() does not move it. ═══ 4.4. ios Class ═══ The ios class maintains the error and format state information for the classes that are derived from it. See The I/O Stream Library Class Hierarchy for a list of these classes. The derived classes support the movement of formatted and unformatted data to and from the stream buffer. This chapter describes the members of the ios class, and thus describes the operations that are common to all the classes that are derived from ios. The following topics are described in this chapter: o Declarations for ios in the iostream.h header file o Constructors and assignment operator for ios o The format state and the error state o Format state variables o Format state flags o Public members of ios for the format state o Public members of ios for user-defined format flags o Public members of ios for the error state o Other ios member functions o Built-in manipulators ═══ 4.4.1. Declarations for ios in iostream.h ═══ You must include the following statement in any file that uses members of the ios class: #include The following is an excerpt from the iostream.h header file that shows the relevant declarations for the members of ios. Note: In the following excerpt, the values of the enumerators have been omitted. Look at the iostream.h header file if you need to use these values explicitly. class ios { public: enum io_state {goodbit, eofbit, failbit, badbit, hardfail}; enum open_mode { in, out, ate, app, trunc, nocreate, noreplace, bin, binary=bin} ; enum seek_dir {beg, cur, end } ; enum {skipws, left, right, internal, dec, oct, hex, showbase, showpoint, uppercase, showpos, scientific, fixed, unitbuf, stdio }; ios(streambuf*); virtual ~ios() ; static const long basefield; /* dec|oct|hex */ static const long adjustfield; /* left|right|internal */ static const long floatfield; /* scientific|fixed */ long flags() const; long flags(long f); long setf(long newset, long field); long setf(long); long unsetf(long) int width() const; int width(int w); ostream* tie(ostream* s); ostream* tie(); char fill(char); char fill() const; int precision(int); int precision() const; int rdstate() const; operator void*(); operator const void*() const; int operator!() const; int eof() const; int fail() const; int bad() const; int good() const; void clear(int i =0); streambuf* rdbuf(); long & iword(int); void* & pword(int); static long bitalloc() static int xalloc(); static void sync_with_stdio(); int skip(int i); protected: ios(); void init(streambuf* isb); ostream* x_tie; short x_precision; char x_fill; short x_width; private: ios(ios& ioa); void operator=(ios& iob); }; ios& dec(ios&); ios& hex(ios&); ios& oct(ios&); istream& ws(istream&); ostream& endl(ostream& i); ostream& ends(ostream& i); ostream& flush(ostream&); Note: iostream.h contains private declarations for an assignment operator and a copy constructor. iostream.h includes these declaration for compatibility with AT&T C++ Language System Release 1.2. The declarations are private to prevent ios objects from being copied. ═══ 4.4.2. Constructors and Assignment Operator for ios ═══ public: ios(streambuf* sb); protected: ios(); init(streambuf* isb); private: ios(ios& ioa); void operator=(ios& iob); There are three versions of the ios constructor. The version that is declared public takes a single argument that is a pointer to the streambuf object that becomes associated with the constructed ios object. If this pointer is equal to 0, the result is undefined. The version of the ios constructor that is declared protected takes no arguments. This version is needed because ios is used as a virtual base class for iostream, and therefore the ios class must have a constructor that takes no arguments. If you use this constructor in a derived class, you must use the init() function to associate the constructed ios object with the streambuf object pointed to by the argument isb. Copying of ios objects is not well defined, and for this reason, both the assignment operator and the copy constructor are declared private. Assignment between streams is supported by the istream_withassign, ostream_withassign, and iostream_withassign classes. See istream_withassign Assignment Operator and ostream_withassign Assignment Operator for more details. None of the predefined classes derived from ios has a copy constructor or an assignment operator. Unless you define your own copy constructor or assignment operator for a class that you derive from ios, your class will have neither a copy constructor nor an assignment operator. ═══ 4.4.3. The Format State and the Error State ═══ Each ios object has a format state and an error state. The format state is a collection of flags and variables that can be set to control the details of formatting operations for input and output. The error state is a collection of flags that records whether any errors have taken place in the processing of the ios object. It also records whether the end of an input stream has been reached. You can view and set the format state and the error state using the functions described in this chapter. ═══ 4.4.4. Format State Variables ═══ The format state is a collection of format flags and format variables that control the details of formatting for input and output operations. This section describes the format variables. The format variables have the following declarations: short x_precision; char x_fill; short x_width; They are used in the following manner: o x_precision is the number of significant digits in the representation of floating-point values. Its default value is 6. o x_fill is the character that is used to pad values that do not require the width of an entire field for their representation. Its default value is a space character. o x_width is the minimum width of a field. Its default value is 0. ═══ 4.4.5. Format State Flags ═══ The format flags have the following declaration in iostream.h: enum { skipws, left, right, internal, dec, oct, hex, showbase, showpoint, uppercase, showpos, scientific, fixed, unitbuf, stdio } ; The following list shows the formatting features and the format flags that control them: o Whitespace and padding: ios::skipws, ios::left, ios::right, ios::internal o Base conversion: ios::dec, ios::hex, ios::oct, ios::showbase o Integral formatting: ios::showpos o Floating-point formatting: ios::fixed, ios::scientific, ios::showpoint o Uppercase and lowercase: ios::uppercase o Buffer flushing: ios::stdio, ios::unitbuf The following sections describe these formatting features in detail. Mutually Exclusive Format Flags describes the flags that produce unpredictable results if they are set at the same time. ═══ 4.4.5.1. Whitespace and Padding ═══ Class: ios The following format state flags control whitespace and padding characters: o skipws: if ios::skipws is set, whitespace will be skipped on input. If it is not set, whitespace is not skipped. If ios::skipws is not set, the arithmetic extractors will signal an error if you attempt to read an integer or floating-point value that is preceded by whitespace. ios::failbit is set, and extraction ceases until it is cleared. This is done to avoid the looping problems that could occur otherwise. If the following program is run with an input file that contains integer values separated by spaces, ios::failbit is set after the first integer value is read, and the program halts. If the program did not call fail() at the beginning of the while loop to test if ios::failbit is set, it would loop indefinitely. #include void main() { fstream f("spadina.dat", ios::in); f.unsetf(ios::skipws); int i; while (!f.eof() && !f.fail()) { f >> i; cout << i; } } o left: if ios::left is set, the value is left-justified. Fill characters are added after the value. o right: if ios::right is set, the value is right-justified. Fill characters are added before the value. o internal: if ios::internal is set, the fill characters are added after any leading sign or base notation, but before the value itself. ═══ 4.4.5.2. Base Conversion ═══ Class: ios The manipulators ios::dec, ios::oct, and ios::hex (see Built-In Manipulators for ios for more details) have the same effect as the flags ios::dec, ios::oct, and ios::hex, respectively. o dec: if ios::dec is set, the conversion base is 10. o oct: if ios::oct is set, the conversion base is 8. o hex: if ios::hex is set, the conversion base is 16. o showbase: if ios::showbase is set, the operation that inserts values converts them to an external form that can be read according to the C++ lexical conventions for integral constants. By default, ios::showbase is unset. ═══ 4.4.5.3. Integral Formatting ═══ Class: ios o showpos: if ios::showpos is set, the operation that inserts values places a positive sign "+" into decimal conversions of positive integral values. ═══ 4.4.5.4. Floating-Point Formatting ═══ Class: ios The following format flags control the formatting of floating-point values: o showpoint: if ios::showpoint is set, trailing zeros and a decimal point appear in the result of a floating-point conversion. This flag has no effect if either ios::scientific or ios::fixed is set. o scientific: if ios::scientific is set, the value is converted using scientific notation. In scientific notation, there is one digit before the decimal point and the number of digits following the decimal point depends on the value of ios::x_precision. The default value for ios::x_precision is 6. If ios::uppercase is set, an uppercase "E" precedes the exponent. Otherwise, a lowercase "e" precedes the exponent. o fixed: if ios::fixed is set, floating point values are converted to fixed notation with the number of digits after the decimal point equal to the value of ios::x_precision (or 6 by default). If neither ios::fixed nor ios::scientific is set, the representation of floating-point values depends on their values and the number of significant digits in the representation equals ios::x_precision. Floating-point values are converted to scientific notation if the exponent resulting from a conversion to scientific notation is less than -4 or greater than or equal to the value of ios::x_precision. Otherwise, floating-point values are converted to fixed notation. If ios::showpoint is not set, trailing zeros are removed from the result and a decimal point appears only if it is followed by a digit. ios::scientific and ios::fixed are collectively identified by the static member ios::floatfield. The following example shows some of the possibilities for formatting a floating-point value: #include void main() { float fp = 3.14f; // // print the value with an uppercase "E" in the exponent // cout << setiosflags(ios::scientific|ios::uppercase); cout << "Here is a floating-point value " << fp << endl; // // print the value with a lowercase "e" in the exponent // cout << resetiosflags(ios::uppercase); cout << "Here is a floating-point value " << fp << endl; // // print the value in fixed format // cout << resetiosflags(ios::scientific) << setiosflags(ios::fixed); cout << "Here is a floating-point value " << fp << endl; } This program produces the following output: Here is a floating-point value 3.140000E+00 Here is a floating-point value 3.140000e+00 Here is a floating-point value 3.140000 ═══ 4.4.5.5. Uppercase and Lowercase ═══ Class: ios o uppercase: if ios::uppercase is set, the operation that inserts values uses an uppercase "E" for floating point values in scientific notation. In addition, the operation that inserts values stores hexadecimal digits "A" to "F" in uppercase and places an uppercase "X" before hexadecimal values when ios::showbase is set. If ios::uppercase is not set, a lowercase "e" introduces the exponent in floating-point values, hexadecimal digits "a" to "f" are stored in lowercase, and a lowercase "x" is inserted before hexadecimal values when ios::showbase is set. ═══ 4.4.5.6. Buffer Flushing ═══ Class: ios o unitbuf: if ios::unitbuf is set, ostream::osfx() performs a flush after each insertion. The attached stream buffer is unit buffered. o stdio: this flag is used internally by sync_with_stdio(). You should not use ios::stdio directly. If you want to combine I/O Stream Library input and output with stdio.h input and output, you should use sync_with_stdio(). See sync_with_stdio - Attach stdiobuf Object to Predefined Streams for more details on sync_with_stdio(). ═══ 4.4.5.7. Mutually Exclusive Format Flags ═══ Class: ios If you specify conflicting flags the results are unpredictable. For example, the results will be unpredictable if you set both ios::left and ios::right in the format state of iosobj. You should set only one flag in each set of the following three sets: o ios::left, ios::right, ios::internal o ios::dec, ios::oct, ios::hex o ios::scientific, ios::fixed. ═══ 4.4.6. Public Members of ios for the Format State ═══ You can use the member functions listed below to control the format state of an ios object. Note: The following descriptions assume that the functions are called as part of an ios object called iosobj. The following functions are described: o fill - Set the fill character o flags - Set format flags o precision - Set the precision o setf - Set specific format flags o skip - Set ios::skipws format flag o unsetf - Turn off format flags o width - Set field width ═══ 4.4.6.1. fill - Set the Fill Character ═══ Class: ios char fill() const; char fill(char fillchar); There are two versions of fill(). fill() with no arguments returns the value of ios::x_fill in the format state of iosobj. fill() with an argument fillchar sets ios::x_fill to be equal to fillchar. ios::x_fill is the character used as padding if the field is wider than the representation of a value. The default value for ios::x_fill is a space. The ios::left, ios::right, and ios::internal flags determine the position of the fill character. You can also use the parameterized manipulator setfill to set the value of ios::x_fill. ═══ 4.4.6.2. flags - Set Format Flags ═══ Class: ios long flags() const; long flags(long flagset); There are two versions of flags(). The version that takes no arguments returns the value of the flags that make up the current format state. The version that takes an argument sets the flags in the format state to the settings specified in flagset and returns the value of the previous settings of the format flags. ═══ 4.4.6.3. precision - Set the Precision ═══ Class: ios int precision() const; int precision(int prec); There are two versions of precision(). The version that takes no arguments returns the value of ios::x_precision. The version that takes one argument sets the value of ios::x_precision to prec and returns the previous value. The value of prec must be greater than 0. If the value is nonpositive, the value of ios::x_precision is set to the default value, 6. ios::x_precision controls the number of significant digits when floating-point values are inserted. If neither ios::scientific nor ios::fixed is set, ios::x_precision specifies the number of significant digits in the floating-point value that is being inserted. If, in addition, ios::showpoint is not set, all trailing zeros are removed and a decimal point only appears if it is followed by digits. If either ios::scientific or ios::fixed is set, ios::x_precision specifies the number of digits following the decimal point. You can also use the parameterized manipulator setprecision to set ios::x_precision. ═══ 4.4.6.4. setf - Set Specific Format Flags ═══ Class: ios long setf(long newset); long setf(long newset, long field); There are two versions of setf(). The version that takes one argument is accumulative. It sets the format flags that are marked in newset, without affecting flags that are not marked in newset, and returns the previous value of the format state. You can also use the parameterized manipulator setiosflags to set the format flags to a specific setting. The version of setf() that takes two arguments clears the format flags specified in field, sets the format flags specified in newset, and returns the previous value of the format state. For example, to change the conversion base in the format state to ios::hex, you could use a statement like this: s.setf(ios::hex, ios::basefield); In this statement, ios::basefield specifies the conversion base as the format flag that is going to be changed, and ios::hex specifies the new value for the conversion base. If newset equals 0, all of the format flags specified in field are cleared. You can also use the parameterized manipulator resetiosflags to clear format flags. The following example demonstrates the use of flags(), setf(), and unsetf(). The main() function changes the flags as follows: 1. The original settings of the format state flags are determined, using flags(). 2. ios::fixed is set, and all other flags are cleared, using flags(ios::fixed). 3. ios::adjustfield is set to ios::right, without affecting other fields, using setf(ios::right). 4. ios::floatfield is set to ios::scientific without affecting other fields, using setf(ios::scientific | ios::left,ios::floatfield). ios::left does not affect the format state here because the second argument to setf() does not include ios::adjustfield. There would be no point in coding a call this way in a real application, but it illustrates the effect of using a mask for the second argument of setf(). 5. The original format state is restored, by calling flags() with an argument of originalFlags, which contains the format state determined in step 1. The function showFlags() determines and displays the current flag settings. It obtains the value of the settings using flags(), then excludes ios::oct from the result before displaying the result in octal. This exclusion is done in order to display the result in octal without causing the octal setting for ios::basefield to show up in the program's output. /* Program to demonstrate use of flags(), flags(long), setf(long), and setf(long,long). */ #include void showFlags() { // save altered flag settings, but clear ios::oct from them long flagSettings = cout.flags() & (~ios::oct) ; // display those flag settings in octal cout << oct << flagSettings << endl; } void main () { // get and display current flag settings using flags() cout << "flags(): "; long originalFlags = cout.flags(); showFlags(); // change format state using flags(long) cout << "flags(ios::fixed): "; cout.flags(ios::fixed); showFlags(); // change adjust field using setf(long) cout << "setf(ios::right): "; cout.setf(ios::right); showFlags(); // change floatfield using setf(long, long) cout << "setf(ios::scientific | ios::left,\n" << "ios::floatfield): "; cout.setf(ios::scientific | ios::left,ios::floatfield); showFlags(); // reset to original setting cout << "flags(originalFlags): "; cout.flags(originalFlags); showFlags(); } This example produces the following output: flags(): 21 flags(ios::fixed): 10000 setf(ios::right): 10004 setf(ios::scientific | ios::left, ios::floatfield): 4004 flags(originalFlags): 21 Note: If you set conflicting flags the results are unpredictable. ═══ 4.4.6.5. skip - Set ios::skipws Format Flag ═══ Class: ios int skip(int i); skip() sets the format flag ios::skipws if the value of the argument i does not equal 0. If i does equal 0, ios::skipws is cleared. skip() returns a value of 1 if ios::skipws was set prior to the call to skip(), and returns 0 otherwise. ═══ 4.4.6.6. unsetf - Turn Off Format Flags ═══ Class: ios long unsetf(long oflags); unsetf() turns off the format flags specified in oflags and returns the previous format state. ═══ 4.4.6.7. width - Set Field Width ═══ Class: ios int width() const; int width(int fwidth); There are two versions of width(). The version that takes no arguments returns the value of the current setting of the format state field width variable, ios::x_width. If the value of ios::x_width is smaller than the space needed for the representation of the value, the full value is still inserted. The version of width() that takes one argument fwidth sets ios::x_width to the value of fwidth and returns the previous value. The default field width is 0. When the value of ios::x_width is 0, the operations that insert values only insert the characters needed to represent a value. If the value of ios::x_width is greater than 0, the characters needed to represent the value are inserted. Then fill characters are inserted, if necessary, so that the representation of the value takes up the entire field. ios::x_width only specifies a minimum width, not a maximum width. If the number of characters needed to represent a value is greater than the field width, none of the characters is truncated. After every insertion of a numeric value or a string, the value of ios::x_width is reset to 0. After every extraction of a value of one of the following types, the value of ios::x_width is reset to 0: o char* o unsigned char* o signed char* o float, double and long double values o integral values:short, int, long o wchar_t * Extractions of any other types do not affect ios::x_width. You can also use the parameterized manipulator setw to set the field width. ═══ 4.4.7. Public Members of ios for User-Defined Format Flags ═══ In addition to the flags described in Format State Flags, you can also use the ios member functions listed in this section to define additional format flags or variables in classes that you derive from ios. The following member functions are described: o bitalloc - Create bit set o iword - Return reference to user-defined flag o pword - Return reference to user-defined flag o xalloc - Return index to format state variables. ═══ 4.4.7.1. bitalloc - Create Bit Set ═══ Class: ios static long bitalloc(); bitalloc() is a static function that returns a long value with a previously unallocated bit set. You can use this long value as an additional flag, and pass it as an argument to the format state member functions. When all the bits are exhausted, bitalloc() returns 0. ═══ 4.4.7.2. iword - Return Reference to User-Defined Flag ═══ Class: ios long& iword(int i); iword() returns a reference to the ith user-defined flag, where i is an index returned by xalloc(). iword() allocates space for the user-defined flag. If the allocation fails, iword() sets ios::failbit. ═══ 4.4.7.3. pword - Return Reference to User-Defined Flag ═══ Class: ios void* & pword(int i); pword() returns a reference to a pointer to the ith user-defined flag, where i is an index returned by xalloc(). pword() allocates space for the user-defined flag. If the allocation fails, pword() sets ios::failbit. pword() is the same as iword() except that the two functions return different types. ═══ 4.4.7.4. xalloc - Return Index to Format State Variables ═══ Class: ios static int xalloc(); xalloc() is a static function that returns an unused index into an array of words available for use as format state variables by classes derived from ios. xalloc() simply returns a new index; it does not do any allocation. iword() and pword() do the allocation, and if the allocation fails, they set ios::failbit. You should check ios::failbit after calling iword() or pword(). ═══ 4.4.8. Public Members of ios for the Error State ═══ The error state is an enumeration that records the errors that take place in the processing of ios objects. It has the following declaration: enum io_state { goodbit, eofbit, failbit, badbit, hardfail }; The error state is manipulated using the ios member functions described in this section. Note: 1. hardfail is a flag used internally by the I/O Stream Library. Do not use it. 2. The following descriptions assume that the functions are called as part of an ios object called iosobj. The following member functions are described: o bad - Check ios::badbit o clear - Clear or Set Error State o eof - Check ios::eofbit o fail - Check ios::failbit and ios::badbit o good - Are Any Bits Set o rdstate - Return Error State o Convert ios Object to Pointer Operator void*() o Check ios::failbit and ios::badbit Operator ! ═══ 4.4.8.1. bad - Check ios::badbit ═══ Class: ios int bad() const; bad() returns a nonzero value if ios::badbit is set in the error state of iosobj. Otherwise, it returns 0. ios::badbit is usually set when some operation on the streambuf object that is associated with the ios object has failed. It will probably not be possible to continue input and output operations on the ios object. ═══ 4.4.8.2. clear - Clear or Set Error State ═══ Class: ios void clear(int state=0); clear() changes the error state of iosobj to state. If state equals 0 (its default), all of the bits in the error state are cleared. If you want to set one of the bits without clearing or setting the other bits in the error state, you can bitwise OR the bit you want to set with the current error state. For example, the following statement sets ios::badbit in iosobj and leaves all the other error state bits unchanged: iosobj.clear(ios::badbit|iosobj.rdstate()); ═══ 4.4.8.3. eof - Check ios::eofbit ═══ Class: ios int eof() const; eof() returns a nonzero value if ios::eofbit is set in the error state of iosobj. Otherwise, it returns 0. ios::eofbit is usually set when an EOF has been encountered during an extraction operation. ═══ 4.4.8.4. fail - Check ios::failbit and ios::badbit ═══ Class: ios int fail() const; fail() returns a nonzero value if either ios::badbit or ios::failbit is set in the error state. Otherwise, it returns 0. ═══ 4.4.8.5. good - Are Any Bits Set ═══ Class: ios int good() const; good() returns a nonzero value if no bits are set in the error state of iosobj. Otherwise, it returns 0. ═══ 4.4.8.6. rdstate - Return Error State ═══ Class: ios int rdstate() const; rdstate() returns the current value of the error state of iosobj. ═══ 4.4.8.7. Convert ios Object to Pointer Operator void*() ═══ Class: ios operator void*(); operator const void*() const; The operator void*() converts iosobj to a pointer so that it can be compared to 0. The conversion returns 0 if ios::failbit or ios::badbit is set in the error state of iosobj. Otherwise, a pointer value is returned. This value is not meant to be manipulated as a pointer; the purpose of the operator is to allow you to write statements such as the following: if (cin) cout << "ios::badbit and ios::failbit are not set" << endl; if (cin >> x) cout << "ios::badbit and ios::failbit are not set " << x << " was input" << endl; ═══ 4.4.8.8. Check ios::failbit and ios::badbit Operator ! ═══ Class: ios int operator!() const; The operator !() returns a nonzero value if ios::failbit or ios::badbit is set in the error state of iosobj. This allows you to write statements like this: if (!cin) cout << "either ios::failbit or ios::badbit is set" << endl; else cout << "neither ios::failbit nor ios::badbit is set" << endl; ═══ 4.4.9. Other Members of ios ═══ This section describes the ios member functions that do not deal with the error state or the format state. These descriptions assume that the functions are called as part of an ios object called iosobj. The following functions are described: o rdbuf - Return pointer to associated streambuf object o sync_with_stdio - Attach stdiobuf object to predefined streams o tie - Set the tie variable ═══ 4.4.9.1. rdbuf - Return Pointer to Associated streambuf Object ═══ Class: ios streambuf* rdbuf(); rdbuf() returns a pointer to the streambuf object that is associated with iosobj. This is the streambuf object that was passed as an argument to the ios constructor. ═══ 4.4.9.2. sync_with_stdio - Attach stdiobuf Object to Predefined Streams ═══ Class: ios static void sync_with_stdio(); sync_with_stdio() is a static function that solves the problems that occur when you call functions declared in stdio.h and I/O Stream Library functions in the same program. The first time that you call sync_with_stdio(), it attaches stdiobuf objects to the predefined streams cin, cout, and cerr. After that, input and output using these predefined streams can be mixed with input and output using the corresponding FILE objects (stdin, stdout, and stderr). This input and output is correctly synchronized. If you switch between the I/O Stream Library formatted extraction functions and stdio.h functions, you may find that a byte is "lost". The reason is that the formatted extraction functions for integers and floating-point values keep extracting characters until a non-digit character is encountered. This non-digit character acts as a delimiter for the value that preceded it. It is not part of the value, so putback() is called to return it to the stream buffer. If a C stdio library function, such as getchar(), performs the next input operation, it will begin input at the character after this non-digit character. Thus, this non-digit character is not part of the value extracted by the formatted extraction function, and it is not the character extracted by the C stdio library function. It is "lost". Therefore, you should avoid switching between the I/O Stream Library formatted extraction functions and C stdio library functions whenever possible. sync_with_stdio() makes cout and cerr unit buffered. After you call sync_with_stdio(), the performance of your program could diminish. The performance of your program is affected adversely if you are dealing mostly with relatively short strings. Note: You should use I/O Stream Library functions exclusively for all new code. ═══ 4.4.9.3. tie - Set the tie Variable ═══ Class: ios ostream* tie(); ostream* tie(ostream* os); There are two versions of tie(). The version that takes no arguments returns the value of ios::x_tie, the tie variable. The version that takes one argument os makes the tie variable, ios::x_tie, equal to os and returns the previous value. You can use ios::x_tie to automatically flush the stream buffer attached to an ios object. If ios::x_tie for an ios object is not equal to 0 and the ios object needs more characters or has characters to be consumed, the ostream object pointed to by ios::x_tie is flushed. By default, the tie variables of the predefined streams cin, cerr, and clog all point to the predefined stream cout. For example, the initial return value of cin.tie() is a pointer to cout. ═══ 4.4.10. Built-In Manipulators for ios ═══ The I/O Stream Library provides you with a set of built-in manipulators for ios and the classes derived from it. These manipulators have a specific effect on a stream other than inserting or extracting a value. Manipulators implicitly invoke functions that modify the state of the stream, and they allow you to modify the state of a stream at the same time as you are doing input and output. The syntax for manipulators is consistent with the syntax for input and output. The following is a list of the manipulators and the classes that they apply to: dec istream and ostream hex istream and ostream oct istream and ostream ws istream endl ostream ends ostream flush ostream See Built-In Manipulators for istream for more details on the built-in manipulators for istream. See Built-In Manipulators for ostream for more details on the manipulators for ostream. ═══ 4.5. istream and istream_withassign Class ═══ This chapter describes the istream class and its derived class istream_withassign. The istream member functions allow you to take characters out of the stream buffer that is associated with an istream object. istream_withassign is derived from istream and includes an assignment operator. istream supports two kinds of input: o Unformatted input: characters are taken as a sequence of bytes from the stream buffer that is associated with the istream object. o Formatted input: characters are taken from the stream buffer associated with the istream object, converted to a given type, and stored in a variable of that type. The following topics are described in this chapter: o Declarations for istream and istream_withassign in the iostream.h header file o Constructors for istream o Input prefix function o Public members of istream for formatted input o Public members of istream for unformatted input o Public members of istream for positioning o Other public members of istream o Built-In Manipulators for istream o Public members of istream_withassign ═══ 4.5.1. Declarations for istream and istream_withassign in iostream.h ═══ You must include the following statement in any file that uses member functions of the istream class: #include The following is an excerpt from the iostream.h header file that shows the relevant declarations for the members of istream: class istream : virtual public ios { public: istream(streambuf*); istream(streambuf*, int sk, ostream* t=0); istream(int size ,char*,int sk=1); istream(int fd,int sk=1, ostream* t=0); virtual ~istream(); int ipfx(int noskipws=0); void isfx(); istream& seekg(streampos p); istream& seekg(streamoff o, ios::seek_dir d); streampos tellg(); istream& operator>> (istream& (*f)(istream&)); istream& operator>> (ios& (*f)(ios&) ); istream& operator>>(char*); istream& operator>>(signed char*); istream& operator>>(unsigned char*); istream& operator>>(char& c); istream& operator>>(signed char& c); istream& operator>>(unsigned char& c); istream& operator>>(short&); istream& operator>>(int&); istream& operator>>(long&); istream& operator>>(unsigned short&); istream& operator>>(unsigned int&); istream& operator>>(unsigned long&); istream& operator>>(float&); istream& operator>>(double&); istream& operator>>(long double&); istream& operator>>(streambuf*); istream& operator>>(wchar_t&); istream& operator>>(wchar_t *); istream& rs_complicated(char& c); istream& rs_complicated(signed char& c); istream& rs_complicated(unsigned char& c); istream& get(char* , int lim, char delim='\n'); istream& get(signed char* b,int lim, char delim='\n'); istream& get(unsigned char* b,int lim, char delim='\n'); istream& get(streambuf& sb, char delim ='\n'); istream& get_complicated(char& c); istream& get_complicated(signed char& c); istream& get_complicated(unsigned char& c); istream& get(char& c); istream& get(signed char& c); istream& get(unsigned char& c); int get(); istream& getline(char* b, int lim, char delim='\n'); istream& getline(signed char* b, int lim, char delim='\n'); istream& getline(unsigned char* b, int lim, char delim='\n'); istream& get(wchar_t&); int peek(); istream& ignore(int n=1,int delim=EOF); istream& read(char* s,int n); istream& read(signed char* s,int n); istream& read(unsigned char* s,int n); int gcount(); istream& putback(char c); int sync(); protected: istream(); int do_ipfx(int noskipws); void eatwhite(); }; class istream_withassign : public istream { public: istream_withassign(); virtual ~istream_withassign(); istream_withassign& operator=(istream&); istream_withassign& operator=(streambuf*); }; extern istream_withassign cin; ios& dec(ios&); ios& hex(ios&); ios& oct(ios&); istream& ws(istream&); Note: The following functions have declarations included in the above listing of iostream.h, but they are only for the internal use of the I/O Stream Library. You should not use them directly: o isfx() o rs_complicated() o get_complicated() o do_ipfx() o eatwhite(). ═══ 4.5.2. Constructors for istream ═══ Class: istream istream(streambuf* sb); The istream constructor takes a single argument sb. The constructor creates an istream object that is attached to the streambuf object that is pointed to by sb. The constructor also initializes the format variables to their defaults. The other istream constructor declarations in iostream.h are obsolete; do not use them. ═══ 4.5.3. Input Prefix Function ═══ int ipfx(int need=0); ipfx() checks the stream buffer attached to an istream object to determine if it is capable of satisfying requests for characters. It returns a nonzero value if the stream buffer is ready, and 0 if it is not. The formatted input operator calls ipfx(0), while the unformatted input functions call ipfx(1). If the error state of the istream object is nonzero, ipfx() returns 0. Otherwise, the stream buffer attached to the istream object is flushed if either of the following conditions is true: o need has a value of 0. o The number of characters available in the stream buffer is fewer than the value of need. If ios::skipws is set in the format state of the istream object and need has a value of 0, leading whitespace characters are extracted from the stream buffer and discarded. If ios::hardfail is set or EOF is encountered, ipfx() returns 0. Otherwise, it returns a nonzero value. ═══ 4.5.4. Public Members of istream for Formatted Input ═══ The istream class lets you perform formatted input from a stream buffer using the input operator >>. Consider the following statement, where ins is a reference to an istream object and x is a variable of a built-in type: ins >> x; The input operator >> calls ipfx(0). If ipfx() returns a nonzero value, the input operator extracts characters from the streambuf object that is associated with ins. It converts these characters to the type of x and stores the result in x. The input operator sets ios::failbit if the characters extracted from the stream buffer cannot be converted to the type of x. If the attempt to extract characters fails because EOF is encountered, the input operator sets ios::eofbit and ios::failbit. If the attempt to extract characters fails for another reason, the input operator sets ios::badbit. Even if an error occurs, the input operator always returns ins. The details of conversion depend on the format state of the istream object and the type of the variable x. The input operator may set the width variable ios::x_width to 0, but it does not change anything else in the format state. The input operator is defined for the following types: o Arrays of character values (including signed char and unsigned char) o Other integral values: short, int, long o float, double, and long double values. In addition, the input operator is defined for streambuf objects. The following sections describe the input operator for these types. Note: The following descriptions assume that the input operator is called with the istream object ins on the left side of the operator. ═══ 4.5.4.1. Input Operator for Arrays of Characters ═══ Class: istream istream& operator>>(char* pc); istream& operator>>(signed char* pc); istream& operator>>(unsigned char* pc); istream& operator>>(wchar_t* pwc); For pointers to char, signed char, and unsigned char, the input operator stores characters from the stream buffer attached to ins in the array pointed to by pc. The input operator stores characters until a whitespace character is found. This whitespace character is left in the stream buffer, and the extraction stops. If ios::x_width does not equal zero, a maximum of ios::x_width - 1 characters are extracted. The input operator calls ins.width(0) to reset ios::x_width to 0. For pointers to wchar_t, the input operator stores characters from the stream buffer attached to ins in the array pointed to by pwc. The input operator stores characters until a whitespace character or a wchar_t blank is found. If the terminating character is a whitespace character, it is left in the stream buffer. If it is a wchar_t blank, it is discarded. This is done to avoid returning two bytes to the input stream. For wchar_t* arrays, if ios::width does not equal zero, a maximum of ios::width-1 characters (at 2 bytes each) are extracted. A 2-character space is reserved for the wchar_t terminating null character. Note: The input operators for numeric types and for pointers to char (including pointers to signed char, unsigned char and wchar_t) reset ios::x_width to 0. None of the other input operators affects ios::x_width. All of the output operators, on the other hand, reset ios::x_width to 0. The input operator always stores a terminating null character in the array pointed to by pc or pwc, even if an error occurs. For arrays of wchar_t*, this terminating null character is a wchar_t terminating null character. ═══ 4.5.4.2. Input Operator for char ═══ Class: istream istream& operator>>(char& rc); istream& operator>>(signed char& rc); istream& operator>>(unsigned char& rc); istream& operator>>(wchar_t& rc); For char, signed char, and unsigned char, the input operator extracts a character from the stream buffer attached to ins and stores it in rc. For references to wchar_t, the input operator extracts a wchar_t character from the stream buffer and stores it in wc. If ios::skipsw is set, the input operator skips leading wchar_t spaces as well as leading char white spaces. ═══ 4.5.4.3. Input Operator for Other Integral Values - short, int, long ═══ Class: istream istream& operator>>(short& ir); istream& operator>>(unsigned short& ir); istream& operator>>(int& ir); istream& operator>>(unsigned int& ir); istream& operator>>(long& ir); istream& operator>>(unsigned long& ir); This section describes how the input operator works for references to the integral types: short, unsigned short, int, unsigned int, long, and unsigned long. For these integral types, the input operator extracts characters from the stream buffer associated with ins and converts them according to the format state of ins. The converted characters are then stored in ir. There is no overflow detection on conversion of integral types. The first character extracted from the stream buffer may be a sign (+ or -). The subsequent characters are converted until a non-digit character is encountered. This non-digit character is left in the stream buffer. Which characters are treated as digits depends on the setting of the following format flags: o ios::oct: the characters are converted to an octal value. Characters are extracted from the stream buffer until a character that is not an octal digit (a digit from 0 to 7) is encountered. If ios::oct is set and a signed value is encountered, the value is converted into a decimal value. For example, if the characters "- 45" are encountered in the input stream and ios::oct is set, the decimal value - 37 is actually extracted. o ios::dec: the characters are converted to a decimal value. Characters are extracted from the stream buffer until a character that is not a decimal digit (a digit from 0 to 9) is encountered. o ios::hex: the characters are converted to a hexadecimal value. Characters are extracted from the stream buffer until a character that is not a hexadecimal digit (a digit from 0 to 9 or a letter from "A" to "F", upper or lower case) is encountered. If ios::hex is set and a signed value is encountered, the value is converted into a decimal value. For example, if the characters "-12" are encountered in the input stream and ios::hex is set, the decimal value -18 is actually extracted. If none of these format flags is set, the characters are converted according to the C++ lexical conventions. This conversion depends on the characters that follow the optional sign: o If these characters are "0x" or "0X", the subsequent characters are converted to a hexadecimal value. o If the first character is "0" and the second character is not "x" or "X", the subsequent characters are converted to an octal value. o If neither of these cases is true, the characters are converted to a decimal value. If no digits are available in the stream buffer (other than the "0" in "0X" or "0x" preceding a hexadecimal value), the input operator sets ios::failbit in the error state of ins. ═══ 4.5.4.4. Input Operator for float and double Values ═══ Class: istream istream& operator>>(float& ref); istream& operator>>(double& ref); istream& operator>>(long double& ref); For float, double, and long double values, the input operator converts characters from the stream buffer attached to ins according to the C++ lexical conventions. The following conversions occur for certain string values: o If the value consists of the character strings "inf" or "infinity" in any combination of uppercase and lowercase letters, the string is converted to the appropriate type's representation of infinity. o If the value consists of the character string "nan" in any combination of uppercase and lowercase letters, the string is converted to the appropriate type's representation of a NaN. The resulting value is stored in ref. The input operator sets ios::failbit if no digits are available in the stream buffer or if the digits that are available do not begin a floating-point number. ═══ 4.5.4.5. Input Operator for streambuf Objects ═══ Class: istream istream& operator>>(streambuf* sb); For pointers to streambuf objects, the input operator calls ipfx(0). If ipfx(0) returns a nonzero value, the input operator extracts characters from the stream buffer attached to ins and inserts them in sb. Extraction stops when an EOF character is encountered. The input operator always returns ins. ═══ 4.5.5. Public Members of istream for Unformatted Input ═══ The functions listed in this section allow you to extract characters from a stream buffer as a sequence of bytes. All of these functions call ipfx(1). They only proceed with their processing if ipfx(1) returns a nonzero value. Note: The following descriptions assume that the functions are called as part of an istream object called ins. The following functions are described: o get - Extract characters and store in array o get - Extract characters and store in stream buffer o get - Extract character and store in char o get - Extract character and return it o getline - Extract characters and store in array o ignore - Extract characters and discard them o read - Extract characters and store in array ═══ 4.5.5.1. get - Extract Characters and Store in Array ═══ Class: istream istream& get(char* ptr, int len, char delim='\n'); istream& get(signed char* ptr, int len, char delim='\n'); istream& get(unsigned char* ptr, int len, char delim='\n'); get() with three arguments extracts characters from the stream buffer attached to ins and stores them in the byte array beginning at the location pointed to by ptr and extending for len bytes. The default value of the delim argument is '\n'. Extraction stops when either of the following conditions is true: o delim or EOF is encountered before len-1 characters have been stored in the array. delim is left in the stream buffer and not stored in the array. o len-1 characters are extracted without delim or EOF being encountered. get() always stores a terminating null character in the array, even if it does not extract any characters from the stream buffer. get() sets the ios::failbit if it encounters an EOF character before it stores any characters. ═══ 4.5.5.2. get - Extract Characters and Store in Stream Buffer ═══ Class: istream istream& get(streambuf& sb, char delim='\n'); get() with two arguments extracts characters from the stream buffer attached to ins and stores them in sb. The default value of the delim argument is "\n". Extraction stops when any of the following conditions is true: o An EOF character is encountered. o An attempt to store a character in sb fails. ios::failbit is set in the error state of ins. o delim is encountered. delim is left in the stream buffer attached to ins. ═══ 4.5.5.3. get - Extract Character and Store in char ═══ Class: istream istream& get(char& cref); istream& get(signed char& cref); istream& get(unsigned char& cref); istream& get(wchar_t& cref); get() with a single argument extracts a single character or wchar_t from the stream buffer attached to ins and stores this character in cref. ═══ 4.5.5.4. get - Extract Character and Return It ═══ Class: istream int get(); get() with no arguments extracts a character from the stream buffer attached to ins and returns it. This version of get() returns EOF if EOF is extracted. ios::failbit is never set. ═══ 4.5.5.5. getline - Extract Characters and Store in Array ═══ Class: istream istream& getline(char* ptr, int len, char delim='\n'); istream& getline(signed char* ptr, int len, char delim='\n'); istream& getline(unsigned char* ptr, int len, char delim='\n'); getline() extracts characters from the stream buffer attached to ins and stores them in the byte array beginning at the location pointed to by ptr and extending for len bytes. The default value of the delim argument is "\n". Extraction stops when any one of the following conditions is true: o delim or EOF is encountered before len-1 characters have been stored in the array. getline() extracts delim from the stream buffer, but it does not store delim in the array. o len-1 characters are extracted before delim or EOF is encountered. getline() always stores a terminating null character in the array, even if it does not extract any characters from the stream buffer. getline() sets the ios::failbit for ins if it encounters an EOF character before it stores any characters. getline() is like get() with three arguments, except that get() does not extract the delim character from the stream buffer, while getline() does. ═══ 4.5.5.6. ignore - Extract Characters and Discard Them ═══ Class: istream istream& ignore(int num=1, int delim=EOF); ignore() extracts up to num character from the stream buffer attached to ins and discards them. ignore() will extract fewer than num characters if it encounters delim or EOF. ═══ 4.5.5.7. read - Extract Characters and Store in Array ═══ Class: istream istream& read(char* s, int n); istream& read(signed char* s, int n); istream& read(unsigned char* s, int n); read() extracts n characters from the stream buffer attached to ins and stores them in an array beginning at the position pointed to by s. If EOF is encountered before read() extracts n characters, read() sets the ios::failbit in the error state of ins. You can determine the number of characters that read() extracted by calling gcount() immediately after the call to read(). ═══ 4.5.6. Public Members of istream for Positioning ═══ The following functions are described: o seekg - reposition get pointer of ultimate producer o tellg - return position of get pointer of ultimate producer ═══ 4.5.6.1. seekg - Reposition Get Pointer of Ultimate Producer ═══ Class: istream istream& seekg(streampos sp); istream& seekg(streamoff so, ios::seek_dir dir); seekg() repositions the get pointer of the ultimate producer. seekg() with one argument sets the get pointer to the position sp. seekg() with two arguments sets the get pointer to the position specified by dir with the offset so. dir can have the following values: o ios::beg: the beginning of the stream o ios::cur: the current position of the get pointer o ios::end: the end of the stream If you attempt to set the get pointer to a position that is not valid, seekg() sets ios::badbit. ═══ 4.5.6.2. tellg - Return Position of Get Pointer of Ultimate Producer ═══ Class: istream streampos tellg(); tellg() returns the current position of the get pointer of the ultimate producer. ═══ 4.5.7. Other Public Members of istream ═══ Note: The following descriptions assume that the functions are called as part of an istream object called ins. The following member functions are described: o gcount - Return number of characters extracted o peek - Return next character without extracting it o putback - Put extracted characters back into stream buffer o sync - Synchronize stream buffer and ultimate producer ═══ 4.5.7.1. gcount - Return Number of Characters Extracted ═══ Class: istream int gcount(); gcount() returns the number of characters extracted from the stream buffer attached to ins by the last call to an unformatted input function. The input operator >> may call unformatted input functions, and thus formatted input may affect the value returned by gcount(). ═══ 4.5.7.2. peek - Return Next Character Without Extracting It ═══ Class: istream int peek(); peek() calls ipfx(1). If ipfx() returns zero, or if no more input is available from the ultimate producer, peek() returns EOF. Otherwise, it returns the next character in the stream buffer attached to ins without extracting the character. ═══ 4.5.7.3. putback - Put Extracted Characters Back into Stream Buffer ═══ Class: istream istream& putback(char c); putback() attempts to put a character that was extracted from the stream buffer attached to ins back into the stream buffer. c must equal the character before the get pointer of the stream buffer. Unless some other activity is modifying the stream buffer, this is the last character extracted from the stream buffer. If c is not equal to the character before the get pointer, the result of putback() is undefined, and the error state of ins may be set. putback() does not call ipfx(), but if the error state of ins is nonzero, putback() returns without doing anything. ═══ 4.5.7.4. sync - Synchronize Stream Buffer and Ultimate Producer ═══ Class: istream int sync(); sync() establishes consistency between the ultimate producer and the stream buffer attached to ins. sync() calls ins.rdbuf()->sync(), which is a virtual function, so the details of its operation depend on the way the function is defined in a given derived class. If an error occurs, sync() returns EOF. ═══ 4.5.8. Built-In Manipulators for istream ═══ istream& ws(istream&); ios& dec(ios&); ios& hex(ios&); ios& oct(ios&); The I/O Stream Library provides you with a set of built-in manipulators that can be used with the istream class. These manipulators have a specific effect on an istream object beyond extracting their own values. The built-in manipulators are accepted by the following versions of the input operator: istream& operator>> (istream& (*f) (istream&)); istream& operator>> (ios& (*f) (ios&)); If ins is a reference to an istream object, then this statement extracts whitespace characters from the stream buffer attached to ins: ins >> ws; This statement sets ios::dec: ins >> dec; This statement sets ios::hex: ins >> hex; This statement sets ios::oct: ins >> oct; ═══ 4.5.9. Public Members of istream_withassign ═══ There are two public member functions of istream_withassign: o istream_withassign constructor o istream_withassign assignment operator ═══ 4.5.9.1. istream_withassign Constructor ═══ Class: istream istream_withassign(); The istream_withassign constructor creates an istream_withassign object. It does not do any initialization of this object. ═══ 4.5.9.2. istream_withassign Assignment Operator ═══ Class: istream istream_withassign& operator=(istream& is); istream_withassign& operator=(streambuf* sb); There are two versions of the istream_withassign assignment operator. The first version takes a reference to an istream object, is, as its argument. It associates the stream buffer attached to is with the istream_withassign object that is on the left side of the assignment operator. The following example shows how you can use this version of the assignment operator to redirect input that would have come from standard input so that it comes from a file: #include #include void main() { ifstream infile("eglinton.dat"); char *s=new char[10]; float f; int i; cin = infile; // // from this point on, all input from cin really // comes from infile // cin >> s >> f >> i; cout <<"Here are the values from the input file: " << endl; cout << s << endl << f << endl << i << endl; infile.close(); exit(0); } If the file eglinton.dat contains the following: Bloor 5.5 3 The example produces the following output: Here are the values from the input file: Bloor 5.5 3 Note that this assignment operator gives the istream_withassign object cin the same stream buffer as the ifstream object, but the two objects maintain separate ios objects. Thus, if the error state is set through the common stream buffer, it must be reset twice, once for each of the two ios objects that are attached to the stream buffer. The second version of the assignment operator takes a pointer to a streambuf object, sb, as its argument. It associates this streambuf object with the istream_withassign object that is on the left side of the assignment operator. The following example shows how you can use this version of the assignment operator to associate cin with the input file eglinton.dat: #include #include #include void main() { ifstream infile("eglinton.dat"); char *s=new char[10]; float f; int i; // // from this point on, all input from cin really // comes from infile // cin = infile.rdbuf(); cin >> s >> f >> i; cout <<"Here are the values from the input file: " << endl; cout << s << endl << f << endl << i << endl; infile.close(); exit(0); } Given the same input, this example produces the same output as the preceding example. ═══ 4.6. ostream and ostream_withassign Classes ═══ This chapter describes the ostream class and its derived class ostream_withassign. The ostream member functions allow you to put characters into the streambuf object that is associated with an ostream object. ostream_withassign is derived from ostream and includes an assignment operator. The following topics are described in this chapter: o Declarations for ostream and ostream_withassign in the iostream.h header file o Constructors for ostream o Output suffix and prefix functions o Public members of ostream for formatted output o Public members of ostream for unformatted output o Public members of ostream for positioning o Other public members of ostream o Built-in manipulators for ostream o Public members of ostream_withassign ═══ 4.6.1. Declarations for ostream and ostream_withassign in iostream.h ═══ You must include the following statement in any file that uses member functions of the ostream class: #include The following is an excerpt from the iostream.h header file that shows the relevant declarations for the members of ostream: class ostream : virtual public ios { public: ostream(streambuf*) ; ostream(int fd) ; ostream(int size ,char*) ; virtual ~ostream(); int opfx(); void osfx(); ostream& flush(); ostream& seekp(streampos p); ostream& seekp(streamoff o,ios::seek_dir d); streampos tellp(); ostream& put(char c); ostream& complicated_put(char c); ostream& operator<<(char c); ostream& operator<<(signed char c); ostream& operator<<(unsigned char c); ostream& operator<<(wchar_t); ostream& operator<<(const wchar_t *); ostream& operator<<(const char*); ostream& operator<<(const signed char*); ostream& operator<<(const unsigned char*); ostream& operator<<(int a); ostream& operator<<(long); ostream& operator<<(double); ostream& operator<<(long double); ostream& operator<<(float); ostream& operator<<(unsigned int a); ostream& operator<<(unsigned long); ostream& operator<<(void*); ostream& operator<<(streambuf*); ostream& operator<<(short i); ostream& operator<<(unsigned short i); ostream& operator<<(ostream& (*f)(ostream&)); ostream& operator<<(ios& (*f)(ios&) ); ostream& ls_complicated(char); ostream& ls_complicated(signed char); ostream& ls_complicated(unsigned char); ostream& write(const char* s,int n); ostream& write(const signed char* s, int n); ostream& write(const unsigned char* s, int n); protected: int do_opfx(); void do_osfx(); ostream(); }; class ostream_withassign : public ostream { public: ostream_withassign(); virtual ~ostream_withassign(); ostream_withassign& operator=(ostream&); ostream_withassign& operator=(streambuf*); }; extern ostream_withassign cout; extern ostream_withassign cerr; extern ostream_withassign clog; ostream& endl(ostream& i); ostream& ends(ostream& i); ostream& flush(ostream&); ios& dec(ios&); ios& hex(ios&); ios& oct(ios&); Note: The following functions have declarations included in the above listing of iostream.h, but they are only for the internal use of the I/O Stream Library. Do not use them directly: o complicated_put() o ls_complicated() o do_opfx() o do_osfx() ═══ 4.6.2. Constructors for ostream ═══ Class: ostream ostream(streambuf* sb); The ostream constructor takes a single argument sb, which is a pointer to a streambuf object. The constructor creates an ostream object that is attached to the streambuf object pointed to by sb. The constructor also initializes the format variables to their defaults. The other declarations for the ostream constructor in iostream.h are obsolete; do not use them. ═══ 4.6.3. Output Suffix and Prefix Functions ═══ The output operator calls the output prefix function opfx() before inserting characters into a stream buffer, and calls the output suffix function osfx() after inserting characters. The following descriptions assume the functions are called as part of an ostream object called os. ═══ 4.6.3.1. osfx - Output Suffix Function ═══ Class: ostream void osfx(); osfx() is called before a formatted output function returns. osfx() flushes the streambuf object attached to os if ios::unitbuf is set. osfx() is called by the output operator. If you overload the output operator to handle your own classes, you should ensure that osfx() is called after any direct manipulation of a streambuf object. Binary output functions do not call osfx(). ═══ 4.6.3.2. opfx - Output Prefix Function ═══ Class: ostream int opfx(); opfx() checks the error state of os. If the internal flag ios::hardfail is set, opfx() returns 0. Otherwise, opfx() flushes the stream buffer attached to the ios object pointed to by os.tie(), if one exists, and returns the value returned by ios::good(). ios::good() returns 0 if ios::failbit, ios::badbit, or ios::eofbit is set. Otherwise, ios::good() returns a nonzero value. ═══ 4.6.4. Public Members of ostream for Formatted Output ═══ The ostream class lets you use the output operator << to perform formatted output (or insertion) to a stream buffer. Consider the following statement, where outs is a reference to an ostream object and x is a variable of a built-in type: outs << x; The output operator << calls opfx() before beginning insertion. If opfx() returns a nonzero value, the output operator converts x into a series of characters and inserts these characters into the stream buffer attached to outs. If an error occurs, the output operator sets ios::failbit. The details of the conversion of x depend on the format state of the ostream object and the type of x. For numeric and string values, the output operator resets the width variable ios::x_width of the format state of an ostream object to 0, but it does not affect anything else in the format state. Note: Only the definitions of the output operator for numeric types and for pointers to char (including signed char and unsigned char) reset ios::x_width. The output operator is defined for the following types: o Arrays of characters and char values, including arrays of wchar_t and wchar_t values. o Other integral values: short, int, long o float, double and long double values o Pointers to void In addition, the output operator is defined for streambuf objects. The following sections describe the output operators for these types. Note: The following descriptions assume that the input operator is called with the ostream object outs on the left side of the operator. ═══ 4.6.4.1. Inserting Fill Characters ═══ Once the representation of a value has been determined, the output operator may insert fill characters. If ios::x_width is greater than 0 and the representation of the value to be inserted is less than ios::x_width, the output operator inserts enough fill characters to ensure that the representation occupies an entire field in the stream buffer. The position of the fill characters depends on the format state of outs. ═══ 4.6.4.2. Output Operator for Arrays of Characters and char Values ═══ Class: ostream ostream& operator<<(const char* cp); ostream& operator<<(const signed char* cp); ostream& operator<<(const unsigned char* cp); ostream& operator<<(wchar_t); ostream& operator<<(char ch); ostream& operator<<(signed char ch); ostream& operator<<(unsigned char ch); ostream& operator<<(const wchar_t *); For a pointer to a char, signed char, or unsigned char value, the output operator inserts all the characters in the string into the stream buffer with the exception of the null character that terminates the string. For a pointer to a wchar_t, the output operator converts the wchar_t string to its equivalent multibyte character string, then inserts it into the stream buffer with the exception of the null character that terminates the string. If ios::x_width is greater than zero and the representation of the value to be inserted is less than ios::x_width, the output operator inserts enough fill characters to ensure that the representation occupies an entire field in the stream buffer. The output operator does not perform any conversion on char, signed char, unsigned char, or wchar_t values. ═══ 4.6.4.3. Output Operator for Other Integral Values ═══ Class: ostream ostream& operator<<(short iv); ostream& operator<<(unsigned short iv); ostream& operator<<(int iv); ostream& operator<<(unsigned int iv); ostream& operator<<(long iv); ostream& operator<<(unsigned long iv); For the integral types (short, unsigned short, int, unsigned int, long, and unsigned long), the output operator converts the integral value iv according to the format state of outs and inserts characters into the stream buffer associated with outs. There is no overflow detection on conversion of integral types. The conversion that takes place on iv depends, in part, on the settings of the following format flags: o If ios::oct is set, iv is converted to a series of octal digits. If ios::showbase is set, "0" is inserted into the stream buffer before the octal digits. If the value being inserted is equal to 0, a single "0" is inserted, not "00". o If ios::dec is set, iv is converted to a series of decimal digits. o If ios::hex is set, iv is converted to a series of hexadecimal digits. If ios::showbase is set, "0x" (or "0X" if ios::uppercase is set) is inserted into the stream buffer before the hexadecimal digits. If none of these format flags is set, iv is converted to a series of decimal digits. If iv is converted to a series of decimal digits, its sign also affects the conversion: o If iv is negative, a negative sign "-" is inserted before the decimal digits. o If iv is equal to 0, the single digit 0 is inserted. o If iv is positive and ios::showpos is set, a positive sign "+" is inserted before the decimal digits. ═══ 4.6.4.4. Output Operator for float and double Values ═══ Class: ostream ostream& operator<<(float val); ostream& operator<<(double val); ostream& operator<<(long double val); The output operator performs a conversion operation on the value val and inserts it into the stream buffer attached to outs. The conversion depends on the values returned by the following functions: o outs.precision(): returns the number of significant digits that appear after the decimal. The default value is 6. o outs.width(): if this returns 0, val is inserted without any fill characters. If the return value is greater than the number of characters needed to represent val, extra fill characters are inserted so that the total number of characters inserted is equal to the return value. The conversion also depends on the values of the following format flags: o If ios::scientific is set, val is converted to scientific notation, with one digit before the decimal, and the number of digits after the decimal equal to the value returned by outs.precision(). The exponent begins with a lowercase "e" unless ios::uppercase is set, in which case the exponent begins with an uppercase "E". o If ios::fixed is set, val is converted to fixed notation, with the number of digits after the decimal point equal to the value returned by outs.precision(). If neither ios::fixed nor ios::scientific is set, the conversion depends upon the value of val. See Floating-Point Formatting for more details. o If ios::uppercase is set, the exponents of values in scientific notation begin with an uppercase "E". See Format State Flags for more details on the format state. ═══ 4.6.4.5. Output Operator for Pointers to void ═══ Class: ostream ostream& operator<<(void* vp); The output operator converts pointers to void to integral values and then converts them to hexadecimal values as if ios::showbase were set. This version of the output operator is used to print out the values of pointers. ═══ 4.6.4.6. Output Operator for streambuf Objects ═══ Class: ostream ostream& operator<<(streambuf* sb); If opfx() returns a nonzero value, the output operator inserts all of the characters that can be taken from sb into the stream buffer attached to outs. Insertion stops when no more characters can be fetched from sb. No padding is performed. The return value is outs. ═══ 4.6.5. Public Members of ostream for Unformatted Output ═══ The functions listed in this section allow you to insert characters into a stream buffer without regard to the type of the values that the characters represent. Note: The following descriptions assume that the functions are called as part of an ostream object called outs. The following functions are described: o put - insert a single character o write - insert an array of characters ═══ 4.6.5.1. put - Insert a Single Character ═══ Class: ostream ostream& put(char c); put() inserts c in the stream buffer attached to outs. put() sets the error state of outs if the insertion fails. ═══ 4.6.5.2. write - Insert an Array of Characters ═══ Class: ostream ostream& write(const char* cp, int n); ostream& write(const signed char* cp, int n); ostream& write(const unsigned char* cp, int n); write() inserts the n characters that begin at the position pointed to by cp. This array of characters does not need to end with a null character. ═══ 4.6.6. Public Members of ostream for Positioning ═══ Note: The following descriptions assume that the functions are called as part of an ostream object called outs. The following functions are described: o seekp - reposition put pointer of ultimate consumer o tellp - return position of put pointer of associated stream buffer ═══ 4.6.6.1. seekp - Reposition Put Pointer of Ultimate Consumer ═══ Class: ostream ostream& seekp(streampos sp); ostream& seekp(streamoff so, ios::seek_dir dir); seekp() repositions the put pointer of the ultimate consumer. seekp() with one argument sets the put pointer to the position sp. seekp() with two arguments sets the put pointer to the position specified by dir with the offset so. dir can have the following values: o ios::beg: the beginning of the stream o ios::cur: the current position of the put pointer o ios::end: the end of the stream. The new position of the put pointer is equal to the position specified by dir offset by the value of so. If you attempt to move the put pointer to a position that is not valid, seekp() sets ios::badbit. ═══ 4.6.6.2. tellp - Return Position of Put Pointer of Associated Stream Buffer ═══ Class: ostream streampos tellp(); tellp() returns the current position of the put pointer of the stream buffer that is attached to outs. ═══ 4.6.7. Other Public Members of ostream ═══ In this section, the following function is described: flush - clear associated stream buffer ═══ 4.6.7.1. clear.flush - Clear Associated Stream Buffer ═══ Class: ostream ostream& flush(); The ultimate consumer of characters that are stored in a stream buffer may not necessarily consume them immediately. flush() causes any characters that are stored in the stream buffer attached to outs to be consumed. It calls outs.rdbuf()->sync() to accomplish this action. ═══ 4.6.8. Built-In Manipulators for ostream ═══ ostream& endl(ostream& i); ostream& ends(ostream& i); ostream& flush(ostream&); ios& dec(ios&); ios& hex(ios&); ios& oct(ios&); The I/O Stream Library provides you with a set of built-in manipulators that can be used with the ostream class. These manipulators have a specific effect on an ostream object beyond extracting their own values. The built-in manipulators are accepted by the following versions of the output operators: ostream& operator<<(ostream& (*f)(ostream&)); ostream& operator<<(ios& (*f)(ios&) ); If outs is a reference to an ostream object, then this statement inserts a newline character and calls flush(). outs << endl; This statement inserts a null character: outs << ends; This statement flushes the stream buffer attached to outs. It is equivalent to flush() outs << flush; This statement sets ios::dec: outs << dec; This statement sets ios::hex: outs << hex; This statement sets ios::oct: outs << oct; ═══ 4.6.9. Public Members of ostream_withassign ═══ There are two public members of ostream_withassign: o ostream_withassign constructor o ostream_withassign assignment operator ═══ 4.6.9.1. ostream_withassign Constructor ═══ Class: ostream ostream_withassign(); The ostream_withassign constructor creates an ostream_withassign object. It does not do any initialization on the object. ═══ 4.6.9.2. ostream_withassign Assignment Operator ═══ Class: ostream ostream_withassign& operator=(ostream& os); ostream_withassign& operator=(streambuf* sb); There are two versions of the ostream_withassign assignment operator. The first version takes a reference to an ostream object, os, as its argument. It associates the streambuf attached to os with the ostream_withassign object that is on the left side of the assignment operator. The following example shows how this version of the assignment operator is used: #include #include #include void main() { ofstream outfile("sheppard.dat"); // from this point on, output sent to cout will // actually be sent to outfile cout = outfile; cout << "This is going to the output file." << endl; outfile.close(); exit(0); } After this program is run, the file sheppard.dat contains the following: This is going to the output file. The second version of the assignment operator takes a pointer to a streambuf object, sb, as its argument. It associates sb with the ostream_withassign object that is on the left side of the assignment operator. The following example shows how this version of the assignment operator is used: #include #include #include void main() { ofstream outfile("sheppard.dat"); // from this point on, output sent to cout will // actually be sent to outfile cout = outfile.rdbuf(); cout << "This is going to the output file." << endl; outfile.close(); exit(0);} This example produces the same results as the preceding example. ═══ 4.7. iostream and iostream_withassign Classes ═══ This chapter describes the iostream class and its derived class iostream_withassign. iostream is derived from istream and ostream iostream_withassign is derived from iostream and includes an assignment operator. Derivation Relationships in the I/O Stream Library shows how iostream and iostream_withassign are derived from their base classes. The following topics are described in this chapter: o Declarations for iostream and iostream_withassign in iostream.h o Public members of iostream and iostream_withassign ═══ 4.7.1. Declarations for iostream and iostream_withassign in iostream.h ═══ You must include the following statement in any file that uses member functions of the iostream or iostream_withassign classes: #include The following is an excerpt from the iostream.h header file that shows the relevant declarations for the members of iostream and iostream_withassign: class iostream : public istream, public ostream { public: iostream(streambuf*); virtual ~iostream(); protected: iostream(); }; class iostream_withassign : public iostream { public: iostream_withassign(); virtual ~iostream_withassign(); iostream_withassign& operator=(ios&); iostream_withassign& operator=(streambuf*); }; ═══ 4.7.2. Public Members of iostream and iostream_withassign ═══ The following public member functions are described: o iostream constructor o iostream_withassign constructor o iostream_withassign assignment operator ═══ 4.7.2.1. Constructor for iostream ═══ Class: iostream iostream(streambuf* sb); The iostream constructor takes a single argument sb. The constructor creates an iostream object that is attached to the streambuf object that is pointed to by sb. The constructor also initializes the format variables to their defaults. ═══ 4.7.2.2. iostream_withassign Constructor ═══ Class: iostream_withassign iostream_withassign(); The iostream_withassign constructor creates an iostream_withassign object. It does not do any initialization of this object. ═══ 4.7.2.3. iostream_withassign Assignment Operator ═══ Class: iostream_withassign iostream_withassign& operator=(ios& is); iostream_withassign& operator=(streambuf* sb); There are two versions of the iostream_withassign assignment operator. The first version takes a reference to an ios object, is, as its argument. It associates the stream buffer attached to is with the iostream_withassign object that is on the left side of the assignment operator. The second version of the iostream_withassign assignment operator takes a pointer to a streambuf object, sb, as its argument. It associates this streambuf object with the iostream_withassign object that is on the left side of the assignment operator. ═══ 4.8. filebuf Class ═══ This chapter describes the filebuf class. This class is derived from streambuf and specializes it for using files as the ultimate producer or the ultimate consumer. The following topics are described in this chapter: o Introduction to the filebuf class o Declarations for filebuf in the fstream.h header file o Public members of filebuf ═══ 4.8.1. Introduction to the filebuf Class ═══ In a filebuf object, characters are cleared out of the put area by doing write operations to the file, and characters are put into the get area by doing read operations from that file. The filebuf class supports seek operations on files that allow seek operations. A filebuf object that is attached to a file descriptor is said to be open. The stream buffer is allocated automatically if one is not specified explicitly with a constructor or a call to setbuf(). You can also create an unbuffered filebuf object by calling the constructor or setbuf() with the appropriate arguments. If the filebuf object is unbuffered, a system call is made for each character that is read or written. The get and put pointers for a filebuf object behave as a single pointer. This single pointer is referred to as the get/put pointer. The file that is attached to the filebuf object also has a single pointer that indicates the current position where information is being read or written. In this chapter, this pointer is called the file get/put pointer. ═══ 4.8.2. Declarations for filebuf in fstream.h ═══ You must include the following statement in any file that uses members of the filebuf class: #include The following is an excerpt from the fstream.h header file that shows the relevant declarations for the members of filebuf: class filebuf : public streambuf { public: filebuf(); filebuf(int fd); filebuf(int fd, char* p, int l); ~filebuf(); int detach(); int fd() ; int is_open(); filebuf* open(const char *name, int om, int prot=openprot); filebuf* attach(int fd); filebuf* close(); virtual int overflow(int=EOF); virtual int underflow(); virtual int sync(); virtual streampos seekoff(streamoff,ios::seek_dir,int); virtual streambuf* setbuf(char* p, int len); static const int openprot ; }; Note: filebuf::openprot is the default protection for open(). It is equivalent to S_IREAD | S_IWRITE. ═══ 4.8.3. Public Members of filebuf ═══ Note: The following descriptions assume that the functions are called as part of a filebuf object called fb. The following member functions are described: o Constructors for filebuf o Destructor for filebuf o attach - attach filebuf object to file o close - disconnect filebuf o detach - detach filebuf object from file o fd - return file descriptor o is_open - return status of filebuf o open - open file and attach to filebuf o seekoff - move the file get/put pointer o seekpos - move the file get/put pointer o setbuf - set up stream buffer o sync - synchronize file and stream buffer ═══ 4.8.3.1. Constructors for filebuf ═══ Class: filebuf filebuf(); filebuf(int d); filebuf(int d, char* p, int len); filebuf() constructor with no arguments constructs an initially closed filebuf object. filebuf() constructor with one argument constructs a filebuf object that is attached to file descriptor d. filebuf() constructor with three arguments constructs a filebuf object that is attached to file descriptor d. The object is initialized to use the stream buffer starting at the position pointed to by p with length equal to len. ═══ 4.8.3.2. Destructor for filebuf ═══ Class: filebuf ~filebuf(); The filebuf destructor calls fb.close(). ═══ 4.8.3.3. attach - Attach filebuf Object to File ═══ Class: filebuf filebuf* attach(int d); attach() attaches fb to the file descriptor d. If fb is already open or if d is not open, attach() returns 0. Otherwise, attach() returns a pointer to fb. ═══ 4.8.3.4. detach - Detach filebuf Object from File ═══ Class: filebuf int detach(); fb.detach() disconnects fb from the file without closing the file. If fb is not open detach() returns -1. Otherwise detach() flushes any output that is waiting in fb to be sent to the file, disconnects fb from the file, and returns the file descriptor. ═══ 4.8.3.5. close - Disconnect filebuf ═══ Class: filebuf filebuf* close(); close() does the following: 1. Flushes any output that is waiting in fb to be sent to the file 2. Disconnects fb from the file 3. Closes the file that was attached to fb If an error occurs, close() returns 0. Otherwise, close() returns a pointer to fb. Even if an error occurs, close() performs the second and third steps listed above. ═══ 4.8.3.6. fd - Return File Descriptor ═══ Class: filebuf int fd(); fd() returns the file descriptor that is attached to fb. If fb is closed, fd() returns EOF. ═══ 4.8.3.7. is_open - Return Status of filebuf ═══ Class: filebuf int is_open(); is_open() returns a nonzero value if fb is attached to a file descriptor. Otherwise, is_open() returns zero. ═══ 4.8.3.8. open - Open File and Attach to filebuf ═══ Class: filebuf filebuf* open(char* fname, int omode, int prot=openprot); open() opens the file with the name fname and attaches fb to it. If fname does not already exist and omode does not equal ios::nocreate, open() tries to create it with protection mode equal to prot. The default value of prot is filebuf::openprot. An error occurs if fb is already open. If an error occurs, open() returns 0. Otherwise, open() returns a pointer to fb. The default protection mode for the filebuf class is S_IREAD | S_IWRITE. If you create a file with both S_IREAD and S_IWRITE set, the file is created with both read and write permission. If you create a file with only S_IREAD set, the file is created with read-only permission, and cannot be deleted later with the stdio.h library function remove(). S_IREAD and S_IWRITE are defined in sys\stat.h. ═══ 4.8.3.9. seekoff - Move the File Get/Put Pointer ═══ Class: filebuf streampos seekoff(streamoff so, seek_dir sd, int omode); seekoff() moves the file get/put pointer to the position specified by sd with the offset so. sd can have the following values: o ios::beg: the beginning of the file o ios::cur: the current position of the file get/put pointer o ios::end: the end of the file seekoff() changes the position of the file get/put pointer to the position specified by the value sd + so. The offset so can be either positive or negative. seekoff() ignores the value of omode. If fb is attached to a file that does not support seeking, or if the value sd + so specifies a position before the beginning of the file, seekoff() returns EOF and the position of the file get/put pointer is undefined. Otherwise, seekoff() returns the new position of the file get/put pointer. The following example shows some of the ways that you can call seekoff(). The file dundas.dat is opened as an fstream object. Assume that this file contains at least 101 bytes of data. rdbuf() returns the filebuf object that is associated with this fstream object, and seekoff() is called with a variety of arguments. #include #define MODE ios::in void main() { streampos pos; fstream myfile("dundas.dat", MODE); filebuf *fb = myfile.rdbuf(); // valid: so = 0, dir = ios::end streamoff offset = 0; pos= fb->seekoff(offset, ios::end, MODE); // valid: so = 100, dir = ios::beg offset = 100; pos= fb->seekoff(offset, ios::beg, MODE); // valid: so = -1, dir = ios::end offset = -1; pos= fb->seekoff(offset, ios::end, MODE); // valid: so = 1, dir = ios::cur offset = 1; pos= fb->seekoff(offset, ios::cur, MODE); // invalid: so = -1, dir = ios::beg offset = -1; pos= fb->seekoff(offset, ios::beg, MODE); } ═══ 4.8.3.10. seekpos - Move the File Get/Put Pointer ═══ Class: filebuf The filebuf class inherits the default definition of seekpos() from the streambuf class. The default definition defines seekpos() as a call to seekoff(). Thus, the following call to seekpos(): seekpos(pos, mode); is converted to a call to seekoff(): seekoff(streamoff(pos), ios::beg, mode); ═══ 4.8.3.11. setbuf - Set Up Stream Buffer ═══ Class: filebuf streambuf* setbuf(char* pbegin, int len); setbuf() sets up a stream buffer with length in bytes equal to len beginning at the position pointed to by pbegin. setbuf() does the following: o If pbegin is 0 or len is nonpositive, setbuf() makes fb unbuffered. o If fb is open and a stream buffer has been allocated, no changes are made to this stream buffer, and setbuf() returns 0. o If neither of these cases is true, setbuf() returns a pointer to fb. ═══ 4.8.3.12. sync - Synchronize File and Stream Buffer ═══ Class: filebuf int sync(); sync() attempts to synchronize the get/put pointer and the file get/put pointer. sync() may cause bytes that are waiting in the stream buffer to be written to the file, or it may reposition the file get/put pointer if characters that have been read from the file are waiting in the stream buffer. If it is not possible to synchronize the get/put pointer and the file get/put pointer, sync() returns EOF. If it is possible to synchronize them, sync() returns zero. ═══ 4.9. fstream, ifstream, and ofstream Classes ═══ This chapter describes fstream, ifstream, and ofstream, the classes that specialize iostream, istream, and ostream, respectively, for files. Another class, fstreambase, is declared in the fstream.h header file. fstreambase is the base class for fstream, ifstream, and ofstream, but it is not meant to be used directly. fstreambase is only documented here to show the functions that the other three classes inherit from it: attach(), close(), and setbuf(). The following topics are described in this chapter: o Declarations in the fstream.h header file o Public members of fstreambase o Public members of fstream o Public members of ifstream o Public members of ofstream o Example of using fstream, ifstream and ofstream ═══ 4.9.1. Declarations for fstream, ifstream and ofstream in fstream.h ═══ You must include the following statement in any file that uses members of the fstream, ifstream, or ofstream classes: #include The following is an excerpt from the fstream.h header file that shows the relevant declarations for these three classes: class fstreambase : virtual public ios { public: fstreambase(); fstreambase(const char* name, int mode, int prot=filebuf::openprot); fstreambase(int fd); fstreambase(int fd, char* p, int l); ~fstreambase(); void open(const char* name, int mode, int prot=filebuf::openprot); void attach(int fd); void close(); int detach(); void setbuf(char* p, int l); filebuf* rdbuf(); }; class ifstream : public fstreambase, public istream { public: ifstream(); ifstream(const char* name, int mode=ios::in, int prot=filebuf::openprot); ifstream(int fd); ifstream(int fd, char* p, int l); ~ifstream(); filebuf* rdbuf(); void open(const char* name, int mode=ios::in, int prot=filebuf::openprot); }; class ofstream : public fstreambase, public ostream { public: ofstream(); ofstream(const char* name, int mode=ios::out, int prot=filebuf::openprot); ofstream(int fd); ofstream(int fd, char* p, int l); ~ofstream(); filebuf* rdbuf(); void open(const char* name, int mode=ios::out, int prot=filebuf::openprot); }; class fstream : public fstreambase, public iostream { public: fstream(); fstream(const char* name, int mode, int prot=filebuf::openprot); fstream(int fd); fstream(int fd, char* p, int l); ~fstream(); filebuf* rdbuf(); void open(const char* name, int mode, int prot=filebuf::openprot) ; }; ═══ 4.9.2. Public Members of fstreambase ═══ Notes Note: 1. The fstreambase class is an internal class that provides common functions for the classes that are derived from it. Do not use the fstreambase class directly. The following descriptions are provided so that you can use the functions as part of fstream, ifstream, and ofstream objects. 2. The following descriptions assume that the functions are called as part of an fstream, ifstream, or ofstream object called fb. The following functions are described: o attach - connect fstream object to file descriptor o close - close associated filebuf object o setbuf - set up stream buffer ═══ 4.9.2.1. attach - Connect fstream Object to File Descriptor ═══ Class: fstreambase void attach(int filedesc); attach() attaches fb to the file descriptor filedesc. If fb is already attached to a file descriptor, an error occurs and ios::failbit is set in the format state of fb. attach() returns zero if the file descriptor is not already open or if fb is already attached to a file descriptor. ═══ 4.9.2.2. close - Close Associated filebuf Object ═══ Class: fstreambase void close(); close() closes the filebuf object, breaking the connection between fb and the file descriptor. close() calls fb.rdbuf()->close(). If this call fails, the error state of fb is not cleared. ═══ 4.9.2.3. detach - Detach Associated filebuf Object ═══ Class: fstreambase int detach(); detach detaches the filebuf object by calling fb.rdbuf->detach(), and returns the value returned by fb.rdbuf->detach(). ═══ 4.9.2.4. setbuf - Set Up Stream Buffer ═══ Class: fstreambase void setbuf(char* pbegin, int len); setbuf() sets up a stream buffer with length in bytes equal to len beginning at the position pointed to by pbegin. If pbegin is equal to 0 or len is nonpositive, fb will be unbuffered. If fb is open, or the call to fb.rdbuf()->setbuf() fails, setbuf() returns 0. Otherwise, setbuf() returns a pointer to the stream buffer that was established. ═══ 4.9.3. Public Members of fstream ═══ Note: The following descriptions assume that the functions are called as part of an fstream object called fs. The following functions are described: o Constructors for fstream o open - open file and connect to fstream object o rdbuf - return pointer to filebuf object ═══ 4.9.3.1. Constructors for fstream ═══ Class: fstream fstream(); fstream(int filedesc); fstream(const char* fname, int mode, int prot=filebuf::openprot); fstream(int filedesc, char* bufpos, int len); There are four versions of the fstream constructor. The first version takes no arguments and constructs an unopened fstream object. The second version takes two arguments and constructs an fstream object that is attached to the file descriptor filedesc. If filedesc is not open, ios::failbit is set in the format state of fs. The third and fourth versions of the fstream() constructor take three arguments. The third version constructs an fstream object and opens the file fname with open mode equal to mode and protection mode equal to prot. The default value for the argument prot is filebuf::openprot. If the file cannot be opened, the error state of the constructed fstream object is set. The fourth version constructs an fstream object that is attached to the file descriptor filedesc. If filedesc is not open, ios::failbit is set in the format state of fs. This constructor also sets up an associated filebuf object with a stream buffer that has length len bytes and begins at the position pointed to by bufpos. If bufpos is equal to 0 or len is equal to 0, the associated filebuf object is unbuffered. ═══ 4.9.3.2. open - Open File and Connect to fstream Object ═══ Class: fstream void open(const char* fname, int mode, int prot=filebuf::openprot); open() opens the file with the name fname and attaches it to fs. If fname does not already exist, open() tries to create it with protection mode equal to prot, unless ios::nocreate is set. The default value for prot is filebuf::openprot. If fs is already attached to a file or if the call to fs.rdbuf()->open() fails, ios::failbit is set in the error state for fs. The members of the ios::open_mode enumeration are bits that can be ORed together. The value of mode is the result of such an OR operation. This result is an int value, and for this reason, mode has type int rather than open_mode. The elements of the open_mode enumeration have the following meanings: ios::app open() performs a seek to the end of the file. Data that is written is appended to the end of the file. This value implies that the file is open for output. ios::ate open() performs a seek to the end of the file. Setting ios::ate does not open the file for input or output. If you set ios::ate, you should explicitly set ios::in, ios::out, or both. ios::bin See ios::binary below. ios::binary The file is opened in binary mode. In the default (text) mode, carriage returns are discarded on input, as is an end-of-file (0x1a) character if it is the last character in the file. This means that a carriage return without an accompanying line feed causes the characters on either side of the carriage return to become adjacent. On output, a line feed is expanded to a carriage return and line feed. If you specify ios::binary, carriage returns and terminating end-of-file characters are not removed on input, and a line feed is not expanded to a carriage return and line feed on output. ios::binary and ios::bin provide identical functionality. ios::in The file is opened for input. If the file that is being opened for input does not exist, the open operation will fail. ios::noreplace is ignored if ios::in is set. ios::out The file is opened for output. ios::trunc If the file already exists, its contents will be discarded. If you specify ios::out and neither ios::ate nor ios::app, you are implicitly specifying ios::trunc. If you set ios::trunc, you should explicitly set ios::in, ios::out, or both. ios::nocreate If the file does not exist, the call to open() fails. ios::noreplace If the file already exists and ios::out is set, the call to open() fails. If ios::out is not set, ios::noreplace is ignored. ═══ 4.9.3.3. rdbuf - Return Pointer to filebuf Object ═══ Class: fstream filebuf* rdbuf(); rdbuf() returns a pointer to the filebuf object that is attached to fs. ═══ 4.9.4. Public Members of ifstream ═══ Note: The following descriptions assume that the functions are called as part of an ifstream object called ifs. o Constructors for ifstream o open - open file and connect to ifstream object o rdbuf - return pointer to filebuf object ═══ 4.9.4.1. Constructors for ifstream ═══ Class: ifstream ifstream(); ifstream(int filedesc); ifstream(const char* fname, int mode=ios::in, int prot=filebuf::openprot); ifstream(int filedesc, char* bufpos, int len); There are four versions of the ifstream constructor. The first version takes no arguments and constructs an unopened ifstream object. The second version takes one argument and constructs an ifstream object that is attached to the file descriptor filedesc. If filedesc is not open, ios::failbit is set in the format state of ifs. The third and fourth versions of the ifstream() constructor take three arguments. The third version constructs an ifstream object and opens the file fname with open mode equal to mode and protection mode equal to prot. The default value for mode is ios::in, and the default value for prot is filebuf::openprot. If the file cannot be opened, the error state of the constructed ifstream object is set. The fourth version constructs an ifstream object that is attached to the file descriptor filedesc. If filedesc is not open, ios::failbit is set in the format state of ifs. This constructor also sets up an associated filebuf object with a stream buffer that has length len bytes and begins at the position pointed to by bufpos. If bufpos is equal to 0 or len is equal to 0, the associated filebuf object is unbuffered. ═══ 4.9.4.2. open - Open File and Connect to ifstream Object ═══ Class: ifstream void open(const char* fname, int mode=ios::in, int prot=filebuf::openprot); open() opens the file with the name fname and attaches it to ifs. If fname does not already exist, open() tries to create it with protection mode equal to prot, unless ios::nocreate is set in mode. The default value for mode is ios::in. The default value for prot is filebuf::openprot. If ifs is already attached to a file, or if the call to ifs.rdbuf()->open() fails, ios::failbit is set in the error status for ifs. The members of the ios::open_mode enumeration are bits that can be ORed together. The value of mode is the result of such an OR operation. This result is an int value, and for this reason mode has type int rather than type open_mode. See open - Open File and Connect to fstream Object for a list of the possible values for mode. ═══ 4.9.4.3. rdbuf - Return Pointer to filebuf Object ═══ Class: ifstream filebuf* rdbuf(); rdbuf() returns a pointer to the filebuf object that is attached to ifs. ═══ 4.9.5. Public Members of ofstream ═══ Note: The following descriptions assume that the functions are called as part of an ofstream object called ofs. o Constructors for ofstream o open - open file and connect to ofstream object o rdbuf - return pointer to filebuf object ═══ 4.9.5.1. Constructors for ofstream ═══ Class: ofstream ofstream(); ofstream(int filedesc); ofstream(const char* fname, int mode=ios::out, int prot=filebuf::openprot); ofstream(int filedesc, char* bufpos, int len); There are four versions of the ofstream constructor. The first version takes no arguments and constructs an unopened ofstream object. The second version takes one argument and constructs an ofstream object that is attached to the file descriptor filedesc. If filedesc is not open, ios::failbit is set in the format state of ofs. The third and fourth versions of the ofstream() constructor take three arguments. The third version constructs an ofstream object and opens the file fname with open mode equal to mode and protection mode equal to prot. The default value for mode is ios::out, and the default value for prot is filebuf::openprot. If the file cannot be opened, the error state of the constructed ofstream object is set. The fourth version constructs an ofstream object that is attached to the file descriptor filedesc. If filedesc is not open, ios::failbit is set in the format state of ofs. This constructor also sets up an associated filebuf object with a stream buffer that has length len bytes and begins at the position pointed to by bufpos. If p is equal to 0 or len is equal to 0, the associated filebuf object is unbuffered. ═══ 4.9.5.2. open - Open File and Connect to ofstream Object ═══ Class: ofstream void open(const char* fname, int mode, int prot=filebuf::openprot); open() opens the file with the name fname and attaches it to ofs. If fname does not already exist, open() tries to create it with protection mode equal to prot, unless ios::nocreate is set. The default value for mode is ios::out. The default value for the argument prot is filebuf::openprot. If ofs is already attached to a file, or if the call to the function ofs.rdbuf()->open() fails, ios::failbit is set in the error state for ofs. The members of the ios::open_mode enumeration are bits that can be ORed together. The value of mode is the result of such an OR operation. This result is an int value, and for this reason, mode has type int rather than open_mode. See open - Open File and Connect to fstream Object for a list of the possible values for mode. ═══ 4.9.5.3. rdbuf - Return Pointer to filebuf Object ═══ Class: ofstream filebuf* rdbuf(); rdbuf() returns a pointer to the filebuf object that is attached to ofs. ═══ 4.9.6. Example of Using fstream, ifstream, and ofstream ═══ In the following example, the ifstream object source is associated with the input file source.dat, and the ofstream object dest is associated with the output file dest.dat. After both files have been opened, the contents of source.dat are written to dest.dat through the associated ifstream and ofstream objects. #include #include void main() { ifstream source("source.dat"); ofstream dest("dest.dat"); // // Check that the source file was opened correctly if (!source) { cerr << "Cannot open file 'source.dat'" << endl; exit(1); } // // Check that the destination file was opened correctly if (!dest) { cerr << "Cannot open file 'dest.dat'" << endl; exit(1); } // Read source file and write it to the dest file. char c = 0; while (dest && source.get(c)) dest.put(c); if (!source.eof()) { cerr << "Unexpected result" << endl; exit(1); } // // Close files. source.close(); dest.close(); exit(0); } ═══ 4.10. strstreambuf Class ═══ This chapter describes the strstreambuf class, the class that specializes streambuf to use an array of bytes in memory as the ultimate producer or ultimate consumer. The following topics are described in this chapter: o Declarations for strstreambuf in strstrea.h header file o Public members of strstreambuf ═══ 4.10.1. Declarations for strstreambuf in strstrea.h ═══ You must include the following statement in any file that uses the strstreambuf class: #include The following is an excerpt from the strstrea.h header file that shows the relevant declarations for the public, nonvirtual members of strstreambuf: class strstreambuf : public streambuf { public: strstreambuf(); strstreambuf(int) strstreambuf(void* (*a)(long), void (*f)(void*)); strstreambuf(char* b, int size, char* pstart = 0 ); strstreambuf(signed char* b, int size, signed char* pstart = 0 ); strstreambuf(unsigned char* b, int size, unsigned char* pstart = 0 ); ~strstreambuf(); int pcount(); void freeze(int n=1); char* str(); virtual int doallocate(); virtual int overflow(int); virtual int underflow(); virtual streampos seekoff(streamoff, ios::seek_dir, int); virtual streambuf* setbuf(char* p, int n); }; Note: Do not use pcount(). It is declared as a public member function of the strstreambuf class, but pcount() is meant to be used internally by the I/O Stream Library. ═══ 4.10.2. Public Members of strstreambuf ═══ The following functions are described: o Constructors for strstreambuf o Destructor for strstreambuf o doallocate - allocate space for a stream buffer o freeze - control deletion of stream buffer o overflow - clear put area o str - return pointer to beginning of stream buffer and freeze strstreambuf Object o seekoff - reposition get or put pointer in memory array o setbuf - set minimum stream buffer size o underflow - fill get area. ═══ 4.10.2.1. Constructors for strstreambuf ═══ Class: strstreambuf strstreambuf(); strstreambuf(int bufsize); strstreambuf(void* (*alloc) (long), void(*free)(void*)); strstreambuf(char* sp, int len, char* tp); strstreambuf(signed char* sp, int len, signed char* tp); strstreambuf(unsigned char* sp, int len, unsigned char* tp); The first version of the strstreambuf constructor takes no arguments and constructs an empty strstreambuf object in dynamic mode. Space will be allocated automatically to accommodate the characters that are put into the strstreambuf object. This space will be allocated using the operator new and deallocated using the operator delete. The characters that are already stored by the strstreambuf object may have to be copied when new space is allocated. If you know you are going to insert many characters into an strstreambuf object, you can give the I/O Stream Library an estimate of the size of the object before you create it by calling strstreambuf::setbuf(). The second version of the strstreambuf constructor takes one argument and constructs an empty strstreambuf object in dynamic mode. The initial size of the stream buffer will be at least bufsize bytes. The third version of the strstreambuf constructor takes two arguments and creates an empty strstreambuf object in dynamic mode. alloc is a pointer to the function that is used to allocate space. alloc is passed a long value that equals the number of bytes that it is supposed to allocate. If the value of alloc is 0, the operator new is used to allocate space. free is a pointer to the function that is used to free space. free is passed an argument that is a pointer to the array of bytes that alloc allocated. If free has a value of 0, the operator delete is used to free space. The fourth, fifth, and sixth versions of the strstreambuf constructor take three arguments and construct a strstreambuf object with a stream buffer that begins at the position pointed to by sp. The nature of the stream buffer depends on the value of len: o If len is positive, the len bytes following the position pointed to by sp make up the stream buffer. o If len equals 0, sp points to the beginning of a null-terminated string, and the bytes of that string, excluding the terminating null character, will make up the stream buffer. o If len is negative, the stream buffer has an indefinite length. The get pointer of the stream buffer is initialized to sp, and the put pointer is initialized to tp. Regardless of the value of len, if the value of tp is 0, the get area will include the entire stream buffer, and insertions will cause errors. ═══ 4.10.2.2. Destructor for strstreambuf ═══ Class: strstreambuf ~strstreambuf(); If freeze() has not been called for the strstreambuf object, and a stream buffer is associated with the strstreambuf object, the strstreambuf destructor frees the space allocated by the strstreambuf constructor. The effect of the destructor depends on the constructor used to create the strstreambuf object: o If you created the strstreambuf object using the constructor that takes two pointers to functions as arguments (see Constructors for strstreambuf for more details), the destructor frees the space allocated by the destructor by calling the function pointed to by the second argument to the constructor. o If you created the strstreambuf object using any of the other constructors, the destructor calls the delete operator to free the space allocated by the constructor. ═══ 4.10.2.3. doallocate - Allocate Space for a Stream Buffer ═══ Class: strstreambuf virtual int doallocate(); doallocate() attempts to allocate space for a stream buffer. If you created the strstreambuf object using the constructor that takes two pointers to functions as arguments (see Constructors for strstreambuf for more details), doallocate() allocates space for the stream buffer by calling the function pointed to by the first argument to the constructor. Otherwise, doallocate() calls the operator new to allocate space for the stream buffer. ═══ 4.10.2.4. freeze - Control Deletion of Stream Buffer ═══ Class: strstreambuf void freeze(int n=1); freeze() controls whether the array that makes up a stream buffer can be deleted automatically. If n has a nonzero value, the array is not deleted automatically. If n equals 0, the array is deleted automatically when more space is needed or when the strstreambuf object is deleted. If you call freeze() with a nonzero argument for a strstreambuf object that was allocated in dynamic mode, any attempts to put characters in the stream buffer may result in errors. Therefore, you should avoid insertions to such stream buffers because the results are unpredictable. However, if you have a "frozen" stream buffer and you call freeze() with an argument equal to 0, you can put characters in the stream buffer again. Only space that is acquired through dynamic allocation is ever freed. ═══ 4.10.2.5. overflow - Clear Put Area ═══ Class: strstreambuf virtual int overflow(int c); overflow() causes the ultimate consumer to consume the characters in the put area and calls setp() to establish a new put area. The argument c is stored in the new put area if c is not equal to EOF. ═══ 4.10.2.6. str - Return Pointer to Beginning of Stream Buffer and Freeze strstreambuf Object ═══ Class: strstreambuf char* str(); str() returns a pointer to the first character in the stream buffer and calls freeze() with a nonzero argument. Any attempts to put characters in the stream buffer may result in errors. If the strstreambuf object was created with an explicit array (that is, the strstreambuf constructor with three arguments was used), str() returns a pointer to that array. If the strstreambuf object was created in dynamic mode and nothing is stored in the array, str() may return 0. ═══ 4.10.2.7. seekoff - Reposition Get or Put Pointer in Memory Array ═══ Class: strstreambuf virtual streampos seekoff( streamoff so, ios::seek_dir dir, int mode); seekoff() repositions the get or put pointer in the array of bytes in memory that serves as the ultimate producer or the ultimate consumer. For a text mode file, seekoff() returns the actual physical file position, because carriage return characters and end-of-file characters are discarded on input. Thus, there may not be a one-to-one correspondence between the characters in a stream and those in its external representation. For further details, see "Low-Level I/O" in the IBM C/C++ Tools C Library Reference. If you constructed the strstreambuf in dynamic mode (see Constructors for strstreambuf), the results of seekoff() are unpredictable. Therefore, do not use seekoff() with an strstreambuf object that you created in dynamic mode. If you did not construct the strstreambuf object in dynamic mode, seekoff() attempts to reposition the get pointer or the put pointer, depending on the value of mode. If ios::in is set in mode, seekoff() repositions the get pointer. If ios::out is set in mode, seekoff() repositions the put pointer. If both ios::in and ios::out are set, seekoff() repositions both pointers. seekoff() attempts to reposition the affected pointer to the value of dir + so. dir can have the following values: o ios::beg: the beginning of the array in memory o ios::cur: the current position in the array in memory o ios::end: the end of the array in memory. If the value of dir + so is equal to or greater than the end of the array, the value is not valid and seekoff() returns EOF. Otherwise, seekoff() sets the affected pointer to this value and returns this value. The following example shows some of the settings of dir and so that can result in a value that is not valid: #include #include char *DATA = "Hello"; #define MODE ios::in void main() { streampos pos; strstream temp (DATA, (int)strlen(DATA)+1, ios::in); strstreambuf *ss = temp.rdbuf(); // // invalid: so = 0, dir = ios::end streamoff offset = 0; pos= ss->seekoff(offset, ios::end, MODE); if (pos == streampos(EOF)) { cout << "seekoff returned EOF" << endl; cout << "offset equals " << offset << endl; cout << "position equals " << ios::end << endl; } // // invalid: so = strlen(DATA)+1, dir = ios::beg offset = strlen(DATA)+1; pos= ss->seekoff(offset, ios::beg, MODE); if (pos == streampos(EOF)) { cout << "seekoff returned EOF" << endl; cout << "offset equals " << offset << endl; cout << "position equals " << ios::beg << endl; } // // valid: so = -1, dir = ios::end offset = -1; pos= ss->seekoff(offset, ios::end, MODE); if (pos == streampos(EOF)) { cout << "seekoff returned EOF" << endl; cout << "offset equals " << offset << endl; cout << "position equals " << ios::end << endl; } // // invalid: so = 1, dir = ios::cur offset = 1; pos= ss->seekoff(offset, ios::cur, MODE); if (pos == streampos(EOF)) { cout << "seekoff returned EOF" << endl; cout << "offset equals " << offset << endl; cout << "position equals " << ios::cur << endl; } } The attempts to position the get pointer to the end of the array or beyond the end of the array are not valid. seekoff() returns EOF in these cases. The following is the expected output of this example: seekoff returned EOF offset equals 0 position equals 2 seekoff returned EOF offset equals 6 position equals 0 seekoff returned EOF offset equals 1 position equals 1 ═══ 4.10.2.8. setbuf - Set Minimum Stream Buffer Size ═══ Class: strstreambuf virtual streambuf* setbuf(0, int bufsize); setbuf() records bufsize. The next time that the strstreambuf object dynamically allocates a stream buffer, the stream buffer is at least bufsize bytes long. Note: If you call setbuf() for an strstreambuf object, you must call it with the first argument equal to 0. ═══ 4.10.2.9. underflow - Fill Get Area ═══ Class: strstreambuf virtual int underflow(); If the get area is not empty, underflow() returns the first character in the get area. If the get area is empty, underflow() creates a new get area that is not empty and returns the first character. If no more characters are available in the ultimate producer, underflow() returns EOF and leaves the get area empty. ═══ 4.11. strstream, istrstream, and ostrstream Classes ═══ This chapter describes istrstream, ostrsteam, and strstream, the classes that specialize istream, ostream, and iostream (respectively) to use strstreambuf objects for stream buffers. These classes are called the array stream buffer classes because their stream buffers are arrays of bytes in memory. You can use these classes to perform input and output with strings in memory. This chapter also describes strstreambase, the class from which the array stream buffer classes are derived. The following topics are described in this chapter: o Declarations for array stream buffer classes in strstrea.h o Public members of strstreambase o Public members of strstream o Public members of istrstream o Public members of ostrstream ═══ 4.11.1. Declarations for strstream, istrstream and ostrstream in strstrea.h ═══ You must include the following statement in any file that uses istrstream, ostrsteam, or strstream: #include The following is an excerpt from the strstrea.h header file that shows the relevant declarations for the members of the istrstream, ostrsteam, and strstream classes: class strstreambase : public virtual ios { public: strstreambuf* rdbuf(); }; class istrstream : public strstreambase, public istream { public: istrstream(char* str); istrstream(signed char* str); istrstream(unsigned char* str); istrstream(char* str, int size ); istrstream(signed char* str, int size); istrstream(unsigned char* str, int size); istrstream(const char* str); istrstream(const signed char* str); istrstream(const unsigned char* str); istrstream(const char* str, int size ); istrstream(const signed char* str, int size); istrstream(const unsigned char* str, int size); ~istrstream(); }; class ostrstream : public strstreambase, public ostream { public: ostrstream(char* str, int size, int=ios::out); ostrstream(signed char* str, int size, int=ios::out); ostrstream(unsigned char* str, int size, int=ios::out); ostrstream(); ~ostrstream(); char* str(); int pcount(); }; class strstream : public strstreambase, public iostream { public: strstream(); strstream(char* str, int size, int mode); strstream(signed char* str, int size, int mode); strstream(unsigned char* str, int size, int mode); ~strstream(); char* str(); }; ═══ 4.11.2. Public Members of strstreambase ═══ Note: The strstreambase class is an internal class that provides common functions for the classes that are derived from it. Do not use the strstreambase class directly. The following description is provided so that you can use the function as part of istrstream, ostrsteam, and strstream objects. ═══ 4.11.2.1. rdbuf - Return Pointer to Associated Stream Buffer ═══ Class: ostrsteam strstreambuf* rdbuf(); rdbuf() returns a pointer to the stream buffer that the strstreambase object is attached to. ═══ 4.11.3. Public Members of strstream ═══ The following functions are described: o Constructor for strstream o Destructor for strstream o str - return pointer to stream buffer array An example of using the strstream class is also provided. ═══ 4.11.3.1. Constructor for strstream ═══ Class: strstream strstream(); strstream(char* cp, int len, int mode); strstream(signed char* cp, int len, int mode); strstream(unsigned char* cp, int len, int mode); There are two versions of the strstream constructor. The version that takes no arguments specifies that space is allocated dynamically for the stream buffer that is attached to the strstream object. The version of the strstream constructor that takes three arguments specifies that characters should be extracted and inserted into the array of bytes that starts at the position pointed to by cp with a length of len bytes. If ios::ate or ios::app is set in mode, cp points to a null-terminated string and insertions begin at the null character. Otherwise, insertions begin at the position pointed to by cp. You can use the istream::seekg() function to reposition the get pointer anywhere in this array. ═══ 4.11.3.2. Destructor for strstream ═══ Class: ostrsteam ~strstream(); The strstream destructor frees the space allocated by the strstream constructor. ═══ 4.11.3.3. str - Return Pointer to Stream Buffer Array ═══ Class: ostrsteam char* str(); str() returns a pointer to the stream buffer attached to the strstream and calls freeze() with a nonzero value to prevent the stream buffer from being deleted. If the stream buffer was constructed with an explicit array, the value returned is a pointer to that array. If the stream buffer was constructed in dynamic mode, cp points to the dynamically allocated area. Until you call str(), deleting the dynamically allocated stream buffer is the responsibility of the strstream object. After str() has been called, the calling application has responsibility for the dynamically allocated stream buffer. Note: If your application calls str() without calling freeze() with a nonzero argument (to unfreeze the strstream), or without explicitly deleting the array of characters returned by the call to str(), the array of characters will not be deallocated by the strstream when it gets destroyed. This situation is a potential source of a memory leak. ═══ 4.11.3.4. Example of Using the strstream Class ═══ Class: ostrsteam The following example shows how you can use the strstream class. An strstream object s is created, and a line of data is written into it. This data is sent to cout using str(). str() calls freeze() with a nonzero argument and "freezes" the stream buffer attached to s. Therefore, the next step is to "thaw" the stream buffer by calling freeze() with an argument equal to 0. Once this has been done, the program continues by writing each character in s to cout using get(). #include void main() { strstream s; char c; s << "A line of data is written to the strstream."; // // Get access to the stream buffer via str(). // The call to str() freezes the stream buffer. cout << "The string is: " << s.str() << endl; // // Now thaw it so that we can proceed. s.rdbuf()->freeze(0); cout << "The string is: "; while (s) { c = s.get(); cout << c; } cout << endl; } The example produces the following output: The string is: A line of data is written to the strstream. The string is: A line of data is written to the strstream. ═══ 4.11.4. Public Members of istrstream ═══ The following functions are described: o Constructors for istrstream o Destructor for istrstream ═══ 4.11.4.1. Constructors for istrstream ═══ Class: istrstream istrstream(char* cp); istrstream(signed char* cp); istrstream(unsigned char* cp); istrstream(const char* cp); istrstream(const signed char* cp); istrstream(const unsigned char* cp); istrstream(char* cp, int len); istrstream(signed char* cp, int len); istrstream(unsigned char* cp, int len); istrstream(const char* cp, int len); istrstream(const signed char* cp, int len); istrstream(const unsigned char* cp, int len); The versions of the istrstream constructor that take one argument specify that characters should be extracted from the null-terminated string that is pointed to by cp. You can use the istream::seekg() function to reposition the get pointer in this string. The versions of the istrstream constructor that take two arguments specify that characters should be extracted from the array of bytes that starts at the position pointed to by cp and has a length of len bytes. You can use istream::seekg() to reposition the get pointer anywhere in this array. ═══ 4.11.4.2. istrstream Destructor ═══ Class: ostrsteam ~istrstream(); The istrstream destructor frees space that was allocated by the istrstream constructor. ═══ 4.11.5. Public Members of ostrstream ═══ The following functions are described: o Constructors for ostrstream o Destructor for ostrstream o str - return pointer to stream buffer array o pcount - return number of characters in stream buffer ═══ 4.11.5.1. Constructors for ostrstream ═══ Class: ostrsteam ostrstream(); ostrstream(char* cp, int len, int mode = ios::out); ostrstream(signed char* cp, int len, int mode = ios::out); ostrstream(unsigned char* cp, int len, int mode = ios::out); The version of the ostrsteam constructor that takes no arguments specifies that space is allocated dynamically for the stream buffer that is attached to the ostrsteam object. The versions of the ostrsteam constructor that take three arguments specify that the stream buffer that is attached to the ostrsteam object consists of an array that starts at the position pointed to by cp with a length of len bytes. If ios::ate or ios::app is set in mode, cp points to a null-terminated string and insertions begin at the null character. Otherwise, insertions begin at the position pointed to by cp. You can use the ostream::seekp() function to reposition the put pointer. ═══ 4.11.5.2. Destructor for ostrstream ═══ Class: ostrsteam ~ostrstream(); The ostrsteam destructor frees space allocated by the ostrsteam constructor. The destructor also writes a null byte to the stream buffer to terminate the stream. ═══ 4.11.5.3. str - Return Pointer to Stream Buffer Array ═══ Class: ostrsteam char* str(); str() returns a pointer to the stream buffer attached to the ostrsteam and calls freeze() with a nonzero value to prevent the stream buffer from being deleted. If the stream buffer was constructed with an explicit array, the value returned is a pointer to that array. If the stream buffer was constructed in dynamic mode, cp points to the dynamically allocated area. Until you call str(), deleting the dynamically allocated stream buffer is the responsibility of the ostrsteam object. After str() has been called, the calling application has responsibility for the dynamically allocated stream buffer. ═══ 4.11.5.4. pcount - Return Number of Characters in Stream Buffer ═══ Class: ostrsteam int pcount(); pcount() returns the number of bytes that have been stored in the stream buffer. pcount() is mainly useful when binary data has been stored and the stream buffer attached to the ostrsteam object is not a null-terminated string. pcount() returns the total number of bytes, not just the number of bytes up to the first null character. ═══ 4.12. stdiobuf and stdiostream Classes ═══ This chapter describes the stdiobuf class and stdiostream, the class that uses stdiobuf objects as stream buffers. Operations on an stdiobuf are mirrored on the associated FILE structure (defined in the C header file stdio.h). Note: The classes described in this chapter are meant to be used when you have to mix C code with C++ code. If you are writing new C++ code, use filebuf fstream, ifstream, and ofstream instead of stdiobuf and stdiostream. The following topics are described in this chapter: o Declarations for stdiobuf and stdiostream in stdiostr.h o Public members of stdiobuf o Public members of stdiostream ═══ 4.12.1. Declarations for stdiobuf and stdiostream in stdiostr.h ═══ You must include the following statement in any file that uses the stdiobuf class: #include The following is an excerpt from the stdiostr.h header file that shows the relevant declarations for the members of stdiobuf: class stdiobuf : public streambuf { public: stdiobuf(FILE* f); virtual ~stdiobuf(); virtual int overflow(int=EOF); virtual int underflow(); virtual int sync() ; virtual streampos seekoff(streamoff,ios::seek_dir,int); virtual int pbackfail(int c); FILE* stdiofile(); }; class stdiostream : public ios { public: stdiostream(FILE*); ~stdiostream(); stdiobuf* rdbuf(); }; ═══ 4.12.2. Public Members of stdiobuf ═══ The following functions are described: o Constructor for stdiobuf o Destructor for stdiobuf o stdiofile - return associated FILE ═══ 4.12.2.1. Constructor for stdiobuf ═══ Class: stdiobuf stdiobuf(FILE* f); The stdiobuf constructor creates an stdiobuf object that is associated with the FILE pointed to by f. Changes that are made to the stream buffer in an stdiobuf object are also made to the associated FILE pointed to by f. Note: If ios::stdio is set in the format state of an ostream object, a call to osfx() flushes stdout and stderr. ═══ 4.12.2.2. Destructor for stdiobuf ═══ Class: stdiobuf ~stdiobuf(); The stdiobuf destructor frees space allocated by the stdiobuf constructor and flushes the file that this stdiobuf object is associated with. ═══ 4.12.2.3. stdiofile - Return Associated FILE ═══ Class: stdiobuf FILE* stdiofile(); stdiofile() returns a pointer to the FILE object that the stdiobuf object is associated with. ═══ 4.12.3. Public Members of stdiostream ═══ The following member functions are described: o Constructor for stdiostream o rdbuf - return pointer to stream buffer An example of using stdiostream is also provided. ═══ 4.12.3.1. Constructor for stdiostream ═══ Class: stdiostream stdiostream(FILE* file); The stdiostream constructor creates a stdiostream object that is attached to the FILE pointed to by file. ═══ 4.12.3.2. rdbuf - Return Pointer to Stream Buffer ═══ Class: stdiostream stdiobuf* rdbuf(); rdbuf() returns a pointer to the stdiobuf object that is attached to the stdiostream object. ═══ 4.12.3.3. Example of How to Use stdiostream ═══ The following example shows how you can use the stdiostream class. Two files are opened using fopen(). The pointers to the FILE structures are then used to create stdiostream objects. Finally, the contents of one of these stdiostream objects are copied into the other stdiostream object. #include #include #include void main() { FILE *in = fopen("in.dat", "r"); FILE *out = fopen("out.dat", "w"); int c; if (in == NULL) { cerr << "Cannot open file 'in.dat' for reading." << endl; exit(1); } if (out == NULL) { cerr << "Cannot open file 'out.dat' for writing." << endl; exit(1); } // // Create a stdiostream object attached to "f" // stdiostream sin(in); stdiostream sout(out); cout << "The data contained in the file is: " << endl; // // Now read data from "sin" and copy it to // "cout" and "sout" // while ((c = sin.rdbuf()->sbumpc()) != EOF) { cout << char(c); sout.rdbuf()->sputc(c); } cout << endl; } If you run this example with an input file containing the following: input input input input The following output is produced: The data contained in the file is: input input input input ═══ 4.13. Manipulators ═══ This chapter describes the parameterized manipulators provided by the I/O Stream Library and the facilities you can use to declare your own manipulators. The following topics are described in this chapter: o Introduction to manipulators o Declarations for parameterized manipulators in iomanip.h o Simple manipulators and parameterized manipulators o Creating simple manipulators for your own types o Creating parameterized manipulators for your own types o Parameterized manipulators for the format state ═══ 4.13.1. Introduction to Manipulators ═══ Manipulators provide a convenient way of changing the characteristics of an input or output stream, using the same syntax that is used to insert or extract values. Manipulators allow you to embed a function call in an expression that contains a series of insertions or extractions. Manipulators usually provide shortcuts for sequences of iostream library operations. See Simple Manipulators and Parameterized Manipulators for a description of the two kinds of manipulators. The iomanip.h header file contains a definition for a macro IOMANIPdeclare(). IOMANIPdeclare() takes a type name as an argument and creates a series of classes that can be used to define manipulators for a given kind of stream. Calling the macro IOMANIPdeclare() with a type as an argument creates a series of classes that let you define manipulators for your own classes. You will get a syntax error if you call IOMANIPdeclare() with the same argument more than once in a file. ═══ 4.13.2. Declarations for Parameterized Manipulators in iomanip.h ═══ You must include the following statement in any file that uses members of the parameterized manipulator classes: #include The following is an excerpt from the iomanip.h header file that shows the relevant declarations for the members of the parameterized manipulator classes. This header file supplies macro definitions that you can use to define new parameterized manipulators. #include #include #define SMANIP(T)name2(smanip_,T) #define SAPP(T)name2(sapply_,T) #define IMANIP(T)name2(imanip_,T) #define OMANIP(T)name2(omanip_,T) #define IOMANIP(T)name2(iomanip_,T) #define IAPP(T)name2(iapply_,T) #define OAPP(T)name2(oapply_,T) #define IOAPP(T)name2(ioapply_,T) #define IOMANIPdeclare(T) class SMANIP(T) { ios& (*fct)(ios&,T); T arg ; public: SMANIP(T)(ios& (*f)(ios&, T), T a); friend istream& operator>>(istream& i,const SMANIP(T)& m); friend ostream& operator<<(ostream& o, const SMANIP(T)& m); }; class SAPP(T) { ios& (*fct)(ios&, T); public: SAPP(T)(ios& (*f)(ios&,T)); SMANIP(T) operator()(T a); }; class IMANIP(T) { istream& (*fct)(istream&,T); T arg; public: IMANIP(T)(istream& (*f)(istream&, T), T a ); friend istream& operator>>(istream& s, const IMANIP(T)& m); }; class IAPP(T) { istream& (*fct)(istream&, T); public: IAPP(T)(istream& (*f)(istream&,T)); IMANIP(T) operator()(T a); }; class OMANIP(T) { ostream& (*fct)(ostream&,T); T arg; public: OMANIP(T)(ostream& (*f)(ostream&, T), T a ); friend ostream& operator<<(ostream& s, const OMANIP(T)& m); }; class OAPP(T) { ostream& (*fct)(ostream&, T); public: OAPP(T)(ostream& (*f)(ostream&,T)); OMANIP(T) operator()(T a); }; class IOMANIP(T) { iostream& (*fct)(iostream&,T); T arg ; public: IOMANIP(T)(iostream& (*f)(iostream&, T), T a ); friend istream& operator>>(iostream& s, const IOMANIP(T)& m); friend ostream& operator<<(iostream& s, const IOMANIP(T)& m); }; class IOAPP(T) { iostream& (*fct)(iostream&, T); public: IOAPP(T)(iostream& (*f)(iostream&,T)); IOMANIP(T) operator()(T a); }; IOMANIPdeclare(int); IOMANIPdeclare(long); SMANIP(int) setbase(int b); SMANIP(long) resetiosflags(long b); SMANIP(long) setiosflags(long b); SMANIP(int) setfill(int f); SMANIP(int) setprecision(int p); SMANIP(int) setw(int w); Note: 1. The following classes are defined after the macro IOMANIPdeclare(T) expands: o SMANIP(T) o SAPP(T) o IMANIP(T) o IAPP(T) o OMANIP(T) o OAPP(T) o IOMANIP(T) o IOAPP(T) 2. These classes could have been implemented as template classes with the argument T rather than as macro expansions. 3. The macro IOMANIPdeclare(T) is defined on a single, continued line in the iomanip.h header file. The continuation delimiters have been omitted from the above excerpt to make it easier to read. ═══ 4.13.3. Simple Manipulators and Parameterized Manipulators ═══ There are two kinds of manipulators: o Simple manipulators do not take any arguments. The following classes have built-in simple manipulators: - ios - istream - ostream. o Parameterized manipulators require one or more arguments. setfill is an example of a parameterized manipulator. You can create your own parameterized manipulators and your own simple manipulators. The following example shows the uses of both simple and parameterized manipulators. #include #include ostream& SimpleGap (ostream& os) { return os << "____"; } ostream& ParmGap(ostream& os, int n) { for (int i=n;i;i--) os << '.'; return os; } OMANIP(int) ParmGap(int n) { return OMANIP(int)(ParmGap,n);} void main() { cout << "Here is a" << SimpleGap << "and some text" << endl << "Here is a" << ParmGap(10) << "of ten dots" << endl; } The simple manipulator SimpleGap allows you to write a fixed-length string of underscores to an ostream object. ParmGap allows you to write a variable-length string of dots to an ostream object. The length of the string of dots is specified as the argument to ParmGap. This program produces the following output: Here is a____and some text Here is a..........of ten dots ═══ 4.13.4. Creating Simple Manipulators for Your Own Types ═══ The I/O Stream Library gives you the facilities to create simple manipulators for your own types. Simple manipulators that manipulate istream objects are accepted by the following input operators: istream istream::operator>> (istream&, istream& (*f) (istream&)); istream istream::operator>> (istream&, ios&(*f) (ios&)); Simple manipulators that manipulate ostream objects are accepted by the following output operators: ostream ostream::operator<< (ostream&, ostream&(*f) (ostream&)); ostream ostream::operator<< (ostream&, ios&(*f) (ios&)); The definition of a simple manipulator depends on the type of object that it is supposed to modify. The following table shows sample function definitions to modify istream, ostream, and ios objects. ┌──────────────────────┬──────────────────────────────────────────┐ │ Class of object │ Sample function definition │ ├──────────────────────┼──────────────────────────────────────────┤ │ istream │ "istream &fi(istream&){ /*...*/ }" │ ├──────────────────────┼──────────────────────────────────────────┤ │ ostream │ "ostream &fo(ostream&){ /*...*/ }" │ ├──────────────────────┼──────────────────────────────────────────┤ │ ios │ "ios &fios(ios&){ /*...*/ }" │ └──────────────────────┴──────────────────────────────────────────┘ For example, if you want to define a simple manipulator tab that inserts a tab character into an ostream object, the definition would look like this: ostream (ostream& os){ return os << '\t'; } Thus defined, the tab manipulator could be used like this: cout << "The value is" << tab << "10" << endl; ═══ 4.13.5. Creating Parameterized Manipulators for Your Own Types ═══ The I/O Stream Library gives you the facilities to create parameterized manipulators for your own types. Follow these steps to create a parameterized manipulator that takes an argument of a particular type tp: 1. Call the macro IOMANIPdeclare(tp). Note that tp must be a single identifier. For example, if you want tp to be a reference to a long double value, use typedef to make a single identifier to replace the two identifiers that make up the type label long double: typedef long double& LONGREF 2. Determine the class of your manipulator. If you want to define the manipulator as shown in Example of Defining an APP Parameterized Manipulator, choose a class that has APP in its name (an APP class, also known as an applicator). If you want to define the manipulator as shown in Example of Defining a MANIP Parameterized Manipulator, choose a class that has MANIP in its name (a MANIP class). Once you have determined whether to use an APP class or a MANIP class, the particular class that you choose depends on the type of object that the manipulator is going to manipulate. The following table shows the class of objects to be modified, and the corresponding manipulator classes. ┌───────────────────────────────────┬───────────────────────────────────┐ │ Class to be modified │ Manipulator class │ ├───────────────────────────────────┼───────────────────────────────────┤ │ istream │ "IMANIP(tp)" or "IAPP(tp)" │ ├───────────────────────────────────┼───────────────────────────────────┤ │ ostream │ "OMANIP(tp)" or "OAPP(tp)" │ ├───────────────────────────────────┼───────────────────────────────────┤ │ iostream │ "IOMANIP(tp)" or "IOAPP(tp)" │ ├───────────────────────────────────┼───────────────────────────────────┤ │ The ios part of istream objects │ "SMANIP(tp)" or "SAPP(tp)" │ │ or ostream objects │ │ └───────────────────────────────────┴───────────────────────────────────┘ 3. Define a function f that takes an object of the class tp as an argument. The definition of this function depends on the class you chose in step 2, and is shown in the following table: ┌──────────────────────────┬───────────────────────────────────────┐ │ Class chosen │ Sample definition │ ├──────────────────────────┼───────────────────────────────────────┤ │ "IMANIP(tp)" or │ "istream &f(istream&, tp){/ *... */ │ │ "IAPP(tp)" │ }" │ ├──────────────────────────┼───────────────────────────────────────┤ │ "OMANIP(tp)" or │ "ostream &f(ostream&, tp){/* ... */ │ │ "OAPP(tp)" │ }" │ ├──────────────────────────┼───────────────────────────────────────┤ │ "IOMANIP(tp)" or │ "iostream &f(iostream&, tp){/* ... */ │ │ "IOAPP(tp)" │ }" │ ├──────────────────────────┼───────────────────────────────────────┤ │ "SMANIP(tp)" or │ "ios &f(ios&, tp){/* ... */ }" │ │ "SAPP(tp)" │ │ └──────────────────────────┴───────────────────────────────────────┘ 4. If you chose one of the APP classes in step 2, define the manipulator as shown in Example of Defining an APP Parameterized Manipulator If you chose one of the MANIP classes in step 2, define the manipulator as shown in Example of Defining a MANIP Parameterized Manipulator. These two methods produce equivalent manipulators. Note: Parameterized manipulators defined with IOMANIP or IOAPP are not associative. See Examples of Nonassociative Parameterized Manipulators for more details. ═══ 4.13.5.1. Example of Defining an APP Parameterized Manipulator ═══ In the following example, the macro IOMANIPdeclare is called with the user-defined class my_class as an argument. One of the classes that is produced, OAPP(my_class), is used to define the manipulator pre_print. #include // declare class class my_class { public: char * s1; const char c; unsigned short ctr; my_class(char *theme, const char suffix, unsigned short times): s1(theme), c(suffix), ctr(times) {} }; // print a character an indicated number of times // followed by a string ostream& produce_prefix(ostream& o, my_class mc) { for (register i=mc.ctr; i; --i) o << mc.c ; o << mc.s1; return o; } IOMANIPdeclare(my_class); // define a manipulator for the class my_class OAPP(my_class) pre_print=produce_prefix; void main() { my_class obj("Hello",'-',10); cout << pre_print(obj) << endl; } This program produces the following output: ----------Hello ═══ 4.13.5.2. Example of Defining a MANIP Parameterized Manipulator ═══ In the following example, the macro IOMANIPdeclare is called with the user-defined class my_class as an argument. One of the classes that is produced, OMANIP(my_class), is used to define the manipulator pre_print(). #include #include class my_class { public: char * s1; const char c; unsigned short ctr; my_class(char *theme, const char suffix, unsigned short times): s1(theme), c(suffix), ctr(times) {}; }; // print a character an indicated number of times // followed by a string ostream& produce_prefix(ostream& o, my_class mc) { for (register int i=mc.ctr; i; --i) o << mc.c ; o << mc.s1; return o; } IOMANIPdeclare(my_class); // define a manipulator for the class my_class OMANIP(my_class) pre_print(my_class mc) { return OMANIP(my_class) (produce_prefix,mc); } void main() { my_class obj("Hello",'-',10); cout << pre_print(obj) << "\0" << endl; } This example produces the same output as the previous example. ═══ 4.13.5.3. Examples of Nonassociative Parameterized Manipulators ═══ The following example demonstrates that parameterized manipulators defined with IOMANIP or IOAPP are not associative. The parameterized manipulator mysetw() is defined with IOMANIP. mysetw() can be applied once in any statement, but if it is applied more than once, it causes a compile-time error. You can avoid such an error by putting each application of mysetw into a separate statement. #include iostream& f(iostream & io, int i) { io.width(i); return io; } IOMANIP (int) mysetw(int i) { return IOMANIP(int) (f,i); } iostream_withassign ioswa; void main() { ioswa = cout ; int i1 = 8, i2 = 14; // // The following statement does not cause a compile-time // error. // ioswa << mysetw(3) << i1 << endl ; // // The following statement causes a compile-time error // because the manipulator mysetw is applied twice. // ioswa << mysetw(3) << i1 <> resetiosflags(flags); In this case, resetiosflags() calls is.setf(0,flags). resetiosflags() can also appear in an output stream: os << resetiosflags(flags); In this case, resetiosflags calls os.setf(0,flags). ═══ 4.13.6.2. setbase - Set Conversion Base ═══ Manipulators SMANIP(int) setbase(int base); setbase() sets the conversion base to be equal to the value of the argument base. If base equals 10, the conversion base is set to 10. If base equals 8, the conversion base is set to 8. If base equals 16, the conversion base is set to 16. Otherwise, the conversion base is set to 0. If the conversion base is 0, output is treated the same as if the base were 10, but input is interpreted according to the C++ lexical conventions. This means that input values that begin with "0" are interpreted as octal values, and values that begin with "0x" or "0X" are interpreted as hexadecimal values. ═══ 4.13.6.3. setfill - Set Fill Character ═══ Manipulators SMANIP(int) setfill(int fill); setfill() sets the fill character, ios::x_fill, to fill. The fill character is the character that appears in values that need to be padded to fill the field width. setfill() can appear in either an input stream or an output stream: is >> setfill(fill); os << setfill(fill); setfill() performs the same task as the function fill(). ═══ 4.13.6.4. setiosflags - Set Format Flags ═══ Manipulators SMANIP(long) setiosflags(long flags); setiosflags() sets the format flags specified in flags. setiosflags() can appear in an input stream: is >> setiosflags(flags); If it appears in an input stream, setiosflags() calls is.setf.(flags) If it appears in an output stream, setiosflags() calls os.setf(flags): os << setiosflags(flags); ═══ 4.13.6.5. setprecision - Set Precision ═══ Manipulators SMANIP(int) setprecision(int prec); setprecision() sets the precision format state variable, ios::x_prec, to the value of prec. The value of prec must be greater than zero. If the value of prec is negative, the precision format state variable is set to 6. setprecision() can appear in either an input stream or an output stream: is >> setprecision(prec); os << setprecision(prec); ═══ 4.13.6.6. setw - Set Field Width ═══ Manipulators SMANIP(int) setw(int width); setw() sets the width format state variable, ios::x_width, to the value of width. setw() can appear in either an input stream or an output stream: is >> setw(width); os << setw(width); ═══ 5. The Task Library ═══ Introduction to the Task Library Introduces the Task Library and lists the runtime error messages it generates. Task Handling Classes Describes object, sched, task, and timer, the task handling classes. These classes give you the facilities to create and manage tasks. Queue Management Classes Describes qhead and qtail the queue management classes. These classes let you implement a wide range of message-passing and data-buffering schemes. Interrupt_handler Class Describes Interrupt_handler, the class that allows your tasks to handle external events in the form of signals from the operating system. Simulation Classes Describes histogrm, randint, urand, and erand, the simulation classes. These classes provide utilities for writing program simulations and gathering statistics about them. ═══ 5.1. Introduction to the Task Library ═══ This chapter introduces the classes that make up the Task Library. This library provides you with facilities to write programs with routines that appear to run in parallel. These routines, or tasks, can communicate with each other and start new tasks, but they do not actually run concurrently. The Task Library lets you simulate concurrent execution and gives you the facilities to write simulations. Extended Task Library Examples contains examples of how you might use the Task Library to implement a parallel algorithm and event-driven simulations. Note: The Task Library is also referred to as the C++ Coroutine Library in some non-IBM documentation. ═══ 5.1.1. What Are Tasks? ═══ Each task described in the context of the Task Library is an instance of a class that you derive from the class task. The constructor for the task class is declared protected, so you do not create instances of the class task, only instances of the classes that you derive from task. Tasks are said to be nonpreemptive and lightweight. They are nonpreemptive because only a single task is executing at any one time, and that task continues to execute until it suspends itself or is terminated. Tasks are lightweight because less time and space are required to create a task than to create a true OS/2 process. Tasks are more similar to OS/2 threads than to OS/2 processes. Each task object has a pointer associated with it called thistask. thistask is a pointer to the task that is executing. For example, if you use thistask in the main() function, you are using a pointer to the main() task, the task whose code appears in the main() function. Note: Tasks are commonly used in program simulations. They are not meant to be replacements for multitasking facilities provided by OS/2 such as OS/2 processes and threads. For further information see Using the Task Library with OS/2. ═══ 5.1.2. What Do Tasks Do? ═══ Here are some of the things that tasks can do: o Communicate with other tasks using the facilities provided by the classes qhead and qtail. See Queue Management Classes for more details on the qhead and qtail classes. o Create new tasks. These tasks are called child tasks, and the task that creates them is called the parent task. o Wait for external events. The Interrupt_handler class allows tasks to wait for external events in the form of signals from the operating system. See Interrupt_handler Class for more details on the Interrupt_handler class. o Consume simulated time. The concept of simulated time is implemented by the timer class. ═══ 5.1.3. The Task Library Class Hierarchy ═══ The Task Library has the following class hierarchy: o randint: each object of this class provides an independent sequence of pseudo-random numbers. It is the base class for the following classes: - urand - erand o object is the base class for the following classes: - Interrupt_handler - qtail - qhead - sched o sched is itself the base class for the following classes: - timer - task o task is itself the base class for the internal class Interrupt_alerter The classes task and sched are used strictly as base classes. The constructors for both of these classes are declared protected. When you use the Task Library, you create objects of classes derived from these two classes rather than creating objects of these classes directly. Derivation Relationships in the Task Library shows the relationships between the classes in the task library. In the figure, two classes are connected by an arrow if the class at the pointed end of the arrow is derived from the class at the other end of the arrow. object and randint are the two base classes in the class hierarchy of the task library. histogram is a stand-alone class (that is, it is neither a base class nor a derived class), but it is commonly used in conjunction with randint. object ┌───────────┘││└───────────┐ │ ┌────┘└────┐ │ Interrupt_ qtail qhead sched handler │ │ ┌───┘ └───┐ timer task │ │ Interrupt_ alerter histogram randint ┌─────┘ └─────┐ urand erand Derivation Relationships in the Task Library ═══ 5.1.4. Using the Task Library with OS/2 ═══ The Task Library was originally coded to run in a UNIX** operating system environment. Compromises were made in porting the library to OS/2 because of architectural differences between operating systems. Use the following guidelines to ensure that your programs' use of the Task Library is appropriate and reliable. ═══ 5.1.4.1. Linking to the Task Library ═══ You must specify the TASK.LIB library when compiling or linking programs that use the Task Library. There is no multitasking version of the library. You should not use this library in a multitasking program. No dynamically linkable version of this library is provided. ═══ 5.1.4.2. Compiler Options for Programs that Use the Task Library ═══ You must compile any modules that use the Task Library with the following options to ensure that the correct stack tracebacks are generated for the Task Library: /Op- Disable all stack pointer optimization /O- Disable optimization (Note: this also sets /Os-) /Gh- Disable profiler hook (This is the default. See Tasks and the Execution Trace Analyzer for further details.) ═══ 5.1.4.3. Tasks and Threads ═══ All tasks run in the user process address space and therefore do not benefit from OS/2's interprocess memory protection. In addition, because threads are preemptive and tasks are not, threads may be an attractive alternative to tasks for many OS/2 processes. The Task Library should never be used in a multithreaded environment, because it is a single task simulating a multithreaded environment. Unpredictable results will occur if you use the Task Library in a true multithreaded environment. See "Creating Multithread Programs" in the IBM C/C++ Tools: Programming Guide for details on multithreaded programs. ═══ 5.1.4.4. Tasks and the Execution Trace Analyzer ═══ Do not attempt to use the execution trace analyzer with programs that make use of the Task Library. Your programs may compile successfully when you specify the /gh compiler option, but the results will be unpredictable and your program may fail without warning. ═══ 5.1.4.5. Other Restrictions ═══ Tasks are simulated on OS/2 by using the heap for all tasks. Because of differences in the way the Task Library and the operating system access the stack, you should follow the guidelines below: 1. You can register an exception handler for a task with OS/2, either through a call to DosSetExceptionHandler or through #pragma handler(). However, you should not register an exception in one task and use it in another task. 2. Do not call longjmp from one task to another. ═══ 5.1.4.6. The /noe Option and the Task Library ═══ If you experience problems linking your programs that use the Task Library with dde4sbs.lib, use the /noe option. ═══ 5.1.5. Task Library Error Messages ═══ The following list shows the errors that can be generated by member functions of the classes that make up the Task Library. The first line in each entry shows the name of the error and the text of the error message that is produced. For some errors, additional information may be provided to help you determine the cause of the error. This information is not included here. The second line explains the error. Note: You should always use the error name macros, rather than using error numbers directly. Error numbers may change in subsequent releases of the compiler, or may vary between different compilers. For example, IBM C Set ++ for AIX*/6000 uses error numbers starting at 1, while IBM C/C++ Tools for OS/2 uses error numbers starting at 7001. Error Name and Message Explanation E_OLINK object::delete(): has chain Attempt to delete an object that remembers a task. E_ONEXT object::delete(): on chain Attempt to delete an object that is still on some chain. E_GETEMPTY qhead::get(): empty Attempt to get from an empty queue that has mode E_MODE. E_PUTOBJ qtail::put(): object on another queue Attempt to put an object that is already on another queue. E_PUTFULL qtail::put(): full Attempt to put to a full queue that has mode E_MODE. E_BACKOBJ qhead::putback(): object on another queue Attempt to put back an object that is already on another queue. E_BACKFULL qhead::putback(): full Attempt to put back to a full queue that has mode E_MODE. E_SETCLOCK sched::setclock(): clock!=0 Clock was nonzero when setclock() was called. E_CLOCKIDLE sched::schedule(): clock_task not idle The clock_task was not IDLE when setclock() was called. E_RESTERM sched::schedule: terminated Attempt to resume a task object with state equal to TERMINATED. E_RESRUN sched::schedule: running Attempt to resume a task object with state equal to RUNNING. E_NEGTIME sched::schedule: clock<0 Negative argument to delay(). E_RESOBJ sched::schedule: task or timer on another queue Attempt to resume a task or timer object that is already on some queue. E_HISTO histogram::histogram: bad arguments Bad arguments for the histogram constructor. E_STACK task::restore(): stack overflow Task runtime stack overflow. E_STORE new: free store exhausted No more free store is available; the call to new() failed. E_TASKMODE task::task(): bad mode Mode argument not permitted for the task constructor. E_TASKDEL task::~task(): not terminated Attempt to delete a non-TERMINATED task object. E_TASKPRE task::preempt(): not running Attempt to preempt a non-RUNNING task. E_TIMERDEL timer::~timer(): not terminated Attempt to delete a non-TERMINATED timer object. E_SCHTIME schedule: bad time Scheduler run chain is corrupted; the time of the task at the beginning of the run chain is not valid. E_SCHOBJ sched object used directly (not as base) sched object used directly instead of as a base class. E_QDEL queue::~queue(): not empty Attempt to delete a nonempty queue. E_RESULT task::result(): thistask->result() A task object attempted to obtain its own result(). E_WAIT task::wait(): wait for self A task object called wait() with a pointer to itself as the argument. E_FUNCS FrameLayout:: FrameLayout(): function start Internal error; cannot determine the call frame layout. E_FRAMES FrameLayout:: FrameLayout(): frame size Internal error; cannot determine frame size. E_REGMASK task::fudge_return(): unexpected register mask Internal error; unexpected register mask. E_FUDGE_SIZE task::fudge_return(): frame too big Internal error; the frame size returned by fudge_return is too big. E_NO_HNDLR sigFunc - no handler for signal No handler for the generated signal. E_BADSIG illegal signal number Attempt to use a signal number that is out of range. E_LOSTHNDLR Interrupt_handler:: ~Interrupt_handler(): signal handler not on chain Attempt to call the destructor for a signal handler that has already been destroyed. E_RETURN task returns without calling sched::resultis(int) Unrecoverable error caused by an attempt to exit a task by a means other than calling resultis(). E_BADMODE Illegal mode passed to qhead::qhead(), qtail::qtail(), qhead::setmode() or qtail::setmode() Unrecoverable error caused by an attempt to set a mode that is not valid for a queue. E_QZERO Attempt to set the maximum size of a queue to a value less than or equal to 0 Unrecoverable error caused by an attempt to set maximum queue size to a value less than or equal to 0. E_URAND urand::urand(int, int) bad arguments Attempt to pass arguments that are not valid to urand::urand(). ═══ 5.2. Task Handling Classes ═══ This chapter describes the task handling classes: task, object, sched, and timer. You can use these classes to create and manage tasks. The fact that the Task Library has a class called object can cause some confusion. In this book, object (in normal typeface) refers to the C++ concept of an instance of a class, while object (in special typeface) refers to the class in the Task Library. In the rest of this book, an object of a given class, such as MyClass, is referred to as a MyClass object. For the sake of simplicity, an object of class object is called an object rather than an object object. Similarly, task (in normal typeface) refers to the concept of a lightweight, nonpreemptive process that can be used to create program simulations, while task (in special typeface) refers to the class in the Task Library. The following topics are described in this chapter: o Deriving classes from the task class o Shared and dedicated tasks o Declarations of task handling classes in task.h o Public members of object o Public members of sched o Members of task o Public members of timer ═══ 5.2.1. Object States ═══ The object class is designed to be used as a base class. Objects of all of the classes that are derived from the object class (sched, timer, task, and any classes that you derive from these classes) can be in one of the two following states: o If a task object has to wait for an object, the object that is waited for has a state of pending. If a task object performs a blocking operation (that is, an operation that may cause the task object to give up control of the processor while it waits for some event to take place) on a pending object, it will wait until the state of the object changes to ready. o An object that does not need to be waited for is ready. You can determine the state of an object by calling the object class member function pending(). pending() returns a nonzero value if the state of an object is pending and returns 0 if the state of an object is ready. Any class that is derived from the class object that may be waited for must have rules for when it is pending or ready (that is, it must define the virtual function pending()). Each class derived from the class object can have, at most, one definition for pending(). The following list contains some examples of pending objects: o A qhead object that is associated with an empty queue is pending. If a task calls qhead::get() for this object, that task must wait until some other task calls qtail::put() to put something in the queue. See Queue Management Classes for a description of queues. o A qtail object that is associated with a full queue is pending. If a task calls qtail::put() for this object, that task must wait until another task calls qhead::get() to remove something from the queue. o A task object that does not have a state equal to TERMINATED is pending. If another task object calls sched::result() for this task object, it must wait until the state of this task object changes to TERMINATED. Once the state of the task object has changed to TERMINATED, the task object is no longer pending. ═══ 5.2.2. Task States ═══ A task can be in one of the three following states: o RUNNING: the task is running or it will be scheduled to run. o IDLE: the task is waiting (possibly for a pending object). Each task object in the IDLE state has certain conditions that will change its state to RUNNING. o TERMINATED: the task is complete. It cannot return to the RUNNING state, but you can retrieve its result. ═══ 5.2.3. Deriving Classes from the task Class ═══ The task constructor is declared protected. This means that you cannot create objects of the class task itself. You must derive a class from task and create objects of this class. This section describes some of the things that you should keep in mind when you derive such a class. The following topics are discussed: o Parent and child tasks o Only a single level of derivation is allowed from the task class o Constructors for classes derived from task cannot be inline o Using the task constructor o The default stack size o Tasks must explicitly call destructors for objects they create ═══ 5.2.3.1. Parent and Child Tasks ═══ If a task is created by another task, then the created task is called a child task and the creating task is called a parent task. If the parent creates the child using dynamic allocation (that is, using the operator new), the child is created dynamically. Otherwise, the child is created on the local stack of the parent. ═══ 5.2.3.2. Only a Single Level of Derivation Is Allowed ═══ Only one level of derivation is allowed from the class task. C/C++ Tools will not produce an error message if you attempt to derive a class from a class that is derived from task, but the behavior of the class will be unpredictable. For example, the following declaration of d_task2 is not valid: class d_task1 : public task { /* valid declaration */ }; class d_task2 : public d_task1 { /* unpredictable results */ }; A class can be derived from a set of classes that includes the class task, but the derived class cannot be used as the base class for any other classes. ═══ 5.2.3.3. Constructors for Classes Derived from task Cannot Be Inline ═══ You should not define as inline the constructor for a class derived from the class task. You will not get a compile-time error if you attempt to do this, but the results will be unpredictable. For example: class d_task : public task { public: d_task() { /* inline constructor - results unpredictable */ } // . // . // . }; ═══ 5.2.3.4. Using the task Constructor ═══ Consider a class Addint that is derived from the class task. The body of the constructor for the Addint class constitutes the code that will be executed by tasks of the Addint class. Suppose that a task of the Addint class adds two numbers together. The definition for Addint could look something like this: #include #include class Addint : public task { public: Addint(int, int); }; The constructor for the class Addint looks like this: Addint::Addint(int a, int b) { resultis(a+b); } A task object of the class Addint could be created and used like this: void main(){ Addint ai(3,4); cout << "The sum is: " << ai.result() << endl; thistask->resultis(0); } This program produces the following output: The sum is: 7 ═══ 5.2.3.5. The Default Stack Size ═══ The default maximum stack size (in words) for tasks is defined as SIZE in the task.h header file. If you do not specify a maximum stack size when you call the task constructor, the maximum stack size will be set to this value. If you are creating a task that will need to put a large amount of data on the stack, you may need to use a maximum stack size that is bigger than the default. In the following example, the class BigStack is derived from the class task. The BigStack constructor specifies that the maximum stack size for objects of BigStack is bigger than SIZE: #include #define BIGSIZE SIZE + 256 class BigStack : public task { public: BigStack(); }; // // request a stack that has a size bigger than the default BigStack::BigStack() : task("Big",DEDICATED,BIGSIZE) { resultis(1); } void main() { BigStack bs; thistask->resultis(0); } ═══ 5.2.3.6. Tasks Must Explicitly Call Destructors for Objects They Create ═══ Usually, the destructors for all of the objects that were created on the stack within a block are automatically called when that block is exited. When a task calls task::resultis() however, it does not return, and the destructors for objects that were created by that task are not called automatically. Thus, before a task calls task::resultis(), it should call the destructors for all of the objects that have destructors and were created by the task on its stack. In the following example, the dedicated task mtask creates an object r1 on its local stack. The constructor for mtask must explicitly call the destructor for the object r1 to remove it from the run chain. class Resource { public: Resource(); // get resource ~Resource(); // give up resource }; // ... class MyTask : public task { public: MyTask(); }; MyTask::MyTask() { Resource r1; // ... r1.Resource::~Resource(); resultis(0); } void main() { MyTask mtask; // ... } ═══ 5.2.4. Shared and Dedicated Tasks ═══ When a task creates another task, it can create it as a shared task or as a dedicated task. You specify whether a task is shared or dedicated in the second argument to the protected constructor of the class task. See Constructor for task for a description of the task class constructor. Each dedicated task has its own stack that is dynamically allocated when the task is created. A shared task, on the other hand, shares the memory space for its stack with its parent. The following topics are described in this section: o Advantages of dedicated tasks o Advantages of shared tasks o Shared child tasks should be dynamically allocated o Passing arguments to shared child tasks ═══ 5.2.4.1. Advantages of Dedicated Tasks ═══ The advantage of using dedicated tasks is that it takes less time to switch between dedicated tasks than it takes to switch between shared tasks. Suppose that there are two tasks, task1 and task2, that share the same stack, and suppose that you want to switch from task1 to task2. Space must be allocated and the contents of the shared stack (that is, the contents of the stack of task1) must be copied into this space. This space is called the dynamic save area of task1. task2 then copies the contents of its stack (currently saved in its dynamic save area) into the shared stack. If you want to switch back to task1, the contents of the shared stack must be copied into the dynamic save area of task2, and the contents of the stack of task1 must be copied from the dynamic save area of task1 into the shared stack. When you switch between two dedicated tasks, the stacks do not have to be saved and restored because both tasks have their own separate stack spaces. The result is that it is faster to switch between dedicated tasks. ═══ 5.2.4.2. Advantages of Shared Tasks ═══ The advantage of using shared tasks is that you can save some memory. Each time that a dedicated task is created, a set amount of memory is allocated for its stack. Even though memory must be allocated for the dynamic save area before you switch between shared tasks, the system only needs to allocate the memory that is needed to save the portion of the stack that the shared task is using. This amount of memory may be considerably less than the set amount of memory that must be allocated for a dedicated task. Note: The following two sections describe some restrictions that are placed on the use of shared tasks. If you do not adhere to these restrictions when you use shared tasks, the results will be unpredictable. Because these restrictions do not affect dedicated tasks, you should use dedicated tasks whenever possible. ═══ 5.2.4.3. Shared Child Tasks Should Be Dynamically Allocated ═══ If a parent task creates a child that is a shared task, the parent should dynamically allocate the child task. The following example shows what can happen when child tasks are not dynamically allocated. In the following program, the child tasks are dynamically allocated if the macro WRONG is not defined, and they are not dynamically allocated if WRONG is defined. #include #include class Semaphore: public object { int signal; public: Semaphore(int s) : signal(s) {} int pending() { return signal <= 0; } void p(); void v(); }; void Semaphore::p(){ while (1) { if (--signal >= 0) return; signal++; thistask->sleep(this); } } void Semaphore::v(){ if (signal++ == 0) alert(); } class Child : public task { public: Child(char *name, Semaphore &); }; Child::Child(char *name, Semaphore &s) : task("Child", SHARED){ cout << "Child " << name <<" entered." << endl; s.p(); cout << "Child " << name <<" after p()." << endl; resultis(0); } class Parent : public task { public: Parent(Semaphore &); }; Parent::Parent(Semaphore &s) : task("Parent", SHARED){ #ifdef WRONG Child c1("c1",s); Child c2("c2",s); #else Child &c1 = *new Child("c1",s); Child &c2 = *new Child("c2",s); #endif cout << "Parent task after creating c1 and c2." << endl; c1.result(); c2.result(); cout << "Parent task after waiting " << "for c1 and c2 to terminate." << endl; resultis(0); } void main(){ #ifdef WRONG Semaphore s(0); Parent p1(s); #else Semaphore &s = *new Semaphore(0); Parent &p1 = *new Parent(s); #endif cout << "Main task after creating parent task." << endl; s.v(); s.v(); cout << "Main task after signalling semaphores." << endl; p1.result(); cout << "Main task after parent task has terminated." << endl; thistask->resultis(0); } If WRONG is not defined, the following objects are dynamically allocated: o c1 and c2, the Child objects that are created in the Parent constructor. o s, the Semaphore object that is created in main(). o p1, the Parent object that is created in main(). Because these are the only child tasks in the program, all of the child tasks are dynamically allocated. The program produces the following output if WRONG is not defined: Child c1 entered. Main task after creating parent task. Main task after signalling semaphores. Child c2 entered. Child c2 after p(). Child c1 after p(). Parent task after creating c1 and c2. Parent task after waiting for c1 and c2 to terminate. Main task after parent task has terminated. However, if WRONG is defined, none of c1, c2, s, and p1 is dynamically allocated. If you include the following statement: #define WRONG after the include statement for iostream.h, the program fails. The following output is produced: Child c1 entered. Main task after creating parent task. Main task after signalling semaphores. SYS1808: The process has stopped. The software diagnostic code (exception code) is 0005. ═══ 5.2.4.4. Passing Arguments to Shared Child Tasks ═══ If you want to pass a reference or a pointer to an object from a parent task to a shared child task, you should ensure that the object that you are passing is either dynamically allocated or declared in global scope. An argument that is either a reference or a pointer to an object that is created on the local stack of the parent task will not be passed properly. When a shared child task is created, its stack uses the same space as the local stack of the parent task. If you pass the child a pointer to a location in the parent's stack, this pointer will not be valid in the scope of the child task because it now points to a location occupied by the child's stack. Note that the parent and child tasks are sharing the same stack space, and thus the current contents of the stack space depend on which task has control of the stack. In the following example, q1 is not a valid argument to pass to the child task, but q2 and q3 are valid arguments: #include qtail q3; // argument with global scope class Parent : public task { public: Parent(); }; class Child : public task { public: Child(qtail*); }; Child::Child(qtail* qt) : task("Child",SHARED) { qt->print(0); resultis(0); } Parent::Parent() { qtail q1; // object declared on local // stack of parent // Child *c1 = new Child(&q1); // incorrect - argument was // created on local stack // of parent task // qtail *q2 = new qtail; // dynamically allocated // object // Child *c2 = new Child(q2); // correct - argument // dynamically allocated // Child *c3 = new Child(&q3); // correct - argument // declared in global scope resultis(0); }; void main() { Parent pp; thistask->resultis(0); } ═══ 5.2.5. Declarations for the Task Handling Classes in task.h ═══ You must include the following statement in any file that uses the task handling classes: #include The following is an excerpt from the task.h header file that show the relevant declarations for the members of the task handling classes. typedef int (*PFIO) (int,object*); typedef void (*PFV) (); typedef void SIG_FUNC_TYP(int); typedef void (*SIG_PF)(int); #define SIZE 1024 #define thistask (object::this_task()) #define run_chain (sched::get_run_chain()); #define task_chain (task::get_task_chain()) extern _hwm; class object{ friend class sched; friend class task; private: static sched* runchain; public: enum objtype { OBJECT, TIMER, TASK, QHEAD, QTAIL, INTHANDLER }; object* o_next; object(); virtual ~object(); virtual objtype o_type(); void remember(task*); void forget(task*); void alert(); virtual int pending(); virtual void print(int, int =0); static int task_error(int, object*); int task_error(int); static task* this_task(); static PFIO error_fct; }; class sched : public object { friend class timer; friend class task; friend class object; friend void _print_error(int n); friend SIG_FUNC_TYP sigFunc; public: enum statetype { IDLE, RUNNING, TERMINATED }; static void setclock(long); static long get_clock(); static sched* get_run_chain(); static int get_exit_status(); static void set_exit_status( int i ); sched* get_priority_sched(); static task* clock_task; long rdtime(); statetype rdstate(); int pending(); int keep_waiting(); int dont_wait(); void cancel(int); int result(); virtual void setwho(object* t); void print(int, int =0); static PFV exit_fct; }; class timer : public sched { void resume(); public: timer(long); ~timer(); void reset(long); object::objtype o_type(); void setwho(object*); void print(int, int =0); }; class task : public sched { friend class sched; private: int* t_framep; int* t_basep; object* t_alert; protected: task(char* name=0, modetype mode=DEFAULT_MODE, int stacksize=SIZE);: public: enum modetype { DEDICATED, SHARED }; ~task(); object::objtype o_type(); task* t_next; char* t_name; static task* get_task_chain(); int waitvec(object**); int waitlist(object* ...); void wait(object* ob); void delay(long); long preempt(); void sleep(object* t =0); void resultis(int); void cancel(int); void setwho(object* t); void print(int, int =0); object* who_alerted_me(); }; inline void setclock(long i); void _print_error(int); typedef int (*PFIO)(int,object*); typedef void (*PFV)(); typedef void SIG_FUNC_TYP(int); typedef void (*SIG_PF)(int); #define SIZE 1024 #define thistask (object::this_task()) #define run_chain (sched::get_run_chain()) #define task_chain (task::get_task_chain()) extern _hwm; class object { friend class sched; friend class task; private: static task* thxstxsk; public: enum objtype { OBJECT, TIMER, TASK, QHEAD, QTAIL, INTHANDLER }; object* o_next; object(); virtual ~object(); virtual objtype o_type(); void remember(task*); void forget(task*); void alert(); virtual int pending(); virtual void print(int, int =0); static int task_error(int, object*); int task_error(int); static task* this_task(); static PFIO error_fct; }; class sched : public object { friend class timer; friend class task; friend class object; friend void _print_error(int n); friend SIG_FUNC_TYP sigFunc; public: enum statetype { IDLE=1, RUNNING=2, TERMINATED=4 }; static void setclock(long); static long get_clock(); static sched* get_run_chain(); static int get_exit_status(); static void set_exit_status( int i ); sched* get_priority_sched(); static task* clock_task; long rdtime(); statetype rdstate(); int pending(); int keep_waiting(); int dont_wait(); void cancel(int); int result(); virtual void setwho(object* t); void print(int, int =0); static PFV exit_fct; }; class timer : public sched { void resume(); public: timer(long); ~timer(); void reset(long); object::objtype o_type(); void setwho(object*); void print(int, int =0); }; class task : public sched { friend class sched; private: int* t_framep; int* t_basep; object* t_alert; protected: task(char* name=0, modetype mode=DEFAULT_MODE, int stacksize=SIZE); public: enum modetype { DEDICATED, SHARED }; ~task(); object::objtype o_type(); task* t_next; char* t_name; static task* get_task_chain(); int waitvec(object**); int waitlist(object* ...); void wait(object* ob); void delay(long); long preempt(); void sleep(object* t =0); void resultis(int); void cancel(int); void setwho(object* t); void print(int, int =0); object* who_alerted_me(); }; inline void setclock(long i) { sched::setclock(i); } void _print_error(int); ═══ 5.2.6. Public Members of object ═══ Each object of the class object has a list of tasks called a remember chain. Tasks that are on the remember chain have a state of IDLE. These tasks will have their state changed from IDLE to RUNNING and be moved to the run chain when the state of the object changes from pending to ready. For every object of the task, timer, qhead, and qtail classes, a call to object::alert() is automatically made when the state of the object changes from pending to ready. If you derive a class from object, you must ensure that object::alert() is explicitly called by objects of that class for the tasks that are on their remember chains. Each object also has a pointer to a list of other objects. This pointer is used to chain together objects that are placed on a queue and task objects on the run chain of the sched object. Note: The following descriptions assume that the functions are called as part of an object called obj. The following functions are described: o Constructor for object o alert - change state of tasks o error_fct - user-defined error-handling function o forget - remove task from remember chain o o_type - return class object type o pending - return object state o print - print contents of object o remember - add task to remember chain o task_error - error-handling o this_task - return pointer to current task ═══ 5.2.6.1. Constructor for object ═══ Class: object object(); The object() constructor constructs an object that is not in any list of objects. ═══ 5.2.6.2. alert - Change State of Tasks ═══ Class: object void alert(); alert() changes the state of all of the tasks on the remember chain for obj from IDLE to RUNNING. ═══ 5.2.6.3. error_fct - User-Defined Error-Handling Function ═══ Class: object typedef int (*PFIO) (int, object*); static PFIO error_fct; When an error occurs, task_error() calls the function pointed to by error_fct with two arguments: the error number, and a pointer to the object that caused the error. To assign the address of a function to error_fct, use an expression similar to the following: error_fct = e_function; where e_function is a user-defined error-handling function that has the following format: int e_function(int errno, object* obj); The first argument, errno, is the error number, and obj is either 0 or a pointer to the object that called task_error(). If error_fct is set to point to such a function, task_error() calls this function with the error number and a pointer to the object as arguments. The pointer to the object is equal to 0 if task_error() was not called by an object. If the user-defined error function does not return 0, task_error calls exit() with an argument equal to errno. If the user-defined error function returns 0, task_error() retries the operation that caused the error. ═══ 5.2.6.4. forget - Remove Task from Remember Chain ═══ Class: object void forget(task* tsk); forget() removes the task object pointed to by tsk from the remember chain for obj. ═══ 5.2.6.5. o_type - Return Class Object Type ═══ Class: object virtual objtype o_type(); o_type() returns the class type of obj, namely object::OBJECT. ═══ 5.2.6.6. pending - Return Object State ═══ Class: object virtual int pending(); pending() is a virtual function that is meant to return 0 if obj is ready and a nonzero value if obj is pending. The default definition of pending() always returns 1. If you want to define a class that is derived from object, and if you want to be able to wait for objects of that class, you must explicitly define pending() for that class. ═══ 5.2.6.7. print - Print Contents of Object ═══ Class: object virtual void print(int x, int y=0); print() prints information about obj on standard output. object::print() is called by the print() member functions of the classes derived from object. The argument x specifies the amount of information to be printed. The argument y is used internally by the Task Library. Its default value is 0. print() prints the type of the object if x equals 0. If x equals VERBOSE, print() prints the type of the object along with the value of the this pointer and the list of tasks on the remember chain for this object. ═══ 5.2.6.8. remember - Add Task to Remember Chain ═══ Class: object void remember(task* tk); remember() adds the task pointed to by tk to the remember chain for obj. Tasks that are on the remember chain will be alerted when the state of obj becomes ready. ═══ 5.2.6.9. task_error - Error-Handling ═══ Class: object static int task_error(int errno, object* op); int task_error(int errno); task_error() is called by the task system when a runtime error occurs. errno is the error number. op is a pointer to the object that called task_error(). If the member error_fct points to a function, task_error() calls that function with errno and op as arguments Otherwise, print_error() is called with the argument errno. print_error() prints an error message on stderr and terminates the program. The nonstatic, single-argument form of task_error() is obsolete, but it is kept for compatibility with the AT&T** C++ Language System Release 1.2 Task Library. The runtime errors are listed in Task Library Error Messages. These errors can be divided into two groups: o Recoverable: the condition that caused the error should be corrected by the program in the function pointed to by error_fct. error_fct should return 0, and thus the function that caused the error can be tried again. o Unrecoverable: the condition that caused the error cannot be corrected by the program. The function that you define for error_fct must not return 0 for unrecoverable errors. If this function does return 0 for unrecoverable errors, the results will be unpredictable. The following runtime errors are recoverable: E_BACKOBJ E_FUNCS E_BACKFULL E_GETEMPTY E_FRAMES E_PUTOBJ E_FUDGE_SIZE E_PUTFULL The following runtime errors are unrecoverable: E_BADMODE E_QDEL E_BADSIG E_QZERO E_CLOCKIDLE E_REGMASK E_HISTO E_RESOBJ E_LOSTHNDLR E_RESRUN E_NEGTIME E_RESTERM E_NO_HNDLR E_RESULT E_OLINK E_RETURN E_ONEXT E_SCHOBJ ═══ 5.2.6.10. this_task - Return Pointer to Current Task ═══ Class: object static task* this_task(); #define thistask object::this_task() this_task() returns a pointer to the task that is currently running. The macro form, thistask, is kept for compatibility with the AT&T** C++ Language System Release 1.2 Task Library. ═══ 5.2.7. Public Members of sched ═══ The constructor for the sched class is declared protected, and thus you cannot create your own objects of the class sched. The sched class is important for the Task Library because it: o Provides common functions for task and timer, the classes that are derived from sched. o Provides functions for measuring simulated time. o Implements the scheduler, the construct of the Task Library that determines the task that is supposed to run next. The sched class includes a static data member called runchain. This is a list of all the tasks that are ready to run. Note: The following descriptions assume that the functions are called as part of schd, an object of a class derived from sched. The following functions are described: o cancel - change state to TERMINATED o clock_task - system clock task variable o dont_wait - return number of objects waiting for external events o exit_fct - user defined exit function o get_clock - return value of the task system clock o get_exit_status - return exit status of task program o get_priority_sched - return pointer to interrupt_alerter o get_run_chain - return pointer to run chain o keep_waiting - keep scheduler waiting o pending - return state o print - print the contents of sched object o rdstate - return the state of sched object o rdtime - return clock time o result - return result of sched object o setclock - initialize the system clock o setwho - record alerting object o set_exit_status - set exit status of task ═══ 5.2.7.1. cancel - Change State to TERMINATED ═══ Class: sched void cancel(int ret_val); cancel() changes the state of schd to TERMINATED without invoking the scheduler and sets the result of schd to ret_val. Because the scheduler is not invoked, a task object should not call cancel() on itself. ═══ 5.2.7.2. clock_task - System Clock Task Variable ═══ Class: sched static task* clock_task; clock_task is a pointer to the task that is scheduled each time the system clock advances, before any other tasks. The state of the task pointed to by clock_task must be IDLE when it is scheduled. The task that is pointed to by clock_task can ensure that it will have a state of IDLE by calling task::sleep() on itself. ═══ 5.2.7.3. dont_wait - Return Number of Objects Waiting for External Events ═══ Class: sched int dont_wait(); dont_wait() returns the number of times that keep_waiting() has been called, minus the number of times that dont_wait() has been called (excluding the current call). The return value should equal the number of objects that were waiting for external events before the current call. ═══ 5.2.7.4. exit_fct - User Defined Exit Function ═══ Class: sched typedef void (*PFV) (); static PFV exit_fct; exit_fct is a pointer to a user-defined exit function that has the following format: void e_function(); If exit_fct is set to point to such a function, the task system scheduler will call it before the program exits. To assign the address of a function to exit_fct, use an expression similar to the following: exit_fct = e_function; where e_function is a user-defined exit function with a return type of void and no arguments. ═══ 5.2.7.5. get_clock - Return Value of the Task System Clock ═══ Class: sched static long get_clock(); get_clock() returns the value of the task system clock. ═══ 5.2.7.6. get_exit_status - Return Exit Status of Task Program ═══ Class: sched static int get_exit_status(); get_exit_status() returns the exit status of the task program. When a task program terminates normally (task_error() is not called), the program will call exit() with the argument i, where i is the value of the argument in the last call of set_exit_status(). ═══ 5.2.7.7. get_priority_sched - Return Pointer to interrupt_alerter ═══ Class: sched sched* get_priority_sched(); get_priority_sched() returns a pointer to the system task interrupt_alerter if the following two conditions are true: o A signal occurred that an Interrupt_handler object was waiting for. o The Interrupt_handler object has not been scheduled yet. get_priority_sched() returns 0 otherwise. ═══ 5.2.7.8. get_run_chain - Return Pointer to Run Chain ═══ Class: sched #define run_chain (sched::get_run_chain()) private: static sched* runchain; public: static sched* get_run_chain(); get_run_chain() returns a pointer to the static sched member runchain. runchain is a linked list of task and timer objects that are ready to run. The macro definition run_chain is obsolete, but it is included for compatibility with the AT&T** C++ Language System Release 1.2. ═══ 5.2.7.9. keep_waiting - Keep Scheduler Waiting ═══ Class: sched int keep_waiting(); keep_waiting() returns the number of times keep_waiting() has been called (not counting the current call) minus the number of times that dont_wait() has been called. keep_waiting() is meant to be called when an object that will wait for an external event is created. For example, the Interrupt_handler constructor calls keep_waiting() when it creates an Interrupt_handler object. dont_wait() should be called when such an object is deleted. keep_waiting() prevents the scheduler from exiting when there are no tasks that can run. In such a situation, an external event could change the state of a task from IDLE, and then the scheduler would have to act. ═══ 5.2.7.10. pending - Return State ═══ Class: sched int pending(); pending() returns 0 if the state of schd equals TERMINATED. Otherwise, pending() returns a nonzero value. ═══ 5.2.7.11. print - Print the Contents of sched Object ═══ Class: sched void print(int x, int y=0); print() prints information about schd on standard output. For more details on print(), see the description of task::print() in print - Print Task Information. ═══ 5.2.7.12. rdstate - Return the State of sched Object ═══ Class: sched statetype rdstate(); rdstate() returns the state of schd. The state can be RUNNING, IDLE, or TERMINATED. ═══ 5.2.7.13. rdtime - Return Clock Time ═══ Class: sched long rdtime(); rdtime() returns the clock time at which schd is supposed to run. If the state of the task for which rdtime() is called is either TERMINATED or IDLE, the value returned by rdtime() is undefined. If rdtime() is called for a timer task, rdtime() returns the time at which the timer task will terminate. rdtime() is meant to be used in conjunction with the function task::delay() to determine when a task will stop delaying. ═══ 5.2.7.14. result - Return Result of sched Object ═══ Class: sched int result(); result() returns the result of schd. If the state of schd is not TERMINATED, the calling task will be suspended to wait for schd to terminate. A task that calls result() for itself will cause an E_RESULT runtime error. ═══ 5.2.7.15. setclock - Initialize the System Clock ═══ Class: sched static void setclock(long init_time); setclock() is a static function that initializes the system clock to the time init_time. You will get an E_SETCLOCK runtime error if you call setclock() more than once in a program. ═══ 5.2.7.16. setwho - Record Alerting Object ═══ Class: sched virtual void setwho(object* alt_obj); setwho() is a virtual function that is defined for task and timer objects. alt_obj is meant to be a pointer to the object that caused schd to be alerted. ═══ 5.2.7.17. set_exit_status - Set Exit Status of Task ═══ Class: sched static void set_exit_status(int i); set_exit_status() sets the exit status of the task program. When a task program terminates normally (task_error() is not called), the program calls exit() with the argument i. ═══ 5.2.8. Members of task ═══ Note: The following descriptions assume that the functions are called as part of a task object called tsk. The following functions are described: o Constructor for task o cancel - change state to TERMINATED o delay - suspend task o get_task_chain - return first task in list o _hwm - high water mark variable o o_type - return class object type o preempt - make running task idle o print - print task information o resultis - set return value o setwho - record alerting object o sleep - suspend task unconditionally o wait - suspend task o waitlist - suspend task, wait for list of objects o waitvec - suspend task, wait for vector of objects o who_alerted_me - return object that put task back on run chain ═══ 5.2.8.1. Constructor for task ═══ Class: task task(char* name = 0, modetype mode = DEFAULT_MODE, int stacksize = SIZE); The task constructor is declared protected. You cannot call the task constructor to create a task object directly, but you can use the task constructor to create objects of the classes that you derive from task. The first argument of the task constructor specifies the name of the task. The default value for name is 0. mode specifies whether the task is SHARED or DEDICATED. The default value for mode is DEFAULT_MODE. stacksize specifies the size of the stack for the task. The default value for stacksize is SIZE. The default values DEFAULT_MODE and SIZE are defined in task.h. Notes 1. At the end of every constructor of a task object, including the main() function in any program that uses the task library, a call to resultis() should appear, unless you want the constructor to execute infinitely. 2. The results of ending a task abnormally using the standard C library function exit() are undefined. Unpredictable results will occur. ═══ 5.2.8.2. cancel - Change State to TERMINATED ═══ Class: task void cancel(int ret_val); cancel() changes the state of tsk to TERMINATED and sets the return value of tsk to ret_val. cancel() does not invoke the scheduler. ═══ 5.2.8.3. delay - Suspend Task ═══ Class: task void delay(long interval); delay() suspends tsk for the time specified by interval. A task that calls delay() has a state of RUNNING, and the call to delay() does not change the state of the task. If the current time on the task system clock is t{0}, tsk resumes at time t{0} + interval. A call to delay() causes the clock to advance. delay() is usually called by a task on itself. If such a task has a state of IDLE, a call to delay() results in an E_CLOCKIDLE runtime error. ═══ 5.2.8.4. get_task_chain - Return First Task in List ═══ Class: task static task* get_task_chain(); #define task_chain (task::get_task_chain()) get_task_chain() returns a pointer to the first task object in the list of task objects. Each task object is linked together by the member t_next. The macro task_chain() is included for compatibility with the AT&T** C++ Language System Release 1.2. ═══ 5.2.8.5. _hwm - High Water Mark Variable ═══ Class: task extern _hwm; The external variable _hwm is the high water mark variable for the stack associated with a task. If it is initially set to a nonzero value, _hwm causes the task system to record the maximum size of the stack. _hwm also affects what is printed by task::print() with an argument of STACK. If _hwm is initially set to a nonzero value, a call to task::print() with an argument of STACK will print out high water mark information. This information is meant for debugging. Note that gathering this information could reduce the performance of your application, and thus you should only give _hwm an initial nonzero value when you are debugging. You can set _hwm in the main() function, but if you want the value of _hwm to be nonzero for the main() task and the interrupt_alerter task you must set the value of _hwm in the constructor of a static object. The following example shows how you might set the value of _hwm to accomplish this: extern _hwm; class hwm_init { public: hwm_init() { _hwm=1 }; }; static hwm_init hwmi; // ... #include Note: The interrupt_alerter task runs before the main() task. Thus, if you set the value of _hwm in the main() function, no high water mark information will be recorded for either the main() task or the interrupt_alerter task. ═══ 5.2.8.6. o_type - Return Class Object Type ═══ Class: task object::objtype o_type(); o_type() returns the class object type (object::objtype) of tsk, namely object::TASK. ═══ 5.2.8.7. preempt - Make Running Task Idle ═══ Class: task long preempt(); preempt() changes the state of tsk from RUNNING to IDLE. preempt() returns the number of time units left in the delay for tsk. preempt() produces an E_TASKPRE runtime error if tsk has state equal to IDLE or TERMINATED. ═══ 5.2.8.8. print - Print Task Information ═══ Class: task void print(int x, int y =0); print() prints information about tsk on standard output. The argument x specifies the amount of information to be printed. The argument y is used internally by the Task Library. Its default value is 0. If x equals 0, the following information is printed: o The type of the object, namely task o The task state (RUNNING, IDLE, or TERMINATED) o The value of the this pointer If x equals CHAIN, the information listed above is printed, along with the same information for every task in the chain attached to tsk. If x equals VERBOSE, the information that is printed when x equals 0 is printed, along with the following information: o The mode of the task (DEDICATED or SHARED) o t_alert, a pointer to the object that alerted tsk o t_next, a pointer to the next task object in the chain o The value returned by result() for this task o The value of the this pointer for the sched and object objects associated with this task o The list of tasks on the remember chain for this task If x equals STACK and the state of tsk is either RUNNING or IDLE, all of the information that is printed when x equals 0 is printed in addition to the information listed below: o The maximum size of the stack for this task o The current size of the stack o The size of _hwm (if _hwm is initially set to a nonzero value) o t_basep, the address of the base of the stack when the state of the task is RUNNING o t_framep, the frame pointer for the task when its state is IDLE o The current address of the top of the stack o The maximum address for the top of the stack If x equals STACK and the state of tsk is TERMINATED, all of the information that is printed when x equals 0 is printed in addition to the information listed below: o The status of the stack, namely deleted o The size and address of _hwm (if _hwm is initially set to a nonzero value) ═══ 5.2.8.9. resultis - Set Return Value ═══ Class: task void resultis(int res); resultis() sets the return value of tsk to res and sets the state of tsk to TERMINATED. The result() member function of the class sched returns the value of this result. An object of a class derived from task object cannot return a value using the usual function return mechanism. A call to resultis() should appear at the end of every constructor for every class that is derived from task. ═══ 5.2.8.10. setwho - Record Alerting Object ═══ Class: task void setwho(object* alt_obj); setwho() is a virtual function that is defined for task and timer objects. alt_obj is a pointer to the object that caused the scheduler to be alerted. setwho() records the object pointed to by alt_obj as the one that caused the state of tsk to change from IDLE to RUNNING. alt_obj points to an object that had a change of state from pending to ready that caused tsk to be put back in the run chain. who_alerted_me() returns this pointer. ═══ 5.2.8.11. sleep - Suspend Task Unconditionally ═══ Class: task void sleep(object* ob=0); sleep() changes the state of tsk to IDLE. If ob points to a pending object, tsk will be put back on the run chain when the state of ob changes to ready. If ob points to a ready object, or if no argument is supplied, tsk will never be put back on the run chain; the event that would cause tsk to be resumed is unspecified. In this case, tsk can only be eliminated by a call to cancel(). Only objects of the predefined classes automatically alert the tasks that are waiting for them. Objects of classes that you define must explicitly call object::alert() when their state changes from pending to ready. See Object States for a general description of the object states. ═══ 5.2.8.12. wait - Suspend Task ═══ Class: task void wait(object* ob); If the state of the object pointed to by ob is pending, wait() changes the state of tsk to IDLE until the object is ready. If the state of the object pointed to by ob is ready, the state of tsk remains unchanged. If wait() is called with an argument equal to 0, tsk will never be put back on the run chain, and tsk can only be eliminated by a call to cancel(). If the argument of wait() is a pointer to tsk, wait() produces an E_WAIT runtime error. Unlike sleep(), wait() checks the state of its argument before it changes the state of tsk. Suppose obr is a pointer to a ready object. tsk.wait(obr) does not change the state of tsk, but tsk.sleep(obr) does change the state of tsk. Note: A task should only call wait() on itself. ═══ 5.2.8.13. waitlist - Suspend Task, Wait for List of Objects ═══ Class: task int waitlist(object* ob1...); waitlist() takes as arguments a list of pointers to objects. The last element in this list must be equal to 0. The result of waitlist() depends on the state of the objects pointed to by the arguments: o If all of the arguments point to objects that have a state of pending, waitlist() changes the state of tsk to IDLE. As soon as the state of one of the objects pointed to by the arguments becomes ready, the state of tsk is changed back to RUNNING and waitlist() returns the position of this argument in the list. For example, if the object pointed to by the third argument is the first one to become ready, waitlist() has a return value of 2 (because the first argument is at position 0). o If any argument obi ( i = 1 . . . n) in the list of arguments is ready (that is, the function obi->pending() returns 0), the state of tsk is not changed and waitlist() returns the position of obi in the argument list. Other arguments in the list may also point to objects that are ready, but waitlist() only returns the position of the first one. ═══ 5.2.8.14. waitvec - Suspend Task, Wait for Vector of Objects ═══ Class: task int waitvec(object** objvec); waitvec() is the same as waitlist() except that its argument objvec is a pointer to a vector that holds a list of object pointers. The last pointer in this vector must be equal to 0. ═══ 5.2.8.15. who_alerted_me - Return Object that Put Task Back on Run Chain ═══ Class: task object* who_alerted_me(); who_alerted_me() returns a pointer to the object whose state change from pending to ready caused tsk to change state from IDLE to RUNNING. ═══ 5.2.9. Public Members of timer ═══ Note: The following descriptions assume that the functions are called as part of a timer object called tm. The following functions are defined: o Constructor for timer o o_type - return class object type o print - print contents of timer object o reset - reset the delay of the timer object o setwho - record alerting object An example of using the timer class is also provided. ═══ 5.2.9.1. Constructor for timer ═══ Class: timer timer(long wait_time); timer() constructs a timer object and inserts it on the scheduler's run chain. wait_time is the number of time units that tm, the newly created timer object, runs. timer objects are inserted into the run chain based on the value of wait_time when they were created. The scheduler resets the current time to the wait_time of the task object at the front of the run chain. ═══ 5.2.9.2. o_type - Return Class Object Type ═══ Class: timer object::objtype o_type(); o_type() returns the class object type (object::objtype) of tm, namely object::TIMER. ═══ 5.2.9.3. print - Print Contents of timer Object ═══ Class: timer void print(int x, int y); print() prints information about tm. The argument x specifies the amount of information to be printed. The argument y is used internally by the Task Library. Its default value is 0. If x equals 0, print() displays the following information on standard output: o The type of the object, namely timer o The amount of time that tm has to wait o The offset from the current setting of the task system clock If x equals VERBOSE, print() displays the information listed above, along with the following information: o The value of the this pointer in the sched object o The value of the this pointer in the object o The list of remembered task objects ═══ 5.2.9.4. reset - Reset the Delay of the timer Object ═══ Class: timer void reset(long wait_time); reset() resets the time units that tm has to wait to wait_time. A timer object can be reset even if its state equals TERMINATED. ═══ 5.2.9.5. setwho - Record Alerting Object ═══ Class: timer void setwho(object* alt_obj); In the timer object, setwho() is defined to do nothing. ═══ 5.2.9.6. Example of Using the timer Class ═══ Class: timer The following example shows the different ways that you can use the timer class and advance the clock: #include #include class ct : public task { int cnt ; public: ct(); }; ct::ct():cnt(0) { while(++cnt) {sleep(); } } void main() { timer *t; object *ov[2]; // ct ct1; sched::clock_task = &ct1; // // Advance the task system clock 50 times // by 50 time units each time. Use various // different ways for clock advancement. // for (register i=0; i<10; ++i) { thistask->delay(50); } for (i=0; i<10; ++i) { t= new timer (50); thistask->wait(t); } t->print(0); for (i=0; i<10; ++i) { t= new timer (50); thistask->sleep(t); } t->print(0); for (i=0; i<10; ++i) { t= new timer (50); thistask->waitlist(t,0); } t->print(VERBOSE); for (i=0; i<10; ++i) { t= new timer (50); ov[0]=t; ov[1]=0; thistask->waitvec(ov); } t->print(0); thistask->resultis(0); } This program produces output similar to the following: timer 1000 == clock+0 timer 1500 == clock+0 timer 1500 == clock+0 timer 2000 == clock+0 sched: this=b1190 object: this=b1190 No tasks remembered timer 2500 == clock+0 ═══ 5.3. Queue Management Classes ═══ This chapter describes the queue management classes qhead and qtail. You can use these classes to implement a wide range of message-passing and data-buffering schemes. Both classes are derived from the class object. The following topics are described in this chapter: o What is a queue? o Queue attributes o Cutting and splicing queues o Restrictions on putting objects in queues o Declarations for the Queue Management Classes in task.h o Public members of qhead o Public members of qtail ═══ 5.3.1. What Is a Queue? ═══ A queue is a data structure with an associated list of objects that are extracted from the queue in first-in, first-out order. No public functions deal with queues directly; you manage a queue using the qhead and qtail objects that are associated with each queue. You create a queue by creating either a qhead object or a qtail object. If you create a qhead object, you can obtain the qtail object that is associated with that qhead object by calling qhead::tail(). Similarly, if you create a qtail object, you can obtain the qhead object that is associated with that qtail object by calling qtail::head(). Once a queue is established, you use qtail::put() to add objects to it and qhead::get() to remove objects from it. Because both qhead and qtail are derived from the class object, they both have definitions for when they are ready and when they are pending. qhead objects are ready when the queue is not empty and pending when the queue is empty. qtail objects are ready when the queue is not full and pending when the queue is full. ═══ 5.3.2. Queue Attributes ═══ Queues have three attributes that control the operation of the queue: o mode: controls what happens when a qhead or qtail object is pending. The mode attribute can have different settings for the qhead and qtail objects that make up a queue. o maximum size: controls the maximum number of objects that can be in the queue. o count: records the number of objects that are in the queue. ═══ 5.3.2.1. Mode Attribute ═══ The mode controls what happens when a qhead or qtail object is pending. The qhead and qtail objects that are attached to the same queue do not necessarily have the same mode. The mode can have the following values: o WMODE (wait mode): a task that calls qhead::get() on an empty queue is suspended until the queue is no longer empty. A task that calls qtail::put() on a full queue is suspended until the queue is no longer full. o EMODE (error mode): calling qhead::get() for an empty queue or qtail::put() for a full queue causes a runtime error. o ZMODE (zero mode): a call to qtail::put() for a full queue or a call to qhead::get() for an empty queue returns 0. Otherwise, qtail::put() and qhead::get() return 1. ═══ 5.3.2.2. Maximum Size Attribute ═══ The maximum size is set to 10 000 by default. A queue can hold up to 10 000 pointers to objects, but it does not preallocate space. You can use either qhead::setmax() or qtail::setmax() to reset the maximum queue size. You can use use either qhead::rdmax() or qtail::rdmax() to get the current setting of the maximum size attribute. ═══ 5.3.2.3. Count Attribute ═══ The count is the number of objects in the queue. You can use qhead::rdcount() to get the current value of the count attribute. ═══ 5.3.3. Cutting and Splicing Queues ═══ You can split a queue into two pieces using the member functions qhead::cut() and qtail::cut(). See cut - Split Queue for more details on qhead::cut(). You can join these two pieces together again into a single queue using the member functions qhead::splice() and qtail::splice(). You can use cutting and splicing to insert a filter into a data stream. A filter is a task that takes input from one queue, performs some kind of transformation on it, and puts the transformed data on another queue. If you want to insert a filter into an existing queue, you can use cut() to split the queue in two pieces. Then the filter can get input from the head of one queue and put output to the tail of the other queue. When the filter has finished its processing, you can use splice() to make the two pieces into a single queue again. Note: Because you do not deal directly with queues, but rather with qhead and qtail objects, you never use the name of a queue in your code. In this chapter, queues are given names so that they can be discussed conveniently. These names would not appear in any actual code. A queue called oldqueue is attached to the qtail object qt. oldqueue is split, and qt is now attached to a new queue called newqueue. Finally, oldqueue and newqueue are reunited with a call to qtail::splice(). The operations illustrated in Cutting and Splicing a qtail Object could be accomplished by code that looks like this: qtail *qt = new qtail; qhead *qh = qt->head(); qtail *qtp = qt->cut(); qhead *qhp = qt->head(); qtp->splice(qhp); The following figure illustrates what happens to a qtail object when it is cut and spliced. before qt->cut(); ┌──────────┐ qh │ │ qt ┌─────────┤ ├─────────┐ └─────────┤ oldqueue ├─────────┘ │ │ └──────────┘ after qt->cut(); ┌──────────┐ ┌──────────┐ qh │ │ qtp qhp │ │ qt ┌────────┤ ├────────┐ ┌────────┤ ├──────────┐ └────────┤ oldqueue ├────────┘ └────────┤ newqueue ├──────────┘ │ │ │ │ └──────────┘ └──────────┘ after qtp->splice(qhp); ┌──────────┐ qh │ │ qt ┌─────────┤ ├─────────┐ └─────────┤ oldqueue ├─────────┘ │ │ └──────────┘ Cutting and Splicing a qtail Object Cutting and Splicing a qhead Object illustrates what happens to a qhead object when it is cut and spliced. A queue called oldqueue is attached to the qhead object qh. oldqueue is split, and qh is now attached to a new queue called newqueue. Finally, oldqueue and newqueue are reunited with a call to qhead::splice(). The operations illustrated in Cutting and Splicing a qhead Object could be accomplished by code that looks like this: qhead *qh = new qhead; qtail *qt = qh->tail(); qhead *qhp = qh->cut(); qtail *qtp = qh->tail(); qhp->splice(qtp); before qh->cut(); ┌──────────┐ qh │ │ qt ┌─────────┤ ├─────────┐ └─────────┤ oldqueue ├─────────┘ │ │ └──────────┘ after qh->cut(); ┌──────────┐ ┌──────────┐ qh │ │ qtp qhp │ │ qt ┌────────┤ ├────────┐ ┌────────┤ ├──────────┐ └────────┤ newqueue ├────────┘ └────────┤ oldqueue ├──────────┘ │ │ │ │ └──────────┘ └──────────┘ after qhp->splice(qtp); ┌──────────┐ qh │ │ qt ┌─────────┤ ├─────────┐ └─────────┤ oldqueue ├─────────┘ │ │ └──────────┘ Cutting and Splicing a qhead Object ═══ 5.3.3.1. Example of Cutting and Splicing a Queue ═══ The following example shows how you can use cutting and splicing to insert a filter into a data stream. This example includes the following classes: o Producer: creates a series of random numbers and puts them into the tail of a queue. o Consumer: gets numbers from the head of a queue and prints them. o Filter: gets numbers from the head of a queue, sorts them, and puts them into the tail of a queue. In the main() function of this example, the following operations are performed: o The Producer object p1 and the Consumer object c1 are created with the same queue (called oldqueue in this discussion). Thus, c1 prints the numbers produced by p1. o oldqueue is cut to produce a new queue (called newqueue in this discussion). Producer object p2 is created with oldqueue as its argument, and Consumer object c2 is created with newqueue as its argument. In between p2 and c2, Filter object f is created with oldqueue and newqueue as arguments. Thus f takes the numbers produced by p2, sorts them, and sends them to c2 to be printed. o oldqueue and newqueue are spliced together to produce a restored oldqueue. Producer object p3 and Consumer object c3 are created with the same queue, oldqueue. Thus, c3 prints the numbers produced by p3. The output produced by this example includes an unsorted list of numbers, followed by a sorted list of numbers, followed by an unsorted list of numbers. Note: You must set the language level to "compat" in order to compile this program successfully. You can use the /Sc switch to do this. #include #include #include const int NumberOfIterations = 10; class Message : public object { private: int value; public: Message(int v) : value(v) {} int getValue() { return value; } }; class Producer : public task { public: Producer(qtail *qt); }; class Consumer : public task { public: Consumer(qhead *qh); }; class Filter : public task { static int Comparison(const void *, const void *); public: Filter(qhead *qhp, qtail *qtp); void sortArray(int *arr); }; Producer::Producer(qtail *qt) { urand u(1,100); for (int lcv=0; lcv < NumberOfIterations; lcv++) qt->put(new Message(u.draw())); resultis(0); } Consumer::Consumer(qhead *qh) { for (int lcv=0; lcv < NumberOfIterations; lcv++) { Message *mess = (Message *)qh->get(); cout << "Consumer got " << mess->getValue() << endl; delete mess; } resultis(0); } Filter::Filter(qhead *qhp, qtail *qtp) { int arr[NumberOfIterations]; for (int lcv=0; lcv < NumberOfIterations; lcv++) { Message *mess = (Message *)qhp->get(); arr[lcv] = mess->getValue(); delete mess; } sortArray(arr); for (lcv=0; lcv < NumberOfIterations; lcv++) qtp->put(new Message(arr[lcv])); resultis(0); } int Filter::Comparison(const void *e1, const void *e2) { if (*(int *)e1 < *(int *)e2) return -1; if (*(int *)e1 == *(int *)e2) return 0; return 1; } void Filter::sortArray(int *arr) { qsort(arr, NumberOfIterations, sizeof(int), &Filter::Comparison); } void main() { qhead *qh = new qhead; qtail *qt = qh->tail(); Producer p1(qt); Consumer c1(qh); cout << "Now insert a filter that will sort the numbers: " << endl; qhead *qhp = qh->cut(); qtail *qtp = qh->tail(); Producer p2(qt); Filter f(qhp,qtp); Consumer c2(qh); cout << "Now remove the filter: " << endl; qhp->splice(qtp); Producer p3(qt); Consumer c3(qh); cout << "All done" << endl; thistask->resultis(0); } This program produces output that looks like this: Consumer got 1 Consumer got 66 Consumer got 31 Consumer got 68 Consumer got 11 Consumer got 52 Consumer got 49 Consumer got 61 Consumer got 37 Consumer got 26 Now insert a filter that will sort the numbers: Consumer got 1 Consumer got 11 Consumer got 26 Consumer got 31 Consumer got 37 Consumer got 49 Consumer got 52 Consumer got 61 Consumer got 66 Consumer got 68 Now remove the filter: Consumer got 1 Consumer got 66 Consumer got 31 Consumer got 68 Consumer got 11 Consumer got 52 Consumer got 49 Consumer got 61 Consumer got 37 Consumer got 26 All done ═══ 5.3.4. Restrictions on Putting Objects in Queues ═══ An object should not be in more than one queue at the same time. An object can end up in two queues in a subtle fashion. For example, the constructor for the timer class places the object that it constructs on the run chain, a queue of task objects that have a state equal to RUNNING. In the following example, a timer object t1 is created and automatically put on the run chain queue. t1 is then placed on another queue, q1. Placing t1 on a second queue causes the program to be suspended: #include class MyTask : public task { public: MyTask(); }; MyTask::MyTask() { qtail q1; timer *t1 = new timer(60); // t1 is put on the run // chain queue by the timer // constructor // q1.put(t1); // t1 is now on 2 queues and // the program will hang resultis(0); } void main(){ MyTask mt; thistask->resultis(0); } ═══ 5.3.5. Declarations for the Queue Management Classes in task.h ═══ You must include the following statement in any file that uses members of qhead or qtail classes: #include The following excerpt from the task.h header file shows member function declarations for the queue management classes: enum qmodetype { EMODE, WMODE, ZMODE }; class qhead : public object { friend class qtail; public: qhead(qmodetype = WMODE, int = 10000); ~qhead(); object::objtype o_type(); object* get(); int putback(object*); int rdcount(); int rdmax(); qmodetype rdmode(); qtail* tail(); qhead* cut(); void splice(qtail*); void setmode(qmodetype m); void setmax(int m); int pending(); void print(int, int =0); }; class qtail : public object { friend class qhead; public: qtail(qmodetype = WMODE, int = 10000); ~qtail(); object::objtype o_type(); int put(object*); int rdspace(); int rdmax(); qmodetype rdmode(); qtail* cut(); void splice(qhead*); qhead* head(); void setmode(qmodetype m); void setmax(int m); int pending(); void print(int, int =0); }; ═══ 5.3.6. Public Members of qhead ═══ Note: The following descriptions assume that the functions are called as part of a qhead object called qh, unless otherwise noted. The following functions are described: o Constructor for qhead o cut - split queue o get - extract object from queue o o_type - return class type o pending - is queue empty? o print - print queue contents o putback - put objects back in queue o rdcount - return number of objects in queue o rdmax - return maximum queue size o rdmode - return mode o setmode - set mode o setmax - set maximum queue size o splice - merge queues o tail - create qtail object ═══ 5.3.6.1. Constructor for qhead ═══ Class: qhead qhead(qmodetype qm= WMODE, int size=10000); The qhead() constructor takes two optional arguments. The qmodetype, qm, can have a value of WMODE, EMODE, or ZMODE. WMODE is the default. The argument size, the maximum number of objects that can be placed in the queue, has a default value of 10 000. ═══ 5.3.6.2. cut - Split Queue ═══ Class: qhead qhead* cut(); cut() splits the queue attached to qh and returns a pointer to a new qhead object. In this description, this new qhead object is called qhp. qhp is attached to the original queue. qh now points to a new, empty queue. You must establish a new qtail for qh. If you want to get objects from the original queue, you must call qhp.get(). You can use the member function splice() to restore a split queue to its original configuration. Cutting and Splicing a qhead Object illustrates the cutting and splicing of a qhead object. ═══ 5.3.6.3. get - Extract Object from Queue ═══ Class: qhead object* get(); If the queue is not empty, get() returns a pointer to the object at the head of the queue. If the queue is empty, the result depends on the mode: o WMODE: the task that executes get() is suspended until the queue is no longer empty. o EMODE: the E_GETEMPTY runtime error is produced. o ZMODE: get() returns 0. ═══ 5.3.6.4. o_type - Return Class Type ═══ Class: qhead object::objtype o_type(); o_type() returns the class type of qh, namely object::QHEAD. ═══ 5.3.6.5. pending - Is Queue Empty? ═══ Class: qhead int pending(); pending() returns a nonzero value if the queue is empty and returns zero otherwise. ═══ 5.3.6.6. print - Print Queue Contents ═══ Class: qhead void print(int detail, int y=0); print() prints information about the queue attached to qh on stdout. It calls the print() member function of the object base class. Argument detail specifies the amount of information to be printed. Argument y is used internally by the Task Library and defaults to 0. If detail equals 0, the following information is printed: o The type of object, namely qhead o The integer value of the mode of the queue o The maximum size of the queue o The value of the count attribute for the queue o The value of the qtail pointer If detail equals VERBOSE, the information listed above is printed along with information about the qtail object that is attached to the queue and information about all of the tasks that are waiting for qh. The following values for the qtail object are printed: o The type of object, namely qtail o The integer value of the mode of the queue o The maximum size of the queue o The number of objects that the queue still has room for o The value of the qhead pointer For each task that is waiting for qh, the following information is printed: o The value of the t_alert pointer, a private pointer to the object that alerted the task o The value of the t_next pointer, a pointer to the next task on the chain o The value of the s_time pointer, a private pointer to the time at which the task is scheduled to run o The value of the this pointer for the sched and object this task is derived from ═══ 5.3.6.7. putback - Put Objects Back in Queue ═══ Class: qhead int putback(object* objptr); putback() puts the object pointed to by objptr back on the head of the queue attached to qh, allowing qh to operate as a stack. A task that calls putback() competes for queue space with tasks that call qtail::put(). If the call to putback() succeeds, putback() returns 1. If the queue is full, a runtime error occurs if mode equals EMODE or WMODE. 0 is returned if mode equals ZMODE. ═══ 5.3.6.8. rdcount - Return Number of Objects in Queue ═══ Class: qhead int rdcount(); rdcount() returns the number of objects in the queue attached to qh. ═══ 5.3.6.9. rdmax - Return Maximum Queue Size ═══ Class: qhead int rdmax(); rdmax() returns the maximum size of the queue attached to qh. ═══ 5.3.6.10. rdmode - Return Mode ═══ Class: qhead qmodetype rdmode(); rdmode() returns the mode of qh. ═══ 5.3.6.11. setmode - Set Mode ═══ Class: qhead void setmode(qmodetype qm); setmode() resets the mode of qh to qm. ═══ 5.3.6.12. setmax - Set Maximum Queue Size ═══ Class: qhead void setmax(int newmax); setmax() sets the maximum size of the queue attached to qh to newmax. You can set the maximum size to be less than the current size of the queue. If you do, you cannot put objects in the queue until the number of objects in the queue is less than the new maximum size. If newmax is less than or equal to 0, the E_QZERO runtime error is produced. ═══ 5.3.6.13. splice - Merge Queues ═══ Class: qhead void splice(qtail* qt); splice() reconnects two queues that were split by a call to cut(). qhp->splice(qtp) merges the queue attached to the qhead pointer qhp with the queue attached to the qtail pointer qtp, where: o A call qh.cut() was made that returned the qhead pointer qhp. After this call, qh is attached to a new queue and qhp is attached to the original queue. o After the call to cut(), a call qh.tail() was made that returned the qtail pointer qtp. In the new queue, the objects that were in the queue attached to qtp precede the objects that were in the queue attached to qhp. splice() deletes both qhp and qtp. If the call to splice() makes an empty queue no longer empty or makes a full queue no longer full, it will alert all of the tasks that are waiting for either of these state changes and add these tasks to the scheduler's run chain. Cutting and Splicing a qhead Object illustrates the cutting and splicing of a qhead object. ═══ 5.3.6.14. tail - Create qtail Object ═══ Class: qtail qtail* tail(); tail() creates a qtail object for the queue attached to qh (if none exists) and returns a pointer to the new qtail object. If a qtail object already exists for the queue attached to qh, tail() returns a pointer to that qtail object. ═══ 5.3.7. Public Members of qtail ═══ Note: The following descriptions assume that the functions are called as part of a qtail object called qt. The following functions are described: o Constructor for qtail o cut - split queue o head - create qhead object o o_type - return class type o pending - is queue full? o print - print queue contents o put - add object to queue o rdspace - space remaining o rdmax - return maximum queue size o rdmode - return mode o setmode - set mode o setmax - set maximum queue size o splice - merge queues ═══ 5.3.7.1. Constructor for qtail ═══ Class: qtail qtail(qmodetype qm = WMODE, int size=10000); The qtail() constructor takes two optional arguments. The qmodetype, qm, can have a value of WMODE, EMODE, or ZMODE. WMODE is the default. The argument size, the maximum number of objects that can be placed in the queue, has a default value of 10 000. ═══ 5.3.7.2. cut - Split Queue ═══ Class: qtail qtail* cut(); cut() splits the queue attached to qt and returns a pointer to a new qtail object, qtp. qtp is attached to the original queue. qt now points to a new, empty queue. You must establish a new qhead for qt. If you want to put objects into the original queue, you must call qtp.put(). You can use the member function splice() to restore a split queue to its original configuration. Cutting and Splicing a qtail Object illustrates the cutting and splicing of a qtail object. ═══ 5.3.7.3. head - Create qhead Object ═══ Class: qtail qhead* head(); head() creates a qhead object for the queue attached to qt (if none exists) and returns a pointer to the new qhead object. If a qhead object already exists for the queue attached to qt, head() returns a pointer to that qhead object. ═══ 5.3.7.4. o_type - Return Class Type ═══ Class: qtail object::objtype o_type(); o_type() returns the class type of qt, namely object::QTAIL. ═══ 5.3.7.5. pending - Is Queue Full? ═══ Class: qtail int pending(); pending() returns a nonzero value if the queue attached to qt is full and 0 otherwise. ═══ 5.3.7.6. print - Print Queue Contents ═══ Class: qtail void print(int detail, int y=0); print() prints information about the queue attached to qt on stdout. It calls the print() member function of the object base class. detail specifies the amount of information to be printed. The second argument, y, is used internally by the Task Library and has a default value of 0. If detail equals 0, the following information is printed: o The type of object, namely qtail o The integer value of the mode of the queue o The maximum size of the queue o The number of objects that the queue still has room for o The value of the qhead pointer If detail equals VERBOSE, the information listed above is printed along with information about the qhead object that is attached to the queue and information about all of the tasks that are waiting for qt. The following values for the qhead object are printed: o The type of object, namely qhead o The integer value of the mode of the queue o The maximum size of the queue o The number of elements in the queue o The value of the qtail pointer For each task that is waiting for qt, the following information is printed: o The value of the t_alert pointer, a private pointer to the object that alerted the task o The value of the t_next pointer, a pointer to the next task on the chain o The value of the s_time pointer, a private pointer to the time at which the task is scheduled to run o The value of the this pointer for the sched and object this task is derived from ═══ 5.3.7.7. put - Add Object to Queue ═══ Class: qtail int put(object* obj); put() adds the object obj to the tail of the queue that is attached to qt. put() returns 1 if it succeeds. If the queue is full, the result depends on the mode: o WMODE: the task that executes put() is suspended until the queue is no longer full o EMODE: the E_PUTFAIL runtime error is produced o ZMODE: put() returns 0 ═══ 5.3.7.8. rdspace - Space Remaining ═══ Class: qtail int rdspace(); rdspace() returns the number of objects that can be inserted into the queue attached to qt before it becomes full. The number of objects in a queue can be greater than the value specified by the maximum size of the queue if one of the two following conditions is true: o You call splice() to reunite two pieces of a queue that together contain more objects than the value specified by the maximum size for the queue. o You call setmax() with an argument that is less than the number of objects currently in the queue. If the number of objects in the queue is greater than the value specified by the maximum size of the queue, rdspace() returns a negative value. The absolute value of this value equals the number of objects that are in the queue over and above the maximum size of the queue. ═══ 5.3.7.9. rdmax - Return Maximum Queue Size ═══ Class: qtail int rdmax(); rdmax() returns the maximum size of the queue attached to qt. ═══ 5.3.7.10. rdmode - Return Mode ═══ Class: qtail qmodetype rdmode(); rdmode() returns the mode of qt. ═══ 5.3.7.11. setmode - Set Mode ═══ Class: qtail void setmode(qmodetype qm); setmode() sets the mode of qt to qm. ═══ 5.3.7.12. setmax - Set Maximum Queue Size ═══ Class: qtail void setmax(int newmax); setmax() sets the maximum size of the queue attached to qt to newmax. You can set the maximum size to be less than the current size of the queue. If you do, you cannot put objects on the queue until the number of objects in the queue is less than the new maximum size. If newmax is less than or equal to 0, the E_QZERO runtime error is produced. ═══ 5.3.7.13. splice - Merge Queues ═══ Class: qtail void splice(qhead* qh); splice() reconnects two queues that were split by a call to cut(). qtp->splice(qhp) merges the queue attached to the qtail pointer qtp with the queue attached to the qhead pointer qhp, where: o A call qt.cut() was made that returned the qtail pointer qtp. After this call, qt is attached to a new queue and qtp is attached to the original queue. o After the call to cut(), a call qt.head() was made that returned the qhead pointer qhp. In the new queue, the objects that were in the queue attached to qtp precede the objects that were in the queue attached to qhp. splice() deletes both qtp and qhp. If the call to splice() makes an empty queue no longer empty or makes a full queue no longer full, it will alert all of the tasks that are waiting for either of these state changes and add these tasks to the scheduler's run chain. Cutting and Splicing a qtail Object illustrates the cutting and splicing of a qtail object. ═══ 5.4. Interrupt_handler Class ═══ This chapter describes the Interrupt_handler class. This class allows tasks to wait for external events in the form of signals from the operating system. The header file task.h includes the declaration of a related class, Interrupt_alerter, but this class is not meant to be used directly. Interrupt_alerter is only documented here to show how it interacts with Interrupt_handler. The following topics are described in this chapter: o Declarations for Interrupt_handler in task.h o Public members of Interrupt_handler o Public members of Interrupt_alerter o Example of using Interrupt_handler ═══ 5.4.1. Declarations for Interrupt_handler in task.h ═══ You must include the following statement in any file that uses members of the Interrupt_handler class: #include The following is an excerpt from task.h that shows the relevant declarations for the members of Interrupt_handler: class Interrupt_handler : public object{ friend class Interrupt_alerter; friend SIG_FUNC_TYP sigFunc; int id; int got_interrupt; Interrupt_handler *old; virtual void interrupt(); public: Interrupt_handler(int sig_num); ~Interrupt_handler(); object::objtype o_type(); int pending(); void print(int, int =0); }; class Interrupt_alerter : public task { public: Interrupt_alerter(); ~Interrupt_alerter(); }; extern Interrupt_alerter interrupt_alerter; ═══ 5.4.2. Public Members of Interrupt_handler ═══ The following functions are described: o Constructor for Interrupt_handler o Destructor for Interrupt_handler o interrupt - what to do when an interrupt occurs o o_type - return class o pending - did a signal occur o print - print Interrupt_handler information ═══ 5.4.2.1. Constructor for Interrupt_handler ═══ Class: Interrupt_handler Interrupt_handler(int sig); The Interrupt_handler constructor constructs a new Interrupt_handler object that is meant to wait for the signal number sig. When the signal with this signal number occurs, the private virtual function interrupt() is called. If several tasks are waiting for one Interrupt_handler task, when the interrupt occurs and that Interrupt_handler is ready, only one of the waiting tasks will run, and only this task has its state changed to RUNNING. Subsequent interrupts will allow the other waiting tasks to run, one task per interrupt. When an interrupt occurs, the current task is suspended and a special, built-in task, interrupt_alerter, is scheduled. When interrupt() returns, control resumes at the point where the current task was interrupted. As long as an Interrupt_handler object exists, the scheduler will not exit when the run chain becomes empty. It will wait for an interrupt instead. This happens because the Interrupt_handler constructor calls sched::keep_waiting(). The Interrupt_handler destructor calls sched::dont_wait(). ═══ 5.4.2.2. Destructor for Interrupt_handler ═══ Class: Interrupt_handler ~Interrupt_handler(); The Interrupt_handler destructor calls sched::dont_wait() to decrement the count of waiting Interrupt_handler() objects. The destructor also restores the handler for the signal for which the Interrupt_handler object was created. If the destructor for an Interrupt_handler has been called previously, the E_LOSTHNDLR runtime error is produced. Otherwise, the destructor verifies that it did indeed set up the Interrupt_handler object, and exits. ═══ 5.4.2.3. interrupt - What to Do When an Interrupt Occurs ═══ Class: Interrupt_handler virtual void interrupt(); interrupt() is a virtual function that you can define in a class that is derived from Interrupt_handler to specify the action to be taken when an interrupt occurs. ═══ 5.4.2.4. o_type - Return Class ═══ Class: Interrupt_handler object::objtype o_type(); o_type() is a virtual function that returns the type of the object, namely object::INTHANDLER. ═══ 5.4.2.5. pending - Did a Signal Occur ═══ Class: Interrupt_handler int pending(); pending() returns a nonzero value every time it is called except for the first time it is called after a signal occurs. ═══ 5.4.2.6. print - Print Interrupt_handler Information ═══ Class: Interrupt_handler void print(int detail, int y=0); print() prints information about the Interrupt_handler object. It calls the print() member function of the object base class. detail specifies how much information is printed. The second argument, y, is used internally by the Task Library and has a default value of 0. If detail equals 0, the following information is printed: o The type of object, namely Interrupt_handler. o The number of the signal that the Interrupt_handler object is waiting for. o The value of the private member got_interrupt. got_interrupt equals 1 if the signal that the Interrupt_handler object is waiting for has been raised. It equals 0 otherwise. o The value of the private member old. old is a pointer to the previous Interrupt_handler object for the signal that the current Interrupt_handler object is waiting for. If detail equals VERBOSE, the information listed above is printed along with the following information: o The objects in the list of previous Interrupt_handler objects for the current signal o The value of the this pointer o The list of remembered tasks ═══ 5.4.3. Public Members of Interrupt_alerter ═══ Note: Interrupt_alerter is an internal class; do not use it directly. The task system creates an object of the Interrupt_alerter class when you create an object of Interrupt_handler. The following functions are described: o Constructor for Interrupt_alerter o Destructor for Interrupt_alerter ═══ 5.4.3.1. Constructor for Interrupt_alerter ═══ Class: Interrupt_alerter Interrupt_alerter(); The Interrupt_alerter constructor creates an Interrupt_alerter object. This constructor is only called once, and this call is in the declaration of the interrupt_alerter object in task.h. The interrupt_alerter object alerts the Interrupt_handler objects and any others tasks that have received interrupts since the Interrupt_alerter constructor last ran. This constructor makes any tasks that are waiting for those Interrupt_handler objects eligible for execution. Note: 1. Interrupt_alerter is a class. interrupt_alerter is a predefined object of the Interrupt_alerter class. 2. Any program that includes task.h will always have at least two tasks: the interrupt_alerter task and the main() task. ═══ 5.4.3.2. Destructor for Interrupt_alerter ═══ Class: Interrupt_alerter ~Interrupt_alerter(); The Interrupt_alerter() destructor cancels the Interrupt_alerter task. ═══ 5.4.4. Example of Using Interrupt_handler ═══ The following example shows how the Interrupt_handler class can be used. In this example, the class MyHandler is derived from Interrupt_handler. Two objects of the MyHandler class are created (h1 and h2), and a signal is raised for each of them. #include #include #include class MyHandler : public Interrupt_handler { private: int sigNo; void interrupt(); public: MyHandler(int sig); }; void MyHandler::interrupt() { cout << "Interrupt " << sigNo << " has occurred." << endl; } MyHandler::MyHandler(int sig) : Interrupt_handler(sig), sigNo(sig) { cout << "Created an interrupt handler for interrupt " << sig << endl; } void main() { MyHandler h1(SIGUSR1); MyHandler h2(SIGUSR2); // // Raise an interrupt for both MyHandler objects. // raise(SIGUSR2); raise(SIGUSR1); // // Explicitly destroy the handlers. // h1.Interrupt_handler::~Interrupt_handler(); h2.Interrupt_handler::~Interrupt_handler(); thistask->resultis(0); } This program produces the following output: Created an interrupt handler for interrupt 7 Created an interrupt handler for interrupt 8 Interrupt 8 has occurred. Interrupt 7 has occurred. ═══ 5.5. Simulation Classes ═══ This chapter describes the simulation classes: histogrm, randint, urand, and erand. You can use these classes to create program simulations and gather statistics on them. The following topics are described in this chapter: o Declarations for the Simulation Classes in task.h o Public members of histogram o Public members of randint o Public members of urand o Public members of erand ═══ 5.5.1. Declarations for the Simulation Classes in task.h ═══ You must include the following statement in any files that use the simulation classes: #include The following is an excerpt from the task.h header file that shows the relevant declarations for the members of the simulation classes: struct histogram { int l, r; int binsize; int nbin; int* h; long sum; long sqsum; histogram(int=16, int=0, int=16); void add(int); void print(); }; class randint { long randx; public: randint(long s = 0); void seed(long s); int draw(); float fdraw(); }; class urand : public randint { public: int low, high; urand(int l, int h); int draw(); }; class erand : public randint public: { int mean; erand(int m); int draw(); }; ═══ 5.5.2. Public Members of histogram ═══ Note: The following descriptions assume that the functions are called as part of a histogrm object called hist. The following functions are described: o Constructor for histogram o add - add to a bin o print - print information about histogram object An example of using histogrm is also included. ═══ 5.5.2.1. Constructor for histogram ═══ Class: histogrm histogram (int nb=16, int left=0, int right=16); The histogrm constructor creates a histogrm object. A histogram object is a collection of bins, each of which encompasses a range of numbers. Elements can be added to these bins, and the range of the bins can be changed as elements are added to them. The histogrm object has the following data members: o l: the left end of the range of bins. o r: the right end of the range of bins. o binsize: the size of each bin. o nbin: the number of bins in the histogram. o h: a pointer to the array of bins. This array is dynamically allocated by the constructor. o sum: the sum of the values added to the histogram using the add() member function. The constructor initializes sum to 0. o sqsum: the sum of the squares of the values added to the histogram using the add() member function. The constructor initializes sqsum to 0. If the nbin member of a histogram object has a value of x, the histogram will consist of x bins, each covering a range of integers from left to right. The first argument of the constructor, nb, is the number of bins in the histogram. If the value of nb is odd, nb is changed to nb + 1. The second argument of the constructor, left, is the left end of the range of bins. The third argument of the constructor, right, is the right end of the range of bins. The default number of bins is 16, the default left end is 0, and the default right end is 16. If nbin is less than or equal to zero, or if left is greater than or equal to right, an E_HISTO runtime error is produced. The size of each bin equals the value binsize=(right-left)/nb. If binsize is not an integer, the number of bins is equal to the integer value that immediately follows this value, and the value of right is changed to 1 + nb *binsize. ═══ 5.5.2.2. add - Add to a Bin ═══ Class: histogrm void add(int i); add() adds one to the i th bin of hist. In other words, it performs the following operations: h[(i-1)/hist.binsize] = h[(i-1)/hist.binsize] + 1 If i is greater than or equal to hist.l and less than hist .r, hist.l, hist.r, and hist.binsize are unchanged. However, if i is less than hist.l, these steps are followed: 1. The value of hist .binsize is doubled. 2. The value (hist .r - hist.nbin*hist.binsize) is calculated. If this value is less than or equal to i, it becomes the new value of hist.l. 3. If this value is still greater than i, return to step 1 and repeat the process. If, on the other hand, i is greater than hist .r, these steps are followed: 1. The value of hist .binsize is doubled. 2. The value (hist .l + hist .nbin*hist .binsize) is calculated. If this value is greater than i, it becomes the new value of hist .r. 3. If this value is less than or equal to i, return to step 1 and repeat the process. ═══ 5.5.2.3. print - Print Information about histogram Object ═══ Class: histogrm void print(); print() displays on standard output the following information for each bin in hist that is not empty: o The range of the bin o The number of elements in the bin ═══ 5.5.2.4. Example of Using histogram Class ═══ Class: histogrm The following program shows how you can use the histogrm class. In this example, a histogrm object is created with the following characteristics: o The number of bins is 16 o The size of each bin is 2 o The left end of the range of bins is 0 o The right end of the range of bins is 32 The first call to add() has an argument, 34, that is greater than the right end of the range of bins. Therefore, the following steps are followed: o The size of the bins is doubled to 4 o The right end of the range of bins is changed to left + (numbins * binsize) = 64 At this point, the histogram has the following characteristics: o The number of bins is 16 o The size of each bin is 4 o The left end of the range is 0 o The right end of the range is 64 The arguments for the second and third calls to add() are both within the range of the bins, so the number and the range of the bins remain unchanged. The argument of the fourth call to add(), - 4, is less than the left end of the range of bins, so the following steps are followed: o The size of the bins is doubled to 8 o The left end of the range of bins is changed to right - (numbins * binsize) = - 64 Thus, after the fourth call to add(), the histogram has the following characteristics: o The number of bins is 16 o The size of each bin is 8 o The left end of the range is -64 o The right end of the range is 64 The following is the code for this example: #include void main () { int a = 34; // Some integers. int b = 4; int c = 9; int d = -4; // // create a histogram // histogram h (16,0,32); // // add values to the histogram // h.add(a); h.add(b); h.add(c); h.add(d); // // print the contents of the histogram // h.print(); thistask->resultis(0); } This program produces the following output: [-8:0] : 1 [0:8] : 1 [8:16] : 1 [32:40] : 1 ═══ 5.5.3. Public Members of randint ═══ The following functions are described: o Constructor for randint o draw - return a random integer o fdraw - return a random floating-point value o seed - initialize random number generator ═══ 5.5.3.1. randint Constructor ═══ Class: randint randint(long seed=0); randint() constructs a randint object. seed is used as a seed for the random number generator. The default value of seed is 0. ═══ 5.5.3.2. draw - Return a Random Integer ═══ Class: randint int draw(); draw() returns a random integer value in the range from 0 to UINT_MAX (defined in limits.h). Integers returned by draw() are uniformly distributed in this range. ═══ 5.5.3.3. fdraw - Return a Random Floating-Point Value ═══ Class: randint float fdraw(); fdraw() returns a random floating-point value in the range from 0 to 1. Floating-point values returned by fdraw() are uniformly distributed in this range. ═══ 5.5.3.4. seed - Initialize Random Number Generator ═══ Class: randint void seed(long seednum); seed() reinitializes the random number generator with the seed seednum. ═══ 5.5.4. Public Members of urand ═══ The following functions are described: o Constructor for urand o draw - return a random number from specified range ═══ 5.5.4.1. urand Constructor ═══ Class: urand urand(int low, int high); urand() constructs a urand object. low and high define the lower and upper bounds for the uniform distribution of the random numbers generated by this object. If low is greater than high, urand() produces the runtime error E_URAND. ═══ 5.5.4.2. draw - Return a Random Number from Specified Range ═══ Class: urand int draw(); draw() returns a random integer value from the range specified in the call to the urand constructor. Integer values returned by draw() are uniformly distributed in this range. ═══ 5.5.5. Public Members of erand ═══ The following functions are described: o Constructor for erand o draw - return a random number from specified range ═══ 5.5.5.1. erand Constructor ═══ Class: erand erand(int mean); erand() constructs an erand object. mean is the mean for the exponential distribution of the random numbers generated by this object. ═══ 5.5.5.2. draw - Return a Random Number from Specified Range ═══ Class: erand int draw(); draw() returns a random integer value. draw() returns values that are exponentially distributed around the mean value specified in the call to the erand constructor. ═══ 6. Appendixes and Glossary ═══ Extended Complex Mathematics Library Examples Contains examples of how to determine the roots of a complex number, and how to define your own complex_error function. Extended Task Library Examples Contains examples of how to use the Task Library to implement a parallel algorithm and an event-driven simulation. ═══ 6.1. Extended Complex Mathematics Library Examples ═══ This appendix contains two examples that show some uses of the Complex Mathematics Library. The two examples are: o Finding the roots of a complex number o Defining your own complex_error function ═══ 6.1.1. Finding the Roots of a Complex Number ═══ Note: In the following text, exponents appear in italicized square brackets. The following example shows how you can use the Complex Mathematics Library to calculate the roots of a complex number. For every positive integer n, each complex number z has exactly n distinct nth roots. Suppose that in the complex plane the angle between the real axis and point z is theta , and the distance between the origin and the point z is r. Then z has the polar form (r, theta ), and the n roots of z have the values: sigma sigma ·omega sigma ·omega [2] sigma ·omega [3] . . . sigma ·omega [n-1] where omega is a complex number with the value: omega = ( cos(2pi /n), sin(2pi /n) ) and sigma is a complex number with the value: sigma = r[1/n ]( cos(theta /n), sin(theta /n) ) The following code includes the functions get_omega() to calculate the value of omega , and get_sigma() to calculate the value of sigma . The user is prompted for the complex value z and the value of n. After the values of omega and sigma have been calculated, the n roots of z are calculated and printed. #include #include #include // // function to calculate the value of omega for a given value // of n // complex get_omega(double n) { complex omega = complex(cos((2.0*M_PI)/n), sin((2.0*M_PI)/n)); return omega; } // // function to calculate the value of sigma for a given value of // n and a given complex value // complex get_sigma(complex comp_val, double n) { double rn, r, theta; complex sigma; r = abs(comp_val); theta = arg(comp_val); rn = pow(r,(1.0/n)); sigma = rn * complex(cos(theta/n),sin(theta/n)); return sigma; } void main() { double n; complex input, omega, sigma; // // prompt the user for a complex number // cout << "Please enter a complex number" << endl; cin >> input; // // prompt the user for the value of n // cout << "What root would you like of this number?" << endl; cin >> n; // // calculate the value of omega // omega = get_omega(n); cout << "Here is omega " << omega << endl; // // calculate the value of sigma // sigma = get_sigma(input,n); cout << "Here is sigma " << sigma << endl; cout << "Here are the " << n << " roots of " << input << endl; for (int i = 0; i < n ; i++) { cout << sigma*(pow(omega,i)) << endl; } } If you enter the complex value (-7, 24) for z and 2 for n, this program produces the following output: Here is omega ( -1, 1.22465e-16) Here is sigma ( 3, 4) Here are the 2 roots of ( -7, 24) ( 3, 4) ( -3, -4) ═══ 6.1.2. Defining Your Own complex_error Function ═══ You can either use the default version of complex_error() described in Errors Handled by the Complex Mathematics Library, or you can define your own version of the function. In the following example, complex_error() is redefined: #include #include #include // // redefinition of the complex_error function // int complex_error(c_exception &c) { cout << "================" << endl; cout << " Exception " << endl; cout << "type = " << c.type << endl; cout << "name = " << c.name << endl; cout << "arg1 = " << c.arg1 << endl; cout << "arg2 = " << c.arg2 << endl; cout << "retval = " << c.retval << endl; cout << "================" << endl; return 0; } void main() { complex c1(DBL_MAX,0); complex result; result = exp(c1); cout << "exp(" << c1 << ")= " << result << endl; } This example produces the following output: ================ Exception type = 3 name = exp arg1 = ( 1.79769e+308, 0) arg2 = ( 0, 0) retval = ( infinity, -infinity) ================ exp(( 1.79769e+308, 0)) = ( infinity, -infinity) If the redefinition of complex_error() in the above code is commented out, the default definition of complex_error() is used, and the program produces the following output exp(( 1.79769e+308, 0)) = ( infinity, -infinity) ═══ 6.2. Extended Task Library Examples ═══ This appendix contains two examples that show how you can use the Task Library. The two examples are: o An example of implementing parallel algorithms o An example of implementing event-driven simulations ═══ 6.2.1. An Example of Implementing Parallel Algorithms ═══ Note: In the following text, exponents are shown in italicized square brackets. The following example shows how you can use the Task Library to implement parallel algorithms. In this example, the "fan-in" parallel algorithm is used in the calculation of the inner product of two vectors. The program creates a series of objects of the class proc, each of which is identified by a node number. These proc objects are used to calculate the inner product. The program also calculates the inner product serially. The "fan-in" algorithm calculates the inner product of two vectors, A and B. If A and B are both of size n, their inner product is the sum of the products of the corresponding elements: A[0]*B[0] + A[1]*B[1] + . . . + A[n]*B[n]. The algorithm begins with the creation of n nodes numbered 0 to n-1. Each node i contains the product of the ith elements of the two vectors. Thus, node 0 contains A[0]*B[0]. At the end of the first step, each even-numbered node i contains A[i]*B[i] + A[i+1]*B[i+1], and the odd-numbered nodes are no longer used. Thus, node 0 contains A[0]*B[0] + A[1]*B[1] at the end of the first step. At the end of the second step, each node i (where i == 0 modulo 4) contains the sum of its previous contents and the contents of node i + 2. Thus, each node i (where i == 0 modulo 4) contains A[i]*B[i] + A[i+1]*B[i+1] + A[i+2]*B[i+2] + A[i +3]*B[i+3], and the other nodes are no longer used. In general, at the end of step s, node i (where i = 0 modulo 2[S]) contains the sum A[i]*B[i] + A[i+1]*B[i+1] + . . . + A[2[S]-1]*B[2[S]-1]. At the end of the algorithm, node 0 contains the inner product of the two vectors. #include #include #include // // The size of the two vectors a and b. // This size also denotes the number // of processors that will be used // in the parallel execution. // #define VECTOR_SIZE 10000 int power2( int m) { // // compute 2^m // int product = 1; for (register i=1; i<=m; ++i) product *= 2; return product; } inline double log2( double x) { // // compute the logarithm of x base 2 // return (log(x)/log(2)); } // // receiver() returns the role of the processor with id "node" // at the step "step". // It returns true if the particular processor is supposed // to "receive" the result of another processor. // It returns false if the particular processor is supposed to // stop executing and make its result available to another // processor. int receiver (int node, int step) { int numerator, denominator; if (node == 0) return 1; else { numerator = node - power2(step-1); denominator = power2(step); if (((float(numerator)/float(denominator)) - numerator/denominator) <= 1E-6) return 0; else return 1; } } // // Input data. // struct vectors { int *a, *b; double ab; // Inner product a*b vectors(); }; vectors::vectors() { // // Initialize vectors a and b with random numbers // in the interval [1,5] // urand rand(1,5); a = new int [VECTOR_SIZE]; b = new int [VECTOR_SIZE]; for (register i=0; i= 1E-6) steps ++; int s=vptr->a[my_node]*vptr->b[my_node]; // // multiply Ai*Bi // int wait_for; for( int step=1; step <= steps; ++step) { if (receiver(my_node, step)) { wait_for=my_node+power2(step-1); // // Special case when // VECTOR_SIZE is not an // integral power of 2. // if (wait_for >= VECTOR_SIZE) continue; s += t[wait_for]->result(); } else { break; // terminate } } resultis(s); } void main() { cout << "Initializing the vectors a and b of size: " << VECTOR_SIZE << " with random numbers in the interval [1,5]... " << endl; vectors v; cout << "Calculating inner product ..." << endl; vectors *vptr = &v; task **processor; processor = new task *[VECTOR_SIZE] ; // // Order of creation of tasks must be from last to first // for (register i=VECTOR_SIZE-1; i>=0; --i) processor[i] = new proc(i,vptr,processor); int sum; sum= processor[0]->result(); // // Wait for result of processor 0. // display and validate result // cout << "This is the inner product of the given vectors\n" << "Calculated serially: " << v.ab << endl << "Calculated through the fan-in algorithm: " << sum << endl; thistask ->resultis(0); } The output created by this program looks like this: Initializing the vectors a and b of size: 10000 with random numbers in the interval [1,5]... Calculating inner product ... This is the inner product of the given vectors Calculated serially: 89735 Calculated through the fan-in algorithm: 89735 ═══ 6.2.2. An Example of Implementing Event-Driven Simulations ═══ The following example shows how you can use the Task Library to implement event-driven simulations. This example simulates a system consisting of two M/M/1 queues that accept packets, process them, and release them. The two M/M/1 queues have different service rates. In the simulation, the packets are produced by the producer object input. The M/M/1 queues are represented by exponential_service_center objects mm1_q1 and mm1_q2. The packets are accepted at the end of their processing by the consumer object output. output calculates the throughput of the system (the total number of packets processed divided by the total time taken to process them). The producer object input, the two M/M/1 queues, and the consumer object output are connected by a series of Task Library queues. The following example could easily be modified to model systems that have exponential service centers in parallel. Note: The word "queue" is used in two different senses in this section. The M/M/1 queues that are implemented by the exponential_service_center objects are meant to simulate the behavior of systems that perform some kind of operation on a series of customers. The amount of time that each operation takes is independent of the previous state of the system. The Task Library queues, on the other hand, are queue data structures. See Queue Management Classes for a description of the qhead and qtail classes. This simulation follows the steps illustrated in Structure of the Event-Driven Simulation Example: 1. The producer object input creates packet objects that it places on the qtail object packet_q. 2. The exponential_service_center object mm1_q1 takes packet objects from the qhead object that corresponds with the qtail object packet_q. mm1_q1 "processes" these packet objects and then places them on the qtail object that corresponds with the qhead object intermediate_result_q. 3. The exponential_service_center object mm1_q2 takes packet objects from the qhead object intermediate_result_q. mm1_q2 "processes" these packet objects and then places them on the qtail object that corresponds to the qhead object result_q. 4. The consumer object output takes packet objects from the qhead object result_q and calculates throughput statistics. ┌─────────┐ │ input │ └────┬────┘  ┌────────────────────────┐ │ packet_q │ └────────────┬───────────┘  ┌───────────┐ │ mm1_q │ └─────┬─────┘  ┌────────────────────────┐ │ intermediate_result_q │ └────────────┬───────────┘  ┌───────────┐ │ mm1_q2 │ └─────┬─────┘  ┌────────────────────────┐ │ result_q │ └────────────┬───────────┘  ┌─────────┐ │ output │ └─────────┘ Structure of the Event-Driven Simulation Example #include #include #include #include #define abs(A) (((A)<0.0)? -(A):(A)) static myseed = abs(time(0)+0x74637602) ; // Request to the system class packet : public object { public: int interval; long sys_arrival_time; long sys_departure_time; }; // // Task that produces packet arrivals to the system. // class producer : public task { erand *rnd; public: producer(int, float, qtail *, task*); ~producer() { delete rnd; } }; producer::producer(int arrivals, float lambda, qtail *packet_q, task *end) { packet *pckt; int interarrival_time, prev_event_time = 0; float *f = new float(0.0) ; rnd = new erand(int(1/lambda)); // random number generator. rnd->seed(myseed++); for (register i=0; idraw(); *f += interarrival_time; pckt->interval = interarrival_time; pckt->sys_arrival_time = prev_event_time+interarrival_time; prev_event_time += interarrival_time; packet_q->put(pckt); } // // Wait for the result analyzer to terminate // (void) end->result(); *f = *f/arrivals; // // Return achieved input rate // *f = 1.0/(*f) ; resultis((int) f); } // // An M/M/1 queue simulator. This task receives packets // from a queue and places them into another // queue after "processing". // class exponential_service_center : public task { erand *rnd; qtail *local_q_t; qhead *local_q_h; public: exponential_service_center(int, float, qhead*, qtail*, task *); ~exponential_service_center() { delete local_q_t; delete rnd; } }; exponential_service_center::exponential_service_center ( int arrivals, float mu, qhead *input, qtail *output, task *end) { rnd = new erand(int (1/mu)); rnd -> seed (myseed++); local_q_t = new qtail; local_q_h = local_q_t -> head(); int cust=0, service_time, terminated = 0; register int cur_arrivals = 0; // Arrivals so far long next_arrival, next_departure; float *f = new float (0.0); packet *pckt = (packet *) input->get(), *departing_pckt; next_arrival = sched::get_clock() + pckt -> interval; next_departure = LONG_MAX; // "LONG_MAX" is used as a flag // // Event loop (Note that every packet generates two events -- // arrival/departure) // for (register i=0; i<2*arrivals; ++i) { if ((next_arrival == LONG_MAX) && (next_departure == LONG_MAX)) { // // Wait for an arrival of a packet // at the input queue. // pckt = (packet *) input->get(); next_arrival = sched::get_clock() + pckt -> interval; } // // Wait for event // delay((next_arrivaldraw(); *f += service_time; next_departure = sched::get_clock() + service_time; pckt -> interval = 0 ; // No more inter-arrival time } // // Put packet into a local "departure" queue // local_q_t -> put(pckt); // // Schedule new arrival if there are // packets in the input queue if (++cur_arrivals < arrivals) { if (input->rdcount() > 0) { pckt = (packet *) input->get(); next_arrival = sched::get_clock() + pckt -> interval; } else next_arrival = LONG_MAX; } else if (cur_arrivals == arrivals) next_arrival = LONG_MAX; } else { // // packet departure // cust -= 1; // // Remove packet from local "departure" // queue and put it in the output queue // departing_pckt = (packet *) local_q_h->get(); departing_pckt -> sys_departure_time = sched::get_clock(); output -> put(departing_pckt); if (cust >0) { service_time = rnd->draw(); *f += service_time; next_departure = sched::get_clock() + service_time; departing_pckt = (packet *) local_q_h->get(); departing_pckt -> interval = 0 ; local_q_h->putback(departing_pckt); } else next_departure = LONG_MAX; } } // // Wait for termination of result analyzer // (void) end->result(); // // Return achieved output rate (1/service rate) // *f = *f/arrivals; *f = 1/(*f) ; resultis ((int) f); } // // This task generates the average system throughput and delay // class consumer : public task { public: float throughput, delay; consumer(int, qhead *); }; consumer::consumer(int arrivals, qhead *result_q) { packet *pckt; int total_packets=0; long total_delay=0; for (register i=0; iget(); total_packets += 1; total_delay += pckt->sys_departure_time-pckt->sys_arrival_time; } throughput = float (total_packets) / sched::get_clock(); delay = float (total_delay) / total_packets ; resultis (0); } void main() { sched::setclock(0); float lambda=0.01; // in packets per msec float mu1=0.05; // in packets per msec float mu2=0.07; // in packets per msec int arrivals=50000; qtail *packet_q = new qtail; qhead *intermediate_result_q = new qhead; qhead *result_q = new qhead; consumer *output = new consumer(arrivals, result_q); producer *input = new producer(arrivals, lambda, packet_q, output); exponential_service_center *mm1_q1 = new exponential_service_center (arrivals, mu1, packet_q->qtail::head(), intermediate_result_q ->qhead::tail(), output); exponential_service_center *mm1_q2 = new exponential_service_center (arrivals, mu2, intermediate_result_q, result_q ->qhead::tail(), output); (void) output->result(); float actual_lambda = *((float *) (input->result())); float actual_mu1 = *((float *) (mm1_q1->result())); float actual_mu2 = *((float *) (mm1_q2->result())); float analytic_throughput = output->throughput; cout << "Simulation Results :\n" << "Average Throughput: " << actual_lambda << " packets/msec\n" << "Average delay: " << output->delay << " msec\n" << endl ; float analytic_delay = (1/actual_mu1) / (1.0-actual_lambda/actual_mu1)+ (1/actual_mu2) / (1.0-((actual_lambdaresultis(0); } The output created by this program looks like this: Simulation Results: Average Throughput: 0.00999937 packets/msec Average delay: 39.7195 msec Analytic results: Average Throughput: 0.0099992 packets/msec Average delay: 39.7881 msec ═══ 6.3. Glossary ═══ ═══ 6.3.1. abstract class ═══ abstract class A class with at least one pure virtual function. It is a C++ class used as a base class for other classes. The abstract class represents a concept; classes derived from it represent implementations of the concept. You cannot have a direct object of an abstract class. (See also base class.) ═══ 6.3.2. access ═══ access Determines whether or not a class member is accessible in an expression or declaration. ═══ 6.3.3. access declaration ═══ access declaration Used to restore access to members of a base class. ═══ 6.3.4. access resolution ═══ access resolution The process by which the accessibility of a particular class member is determined. ═══ 6.3.5. access specifiers ═══ access specifiers One of the C++ keywords: public, private, and protected. ═══ 6.3.6. anonymous union ═══ anonymous union A union without a class name. It must not be followed by a declarator. ═══ 6.3.7. argument declaration ═══ argument declaration See parameter declaration. ═══ 6.3.8. array ═══ array A variable that contains an ordered group of data objects. All data items (or elements) in an array have the same data type. ═══ 6.3.9. array element ═══ array element A single data item in an array. ═══ 6.3.10. base class ═══ base class A class from which other classes are derived. May itself be derived from another base class. (See also abstract class.) ═══ 6.3.11. buffer flush ═══ buffer flush A process that removes the contents of a buffer. After a buffer flush, the buffer is empty. ═══ 6.3.12. case clause ═══ case clause In a switch statement, a case label followed by any number of statements. ═══ 6.3.13. case label ═══ case label The word case followed by a constant expression and a colon. When the selector evaluates the value of the constant expression, the statements following the case label are processed. ═══ 6.3.14. cast expression ═══ cast expression A cast expression explicitly converts its operand to a specified arithmetic, scalar, or class type. ═══ 6.3.15. cast operator ═══ cast operator The cast operator is used for explicit type conversions. ═══ 6.3.16. catch block ═══ catch block A block associated with a try block that receives control when an exception matching its argument is thrown. ═══ 6.3.17. class ═══ class A user-defined data type that can contain both data representations (data members) and functions (member functions). ═══ 6.3.18. class key ═══ class key One of the C++ keywords: class, struct and union. ═══ 6.3.19. class library ═══ class library A collection of C++ classes. ═══ 6.3.20. class member operators ═══ class member operators Used to access class members through class objects or pointers to class objects. They are ., ->, .*, and ->*. ═══ 6.3.21. class template ═══ class template A blueprint describing how a set of related classes can be constructed. ═══ 6.3.22. compilation unit ═══ compilation unit A single compiled file and all its associated include files. ═══ 6.3.23. complete class name ═══ complete class name The complete qualification of a nested class name including all enclosing class names. ═══ 6.3.24. Complex Mathematics Library ═══ Complex Mathematics Library A class library that provides the facilities to manipulate complex numbers and perform standard mathematical operations on them. ═══ 6.3.25. complex number ═══ complex number A number made up of a real part and an imaginary part. A complex number can be represented by an ordered pair (a, b), where a is the value of the real part and b is the value of the imaginary part. The same complex number could also be represented as a + bi, where i is the square root of -1. ═══ 6.3.26. constructor ═══ constructor A class member function with the same name as its class, used to construct class objects and sometimes to initialize them. ═══ 6.3.27. conversion ═══ conversion A change in the type of a value. For example, when you add values having different data types, the compiler converts both values to the same type before adding them. ═══ 6.3.28. conversion function ═══ conversion function A member function that specifies a conversion from its class type to another type. ═══ 6.3.29. copy constructor ═══ copy constructor A constructor used to make a copy of a class object from another class object of the same class type. ═══ 6.3.30. data abstraction ═══ data abstraction See abstraction (data) ═══ 6.3.31. default clause ═══ default clause In a switch statement, the keyword default followed by a colon, and one or more statements. When the conditions of the specified case labels in the switch statement do not hold, the default clause is chosen. ═══ 6.3.32. default constructor ═══ default constructor A constructor that takes no arguments, or if it takes any arguments, all its arguments have default values. ═══ 6.3.33. default initialization ═══ default initialization The initial value assigned to a data object by the compiler if no initial value is specified by the programmer. ═══ 6.3.34. define statement ═══ define statement A preprocessor statement that causes the preprocessor to replace an identifier or macro call with specified code. ═══ 6.3.35. demangling ═══ demangling The conversion of mangled names back to their original source code names. During compilation, identifiers such as function and static class member names are mangled (encoded) with type and scoping information to ensure type-safe linkage. These mangled names appear in the object file and the final executable file. Demangling converts these names back to their original names to make program debugging easier. ═══ 6.3.36. delete ═══ delete 1) The keyword delete identifies a free store deallocation operator. 2) The delete operator is used to destroy objects created by new. ═══ 6.3.37. derived class ═══ derived class A class that inherits the proper base class become members of a derived class object. You can add additional data members and member functions to the derived class. A derived class object can be manipulated as if it is a base class object. The derived class can override virtual functions of the base class. ═══ 6.3.38. destructor ═══ destructor A special member function with the same name as its class preceded by a ~ (tilde). A destructor, which has no arguments and a void return type, "cleans up" after an object by, for example, freeing any storage that was dynamically allocated when the object was created. ═══ 6.3.39. dynamic binding ═══ dynamic binding Binding that occurs at run-time. ═══ 6.3.40. element ═══ element The component of an array, subrange, enumeration, or set. ═══ 6.3.41. enumeration constant ═══ enumeration constant An identifier (that has an associated integer value) defined by an enumeration type. You can use an enumeration constant anywhere an integer constant is allowed. ═══ 6.3.42. enumeration tag ═══ enumeration tag The identifier that names an enumeration data type. ═══ 6.3.43. enumeration type ═══ enumeration type In C++, an enumeration type is a distinct data type that is not an integral type. An enumeration type defines a set of enumeration constants. ═══ 6.3.44. enumerator ═══ enumerator An enumeration constant and its associated value. ═══ 6.3.45. EOF ═══ EOF End-of-file. A character value used to represent the end of an ASCII file. Corresponds to the numeric value (-1). ═══ 6.3.46. exception ═══ exception Any user, logic, or system error detected by a function that does not itself deal with the error but passes the error on to a handling routine. Passing this error is called throwing an exception. ═══ 6.3.47. exception handler ═══ exception handler Exception handlers are catch blocks in C++. Catch blocks catch exceptions when they are thrown from a function enclosed in a try block. Try blocks, catch blocks and throw expressions are the constructs used to implement formal exception handling in C++. ═══ 6.3.48. exception handling ═══ exception handling A type of error handling that allows control and information to be passed to an exception handler when an exception occurs. ═══ 6.3.49. external data definition ═══ external data definition A definition appearing outside a function. The defined object is accessible to all functions that follow the definition and are located within the same source file as the definition. ═══ 6.3.50. float constant ═══ float constant A number containing a decimal point, an exponent, or both a decimal point and an exponent. The exponent contains an e or E, an optional sign (+ or -), and one or more digits (0 through 9). ═══ 6.3.51. free store ═══ free store Dynamically allocates memory. New and delete are used to allocate and deallocate free store. ═══ 6.3.52. friend class ═══ friend class A class in which all the member functions are granted access to the private and protected members of another class. It is named in the declaration of another class and uses the keyword friend as a prefix to the class. For example: class me { friend class you; // ... }; makes all the functions in class you friends of class me. ═══ 6.3.53. friend function ═══ friend function A function that is granted access to the private and protected parts of a class. It is named in the declaration of the class and uses the keyword friend as a prefix. ═══ 6.3.54. function definition ═══ function definition The complete description of a function. A function definition contains an optional storage class specifier, an optional type specifier, a function declarator, parameter declarations, and a block statement (the function body). ═══ 6.3.55. function template ═══ function template Provides a blueprint describing how a set of related individual functions can be constructed. ═══ 6.3.56. generic class ═══ generic class See class templates. ═══ 6.3.57. header file ═══ header file A file that contains declarations used by a group of functions or users. ═══ 6.3.58. I/O Stream Library ═══ I/O Stream Library A class library that provides the facilities to deal with many varieties of input and output. ═══ 6.3.59. identifier ═══ identifier A name that refers to a data object. An identifier contains some combination of letters, digits, and underscores, but its first character cannot be a digit. ═══ 6.3.60. include file ═══ include file A text file that contains declarations used by a group of functions, programs, or users. Also known as a header file. ═══ 6.3.61. include statement ═══ include statement A preprocessor statement that causes the preprocessor to replace the statement with the contents of a specified file. ═══ 6.3.62. inheritance ═══ inheritance An object-oriented programming technique that allows you to use existing classes as bases for creating other classes. ═══ 6.3.63. initializer ═══ initializer An expression used to initialize data objects. In C++, there are three types of initializers: 1) You can use an expression followed by an assignment operator to initialize fundamental data type objects or class objects that have copy constructors. 2) You can use an expression enclosed in braces ( {} ) to initialize aggregates. 3) You can use a parenthesized expression list to initialize base classes and members using constructors. ═══ 6.3.64. inline function ═══ inline function Inlining is a hint to the compiler to perform inline expansion of the body of a function member. Functions declared and defined simultaneously in a class definition are inline. You can also explicitly declare a function inline by using the keyword inline. Both member and nonmember functions can be inlined. ═══ 6.3.65. instance ═══ instance An object-oriented programming term synonymous with 'object'. An instance is a particular instantiation of a data type. It is simply a region of storage that contains a value or group of values. For example, if a class box is previously defined, two instances of a class box could be instantiated with the declaration: box box1, box2; ═══ 6.3.66. instantiate ═══ instantiate To create or generate a particular instance (or object) of a data type. For example, an instance box1 of class box could be instantiated with the declaration: box box1; ═══ 6.3.67. integral object ═══ integral object A character object, an object having variations of the type int, or an object that is a bit field. ═══ 6.3.68. internal data definition ═══ internal data definition A description of a variable appearing in a block that directs the system to allocate storage for that variable and makes that variable accessible to the current block after its point of declaration. ═══ 6.3.69. manipulator ═══ manipulator A value tha can be inserted into streams or extracted from streams to affect or query the behaviour of the stream. ═══ 6.3.70. member ═══ member A data object or function in a structure, union or class. Members can also be classes, enumerations, bit fields and type names. ═══ 6.3.71. member function ═══ member function Operators and functions that are declared as members of a class. A member function has access to the private and protected data members and member functions of an object of its class. Member functions are also called methods. ═══ 6.3.72. memory leak ═══ memory leak Occurs when dynamic memory that has been allocated to an application is not freed by the application when the memory is no longer needed. ═══ 6.3.73. method ═══ method Method is an object-oriented programming term synonymous with member function. ═══ 6.3.74. multiple inheritance ═══ multiple inheritance An object-oriented programming technique implemented in C++ through derivation, in which the derived class inherits members from more than one base class. See also inheritance. ═══ 6.3.75. nested class ═══ nested class A class defined within the scope of another class. ═══ 6.3.76. new ═══ new A keyword identifying a free store allocation operator. The new operator may be used to create class objects. ═══ 6.3.77. object ═══ object A region of storage. An object is created when a variable is defined or new is invoked. An object is destroyed when it goes out of scope. See also instance. ═══ 6.3.78. object-oriented programming ═══ object-oriented programming A programming approach based on the concepts of data abstraction and inheritance. Unlike procedural programming techniques, object-oriented programming concentrates not on how something is accomplished but instead on what data objects comprise the problem and how they are manipulated. ═══ 6.3.79. operator function ═══ operator function An overloaded operator that is either a member of a class, or takes at least one argument that is a class type or a reference to a class type. ═══ 6.3.80. overflow ═══ overflow That portion of an operation's result that exceeds the capacity of the intended unit of storage. ═══ 6.3.81. overflow condition ═══ overflow condition A condition that occurs when a portion of the result of an operation exceeds the capacity of the intended unit of storage. ═══ 6.3.82. overloading ═══ overloading Allows you to redefine functions and most standard C++ operators when the functions and operators are used with class types. ═══ 6.3.83. pad ═══ pad To fill unused positions in a field with dummy data, usually zeros, ones, or blanks. ═══ 6.3.84. parameter declaration ═══ parameter declaration A description of a value that a function receives. A parameter declaration determines the storage class and the data type of the value. ═══ 6.3.85. pointer ═══ pointer A variable that holds the address of a data object or function. ═══ 6.3.86. pointer to member ═══ pointer to member Used to access the address of non static members of a class. ═══ 6.3.87. precedence ═══ precedence The priority system for grouping different types of operators with their operands. ═══ 6.3.88. private ═══ private A private member of a class is only accessible to member functions and friends of that class. ═══ 6.3.89. protected ═══ protected A protected member of a class is accessible to member functions and friends of that class, or member functions and friends of classes derived from that class. ═══ 6.3.90. prototype ═══ prototype See function prototype. ═══ 6.3.91. public ═══ public A public member of a class is accessible to all functions. ═══ 6.3.92. pure virtual function ═══ pure virtual function A virtual function is declared pure by replacing the function definition with '=0;'. See also abstract classes. ═══ 6.3.93. qualified class name ═══ qualified class name Any class name or class name qualified with one or more :: (scope) operators. ═══ 6.3.94. qualified name ═══ qualified name Used to qualify a nonclass type name such as a member by its class name. ═══ 6.3.95. qualified type name ═══ qualified type name Used to reduce complex class name syntax by using typedefs to represent qualified class names, ═══ 6.3.96. static ═══ static A keyword used for defining the scope and linkage of variables and functions. For internal variables, the variable has block scope and retains its value between function calls. For external values, the variable has file scope and retains its value within the source file. For class variables, the variable is shared by all objects of the class and retains its value within the entire program. ═══ 6.3.97. static binding ═══ static binding Binding that occurs at compilation time based on the resolution of overloaded functions. or more instructions enclosed in braces ({}). ═══ 6.3.98. storage class specifier ═══ storage class specifier One of: auto, register, static, or extern. ═══ 6.3.99. stream ═══ stream A continuous stream of data elements being transmitted, or intended for transmission, in character or binary-digit form, using a defined format. ═══ 6.3.100. stream buffer ═══ stream buffer A stream buffer is a buffer between the ultimate consumer and the I/O Stream Library functions that format data. It is implemented in the I/O Stream Library by the streambuf class and the classes derived from streambuf. ═══ 6.3.101. structure ═══ structure A class data type that contains an ordered group of data objects and member functions. Unlike an array, the data objects within a structure can have varied data types. A structure can be used in all places a class is used. The initial projection is public. ═══ 6.3.102. structure tag ═══ structure tag The identifier that names a structure data type. ═══ 6.3.103. switch expression ═══ switch expression The controlling expression of a switch statement. ═══ 6.3.104. switch statement ═══ switch statement A C++ language statement that causes control to be transferred to one of several statements depending on the value of an expression. ═══ 6.3.105. task ═══ task A lightweight, nonpreemptive routine that you can use to simulate the operation of programs. Only a single task executes at any one time. Less time and space are required to create a task than a true operating system process. ═══ 6.3.106. Task Library ═══ Task Library A class library that provides the facilities to write programs that are made up of tasks. ═══ 6.3.107. template ═══ template A family of classes or functions with variable types. ═══ 6.3.108. template class ═══ template class A class instance generated by a class template. ═══ 6.3.109. template function ═══ template function A function generated by a function template. ═══ 6.3.110. this ═══ this A keyword that identifies a special type of pointer that references in a member function the class object with which the member function was invoked. ═══ 6.3.111. type balancing ═══ type balancing A conversion that makes both operands have the same data type. If the operands do not have the same size data type, the compiler converts the value of the operand with the smaller type to a value having the larger type. ═══ 6.3.112. type definition ═══ type definition A definition of a data type. ═══ 6.3.113. type specifier ═══ type specifier Used to indicate the data type of an object or function being declared. ═══ 6.3.114. ultimate consumer ═══ ultimate consumer The target of data in an input and output operation. Can be a file, a device, or an array of bytes in memory. ═══ 6.3.115. ultimate producer ═══ ultimate producer The source of data in an input and output operation. Can be a file, a device, or an array of bytes in memory. ═══ 6.3.116. union ═══ union A variable that can hold any one of several data types, but only one data type at a time. ═══ 6.3.117. union tag ═══ union tag The identifier that names a union data type. ═══ 6.3.118. virtual function ═══ virtual function A class function declared with the keyword virtual. The implementation that is executed when you call a virtual function is determined at run-time based on the type of the object for which it is called.