AhmadLang / Object Oriented Programing using C++
.pdf
Object Oriented Programming using C++
returns the previous set of all flags, and clears one formatting flag (leaving the remaining flags unaltered). The unsetting of a default flag (e.g., cout.unsetf(ios::dec)) has no effect.
ios::width() const:
returns (as int) the current output field width (the number of characters to write for numerical values on the next insertion operation). Default: 0, meaning `as many characters as needed to write the value'.
ios::width(int nchars):
returns (as int) the previously used output field width, redefines the value to nchars for the next insertion operation. Note that the field width is reset to 0 after every insertion operation, and that width() currently has no effect on text-values like char * or string values.
Output
Output in C++ evolves around the ostream class. The ostream class defines the basic operators and members for inserting information into streams: the insertion operator ( operator<<()), and special members like ostream::write() for writing unformatted information from streams.
From the class ostream several other classes are derived, all having the functionality of the ostream class, and adding their own specialties. In the next sections we will introduce:
The class ostream, offering the basic facilities for doing output;
The class ifstream, allowing us to open files for writing (comparable to C's fopen(filename, "w"));
The class ostringstream, allowing us to write informatioon to memory rather than to files (streams) (comparable to C's sprintf() function).
Manipulators, allowing us, among other things, to format output and to change the radix used for displaying integral numbers.
Basic output: the class `ostream'
The class ostream is the class defining basic output facilities. The cout, clog and cerr objects are all ostream objects. Note that all facilities defined in the ios class, as far as output is concerned, is available in the ostream class as well, due to the inheritance mechanism
Ostream objects can be constructed by the following ostream constructors:
ostream object:
this constructor basically creates a new ios object. It is seldomly used.
ostream object(streambuf *sb):
this constructor can be used to construct a wrapper around an existing open stream. The wrapper can be used, e.g., to write to an external process
In order to use the ostream class in C++ sources, the #include <iostream> preprocessor directive must be given.
141
Object Oriented Programming using C++
Writing to `ostream' objects
The ostream class supports both formatted and binary output.
The insertion operator ( <<) may be used to insert values in a type safe way into ostream objects. This is called formatted output, as binary values which are stored in the computer's memory are converted to human-readable ASCII characters according to certain formatting rules.
Note that the insertion operator points to the ostream object wherein the information must be inserted. The normal associativity of the <<-operator remains unaltered, so when a statement like
cout << "hello " << "world";
is encountered, the leftmost two operands are evaluated first (cout << "hello "), and an ostream & object, which is actually the same cout object, is returned. Now, the statement is reduced to
cout << "world"
and the second string is inserted into cout.
The << operator has a lot of (overloaded) variants, so many types of variables can be inserted into ostream objects. There is an overloaded <<-operator expecting an int, a double, a pointer, etc. etc.. For every part of the information that is inserted into the stream the operator returns the ostream object into which the information so far was inserted, and the next part of the information to be inserted is devoured.
As an extension to the ANSI/ISO standard, the Gnu compiler provides the following additional member functions for formatted output:
: ostream& ostream::form(char const *format, ...):
This member function returns a reference to an ostream object. Therefore, it can be used in combination with, e.g., the insertion operator:
cout.form("Hello %s", "world") << endl;
The member function form() is the analogue of C's printf() and fprintf() functions.
ostream& ostream::vform(char const *format, va_list list):
When variadic functions are constructed in which information must be inserted into a stream, the member function vform() can be used, being the analogue of C's vprintf() and vfprintf() functions.
When binary files must be written, the information should normally not be formatted: an int value should be written as a series of unaltered bytes, not as a series of ASCII numeric characters 0 to 9. The following member functions are defined for ostream objects:
ostream& ostream::put(char c):
This member function
writes a single character to the output stream. Since a character is a byte, this member function could also be used for writing a single character to a text-file.
142
Object Oriented Programming using C++
ostream& ostream::write(void const *buffer, int length):
This member function writes at most len bytes, stored in the void const *buffer to the ostream object. The bytes are written as they are stored in the buffer, no formatting is done whatsoever.
`ostream' positioning
Although not every ostream object supports repositioning, some do. This means that it is possible to rewrite a section of the stream which was written earlier. Repositioning is frequently used in database applications where it must be possible to access the information in the database randomly.
The following members are available:
streampos ostream::tellp():
this function returns the current position where the next write-operation to the stream will take place. For all practical purposes a streampos can be considered to
be an unsigned long.
ostream &ostream::seekp(streamoff step, ios::seekdir org):
This member function can be used to reposition the stream. The function expects a streamoff step, the stepsize in bytes to go from org. For all practical purposes a streampos can be considered to be a long. The origin of the step, org is a ios::seekdir value. Possible values are:
ios::beg:
org is interpreted as the stepsize relative to the beginning of the stream. If org is not specified, ios::beg is used.
ios::cur:
org is interpreted as the stepsize relative to the current position (as returned by tellp() of the stream).
ios::end:
org is interpreted as the stepsize relative to the current end position of the the stream.
It is allowed to seek beyond end of file . Writing bytes to a location beyond EOF will pad the intermediate bytes with ASCII-Z values: null-bytes. It is not allowed to seek before begin of file. Seeking before ios::beg will cause the ios::fail flag to be set.
`ostream' flushing
143
Object Oriented Programming using C++
Unless the ios::unitbuf flag has been set, information written to an ostream object is not immediately written to the physical stream. Rather, an internal buffer is filled up during the write-operations, and when full it is flushed.
The internal buffer can be flushed under program control:
ostream& ostream::flush():
this member function writes any buffered information to the ostream object. The call to flush() is implied when:
The ostream object ceases to exist,
The endl or flush manipulators are inserted into the ostream object,
A stream derived from ostream is closed.
Output to files: the class `ofstream'
The ofstream class is derived from the ostream class: it has the same capabilities as the ostream class, but can be used to access files or create files for writing.
In order to use the ofstream class in C++ sources, the preprocessor directive #include <fstream> must be given. If this directive is used, it is not necessary anymore to include the header file iostream.
The following constructors are available for ofstream objects:
ofstream object:
This is the basic constructor. It creates an ofstream object which may be associated with an actual file later, using the open() member (see below).
ofstream object(char const *name, int mode, int perm):
This constructor can be used to associate an ofstream object with the file named name, using output mode mode, and permission bits perm.
The output mode is by default ios::out.
The file permission bits value is 0644, meaning read-only access.
are the standard Unix permission values. The default owner: read/write access, group members and others:
In the following example an ofstream object, associated with the newly created file /tmp/scratch, is constructed:
ofstream out("/tmp/scratch");
ofstream object(int fd):
144
Object Oriented Programming using C++
construct an ofstream wrapper around an existing open file whose file descriptor is known. Using the well-known file descriptor for the standard output stream, STDOUT_FILENO, as defined in, e.g., the unistd.h header file.
Instead of directly associating an ofstream object with a file, the object can be constructed first, and opened later.
tt(void ofstream::open(char const *name, int mode, int perm)): quote( Having constructed an tt(ofstream) object, the member function tt(open()) can be used to associate the tt(ofstream) object with an actual file. This member function can only be used with a file whose name is known. It is not possible to open a tt(ofstream) object with the tt(open()) member function when a file descriptor is available.)
ofstream::close():
Conversely, it is possible to close an ofstream object explicitly using the close() member function. The function sets the ios::fail flag of the closed object. Closing the file will flush any buffered information to the associated file. A file is automatically closed when the associated ofstream object ceases to exist.
A subtlety is the following: Assume a stream is constructed, but it is not actually attached to a file. E.g., the statement ofstream ostr was executed. When we now check its status through good(), a non-zero (i.e., ok) value will be returned. The `good' status here indicates that the stream object has been properly constructed. It doesn't mean the file is also open. To test whether a stream is actually open, In order to write information to memory, using the stream facilities, ostringstream objects can be used. These objects are derived from ostream objects. The following constructors and members are available:
ostringstream ostr:
The constructor will construct an empty ostringstream object. Any information inserted into the object is stored in dynamically allocated memory which is deleted when the ostringstream object goes out of scope.
string ostringstream::str() const:
This member function will return the string that is stored inside the ostringstream object.
Before the stringstream class was available the class ostrstream was commonly used for doing output to memory. This latter class suffered from the fact that, once its contents were retrieved using its str() member function, these contents were `frozen', meaning that its dynamically allocated memory was not released when the object went out of scope. Although this situation could be prevented (using the ostrstream member call freeze(0)), this implementation could easily lead to memory leaks. The stringstream class does not suffer from these risks. Therefore, the use of the class ostrstream is now deprecated in favor of ostringstream.
The following example illustrates the use of the ostringstream class: several values are inserted into the object. Then, the stored text is stored in a string, whose length and contents are thereupon printed. Ostringstream objects are most often used for doing `type to string' conversions, like converting int to string. Formatting commands can be used with stringstreams as well, as they are available in ostream objects.
#include <string> #include <sstream>
int main()
{
145
Object Oriented Programming using C++
ostringstream ostr;
ostr.setf(ios::showbase); ostr.setf(ios::hex, ios::basefield); ostr << 12345;
cout << ostr.str() << endl;
ostr << " -- "; ostr.unsetf(ios::hex); ostr << 12;
cout << ostr.str() << endl;
/*
Output from this program: 0x3039
0x3039 -- 12 */
}
Manipulators
Iostream objects define a set of format flags that are used for determining the way values are inserted. The format flags can be controlled by member functions, but also by manipulators. Manipulators are inserted into the stream, instead of being activated through the member selection operator (`.').
New manipulators can be constructed as well. In this section the manipulators that are available in the default implementation of the ostream class are discussed.
dec, hex, oct:
These manipulators enforce the display of integral numbers in, respectively, decimal, hexadecimal and octal format. The default conversion is decimal. The conversion is applied to values inserted into the stream after processing the manipulators. For example,
cout << 16 << ", " << hex << 16 << ", " << oct << 16; // produce the output:
16, 10, 20
setbase(int b):
This manipulator can be used to display integral values using the base 8, 10 or 16. It can be used as an alternative to in situations where the base of integral values is parameterized.
setfill(int ch):
This manipulator can be used when the header file iomanip.h is included. It can be used when the header file iomanip.h is included. It defines the filling character in situations where the values of numbers are too small to fill the width that is used to display these values. By default the blank space is used.
setprecision(int width):
146
Object Oriented Programming using C++
This manipulator can be used when the header file iomanip.h is included. It will set the precision in which a float or double is displayed.
setw(int width):
This manipulator can be used when the header file iomanip.h is included. It expects as its argument the width of the field that is inserted or extracted next. It can be used as manipulator for insertion, where it defines the maximum number of characters that are displayed for the field, but it can also be used during extraction, where it defines the maximum number of characters that are inserted into an array of characters. To prevent array bounds overflow when extracting from cin, setw() can be used as well:
cin >> setw(sizeof(array)) >> array;
A nice feature is that a long string appearing at cin is split into substrings of at most sizeof(array) - 1 characters, and that an ASCII-Z character is automatically appended. Notes:
setw() is valid only for the next field. It does not act like e.g., hex which changes the general state of the output stream for displaying numbers.
When setw(sizeof(someArray)) is used, make sure that someArray really is an array, and not a pointer to an array: the size of a pointer, being, e.g., four bytes, is usually not the size of the array that it points to....
For reasons unknown (to me), setw() doesn't work when a string is inserted into an ostream. If a string must be inserted using a particular field width, the string::c_str() member can be used.
Input
Input in C++ evolves around the istream class. The istream class defines the basic operators and members for extracting information from streams: the extration operator ( operator>>()), and special members like istream::read() for reading unformatted information from streams.
From the class istream several other classes are derived, all having the functionality of the istream class, and adding their own specialties. In the next sections we will introduce:
The class istream, offering the basic facilities for doing input;
The class ifstream, allowing us to open files for reading (comparable to C's fopen(filename, "r"));
The class istringstream, allowing us to read informatioon from text that is not stored on files (streams) but in memory (comparable to C's sscanf() function).
Basic input: the class `istream'
The class istream is the class defining basic output facilities. The cin object is an istream object. Note that all facilities defined in the ios class, as far as input is concerned, is available in the istream class as well, due to the inheritance mechanism
Istream objects can be constructed by the following istream constructors:
147
Object Oriented Programming using C++
istream object:
this constructor basically creates a new ios object. It is seldomly used.
istream object(streambuf *sb):
this constructor can be used to construct a wrapper around an existing open stream. The wrapper can be used, e.g., to read from an external process .
In order to use the istream class in C++ sources, the #include <iostream> preprocessor directive must be given.
Reading from `istream' objects
The istream class supports both formatted and unformatted binary input.
The extraction operator ( >>) may be used to extract values in a type safe way from istream objects. This is called formatted input, whereby human-readable ASCII characters are converted, according to certain formatting rules, to binary values which are stored in the computer's memory.
Note that the extraction operator points to the objects or variables which must receive new values. The normal associativity of the >>-operator remains unaltered, so when a statement like
cin >> x >> y;
is encountered, the leftmost two operands are evaluated first (cin >> x), and an istream & object, which is actually the same cin object, is returned. Now, the statement is reduced to
cin >> y
and the y variable is extracted from cin.
The >> operator has a lot of (overloaded) variants, so many types of variables can be extracted from istream objects. There is an overloaded >>-operator available for the extraction of an int, a double, a string, an array of characters, possibly to a pointer, etc. etc.. String or character array extraction will (by default) skip all white space characters, and will then extract all consecutive non-white space characters. After processing an extraction operator, the istream object into which the information so far was inserted is returned, which will thereupon be used as the lvalue for the remaining part of the statement.
As an extension to the ANSI/ISO standard, the Gnu compiler provides the following additional member functions for formatted input:
: istream& istream::scan(char const *format, ...):
This member function returns a reference to an istream object. Therefore, it can be used in combination with, e.g., the extraction operator:
cin.scan("%s", charptr) >> x;
The member function scan() is the analogue of C's scanf() and fscanf() functions.
148
Object Oriented Programming using C++
istream& istream::vscan(char const *format, va_list list):
When variadic functions are to be used to extract information from streams, the member function vscan() can be used, being the analogue of C's vscanf() and vfscanf() functions.
When binary files must be read, the information should normally not be formatted: an int value should be read as a series of unaltered bytes, not as a series of ASCII numeric characters 0 to 9. The following member functions for reading information from istream objects are available:
int istream::gcount():
this function does not actually read from the input stream, but returns the number of characters that were read from the input stream during the last unformated input operation.
int istream::get():
this function returns EOF or reads and returns the next available single character as an int value.
istream &istream::get(char &c):
this function reads the next single character from the input stream into c. As its return value is the stream itself, its return value can be queried to determine whether the extraction succeeded or not.
istream& istream::get(char *buffer, int len [, char delim]):
This function reads a series of len - 1 characters from the input stream into the array starting at buffer, which should be at least len bytes long. At most len - 1 characters are read into the buffer. By default, the delimiter is a newline ('\n') character. The delimiter itself is not removed from the input stream.
After reading the series of characters into buffer, an ASCII-Z character is written beyond the last character that was written to buffer. The functions eof() and fail()return 0 (false) if the delimiter was not encountered before len - 1 characters were read. Furthermore, an ASCII-Z can be used for the delimiter: this way strings terminating in ASCII-Z characters may be read from a (binary) file. The program using this get() member function should know in advance the maximum number of characters that are going to be read.
istream& istream::getline(char *buffer, int len [, char delim]):
This function operates analogously to the previous get() member function, but delim is removed from the stream if it is actually encountered. At most len - 1 bytes are written into the buffer, and a trailing ASCII-Z character is appended to the string that was read. The delimiter itself is not stored in the buffer. If delim was not found (before reading len - 1 characters) the fail() member function, and possibly also eof() will return true.
istream& istream::ignore(int n , int delim):
149
Object Oriented Programming using C++
This member function has two (optional) arguments. When called without arguments, one character is skipped from the input stream. When called with one argument, n characters are skipped. The optional second argument specifies a delimiter: after skipping n or the delim character (whichever comes first) the function returns.
int istream::peek():
this function returns the next available input character, but does not actually remove the character from the input stream.
istream& istream::putback (char c):
The character c is `pushed back' into the input stream, to be read again as the next character. EOF is returned if this is not allowed. One character may always be put back.
istream& istream::read(void *buffer, int len):
This function reads at most len bytes from the input stream into the buffer. If EOF is encountered first, fewer bytes are read, and the member function eof() will return true. This function will normally be used for reading binary files.
istream& istream::unget():
an attempt is made to push back the last character that was read into the stream. Normally, this succeeds, as with putback()
`istream' positioning
Although not every istream object supports repositioning, some do. This means that it is possible to rewrite a section of the stream which was written earlier. Repositioning is frequently used in database applications where it must be possible to access the information in the database randomly.
The following members are available:
streampos istream::tellg():
this function returns the current position where the next write-operation to the stream will take place. For all practical purposes a streampos can be considered to
be an unsigned long.
istream &istream::seekg(streamoff step, ios::seekdir org):
This member function can be used to reposition the stream. The function expects a streamoff step, the stepsize in bytes to go from org. For all practical purposes a streampos can be considered to be a long. The origin of the step, org is a ios::seekdir value. Possible values are:
ios::beg:
150
