The iostream library
Our first hint of object-oriented
messaging appears in the next program[MESSAGE.CPP].
#include <iostream.h>
#include <string.h>
void main()
{
int index;
float distance;
char letter;
char name[25];
index = -23;
distance = 12.345;
letter = 'X';
strcpy(name,"John Doe");
cout << "The value of index is " << index << "\n";
cout << "The value of distance is " << distance << "\n";
cout << "The value of letter is " << letter << "\n";
cout << "The value of name is " << name << "\n";
index = 31;
cout << "The decimal value of index is " << dec << index << "\n";
cout << "The octal value of index is " << oct << index << "\n";
cout << "The hex value of index is " << hex << index << "\n";
cout << "The character letter is " << (char)letter << "\n";
cout << "Input a decimal value --> ";
cin >> index;
cout << "The hex value of the input is " << index << "\n";
}
In this program we define a few variables and assign values to them for
use in the output statements illustrated in lines 13 to 16, and in lines
118 to 22. The new operator
cout is the output function to the standarddevice, the monitor, but works a little differently from our familiar
printf( ) function, because we do not have to tell the system what type
we are outputting.
Like C, C++ has no input or output operations as part of the language
itself, but defines the stream library to add input and output functions in
a very elegant manner.
The operator << (sometimes called the "put to" operator but more
properly called the
insertion operator) tells the system to output thevariable or constant following it, but lets the system decide how to
output the data. In line 13, we first tell the system to output the string,
which it does by copying characters to the monitor, then we tell it to
output the value of index. Notice, however, that we fail to tell it what
the type is or how to output the value. Since we don't tell the system
what the type is, it is up to the system to determine what the type is and
to output the value accordingly. After the system finds the correct type,
we also leave it up to the system to use the built in default as to how
many characters should be used for this output. In this case, we find
no leading or trailing blanks, which is fine for this output. Finally, the
new line character is output, and the line of code is terminated with a
semicolon.
When we called the cout output function in line 13, we actually called
two different functions because we used it to output a string and a
variable of type int. This is the first hint at object-oriented programming
because we simply broadcast a
message to the system to print out avalue, and let the system find an appropriate function to do so. We are
not required to tell the system exactly how to output the data, we only
tell it to output it. This is a very weak example of object-oriented
programming, and we will get into it in much more depth later.
In line 14 we tell the system to output a different string, followed by a
floating point number, and another string of one character, the new line
character. In this case, we told it to output a floating point number
without telling it that it was a floating point number, once again letting
the system choose the appropriate output means based on its type. We
did lose a bit of control in the transaction, however, because we had no
control over how many significant digits to print before or after the
decimal point. We chose to let the system decide how to format the
output data. The variable named letter is of type char, and is assigned
the value of the uppercase X in line 11, then printed as a letter in line
15.
Because C++ has several other operators and functions available with
streams, you have complete flexibility in the use of the stream output
functions. You should refer to your compiler documentation for details
of other available formatting commands. The cout and the printf( )
statements can be mixed in any way you want, as both statements result
in output to the monitor.
The Stream library
The stream library was defined for use with C++ for increased
execution efficiency. The printf() function was defined early in the
development C and is meant to be all things to all programmers. As a
result, it became a huge function with lots of extra baggage that is only
used by a few programmers. By defining the smaller special purpose
stream library, C++ allows the programmer to use a limited set of
formatting capabilities, but which are still adequate for most
programming jobs. If more elaborate formatting capabilities are
required, the complete printf( ) library is available within any C++
program, and the two types of outputs can be freely mixed.
Lines 18 to 24 illustrate some of the additional features of the stream
library which can be used to output data in a very flexible yet controlled
format. The value of index is printed out in decimal, octal, and
hexadecimal format. When one of the special stream operators, dec,
oct, or hex, is output, all successive output will be in that number base.
Looking ahead to line 24, we find the value of index printed in hex
format due to the selection of the hexadecimal base in line 20. If none
of these special stream operators are output, the system defaults to
decimal format.
The CIN operator
In addition to the cout operator, there is a
cin operator which is used toread data from the standard input device, usually the keyboard. The cin
operator uses the >> operator, usually called the ‘get from’ operator
but properly called the
extraction operator. It has most of the flexibilityof the cout operator. A brief example of the use of the cin operator is
given in line 23. The special stream operators, dec, oct, and hex, also
select the number base for the cin stream separately from the cout
stream. If none is specified, the input stream also defaults to decimal.
In addition to the cout operator and the cin operator there is one more
standard operator, the
cerr, which is used to output to the errorhandling device. This device cannot be redirected to a file as the output
to the cout can be. The three operators (cout, cin, and cerr) correspond
to the stdout, the stdin, and the stderr stream pointers of the
programming language C.
File stream operations
The next example program [FSTREAM.CPP] includes examples of the
use of streams with files.
#include <iostream.h>
#include <fstream.h>
#include <process.h>
void main()
{
ifstream infile;
ofstream outfile;
ofstream printer;
char filename[20];
cout << "Enter the desired file to copy ----> ";
cin >> filename;
infile.open(filename, ios::nocreate);
if (!infile) {
cout << "Input file cannot be opened.\n";
exit(1);
}
outfile.open("copy");
if (!outfile) {
cout << "Output file cannot be opened.\n";
exit(1);
}
printer.open("PRN");
if (!printer) {
cout << "There is a problem with the printer.\n";
exit(1);
}
cout << "All three files have been opened.\n";
char one_char;
printer << "This is the beginning of the printed copy.\n\n";
while (infile.get(one_char)) {
outfile.put(one_char);
printer.put(one_char);
}
printer << "\n\nThis is the end of the printed copy.\n";
infile.close();
outfile.close();
printer.close();
}
A file is opened for reading, another for writing, and a third stream is
opened to the printer to illustrate the semantics of stream operations on
a file. The only difference between the streams in the last program and
the streams in this program is the fact that in the last program, the
streams were already opened for us by the system. You will note that
the stream named printer is used in the same way we used the cout
operator in the last program. Finally, because we wish to exercise good
programming practice, we close all of the files we have opened prior to
ending the program.
The standard file I/O library is available with ANSI-C; it is as easy to
use as the stream library and very portable. For more information on the
stream file I/O library, see Strøustrup's book or refer to your compiler
documentation. When you compile and execute this program it will
request a file to be copied; you can enter the name of any ASCII file in
the current directory.
The following program [VARDEF.CPP] has a few more additions to
the C++ language which aid in writing a clear and easy-to-understand
program.
#include <iostream.h>
int index;
void main()
{
int stuff;
int &another_stuff = stuff; // A synonym for stuff
stuff = index + 14; //index was initialised to zero
cout << "stuff has the value " << stuff << "\n";
stuff = 17;
cout << "another_stuff has the value " << another_stuff << "\n";
int more_stuff = 13; //not automatically initialised
cout << "more_stuff has the value " << more_stuff << "\n";
for (int count = 3;count < 8;count++) {
cout << "count has the value " << count << "\n";
char count2 = count + 65;
cout << "count2 has the value " << count2 << "\n";
}
static unsigned goofy; //automatically initialised to zero
cout << "goofy has the value " << goofy << "\n";
}
In C++, as in ANSI-C, global and static variables are automatically
initialised to zero when they are declared. The variables named index in
line 2, and goofy in line 18 are therefore automatically initialised to
zero.
Of course, you can still initialise either to some other value if you so
desire. Global variables are sometimes called
external since they areexternal to any functions.
Automatic variables - those declared inside ofany function - are not automatically initialised but will contain the value
that happens to be in the location where they are defined, which must
be considered a garbage value. The variable named stuff in line 5,
therefore, does not contain a valid value, but some garbage value which
should not be used for any meaningful purpose. In line 7 it is assigned a
value based on the initialised value of index and it is then displayed on
the monitor for your examination.
The reference variable
The ampersand (&) in line 6 defines another_stuff as a
referencevariable, which is a new addition to C++. In fact, the reference variable
should not be used very often, if at all, in this context. In order to be
complete however, we will discuss its operation.
The reference variable is not quite the same as any other variable
because it operates like a self dereferencing pointer. Following its
initialisation, the reference variable becomes a synonym for the variable
stuff, and changing the value of stuff will change the value of
another_stuff because they are both actually referring to the same
variable. The synonym can be used to access the value of the variable
for any legal purpose in the language. It should be pointed out that a
reference variable must be initialised to reference some other variable
when it is declared or the compiler will respond with an error.
Following initialisation, the reference variable cannot be changed to
refer to a different variable.
The use of the reference variable in this way can lead to very confusing
code, but it has another use where it can make the code very clear and
easy to understand. We will study this use later.
Definitions as executable statements
Anywhere it is legal to put an executable statement, it is also legal to
declare a new variable, because a data declaration is defined as an
executable statement in C++. In line 11 we define the new variable
named more_stuff and initialise it to the value of 13. It has a scope from
the point where it was defined to the end of the block in which it is
defined, so it is valid throughout the remainder of the main program.
The variable named goofy is declared even later in line 18.
It is very significant that the variable is declared near its point of usage.
This makes it easier to see just what the variable is used for, since it has
a much more restricted scope of validity. When you are debugging a
program, it is convenient if the variable declaration is located in close
proximity to where you are debugging the code.
Links: Home C Programming Guide C++ programming Guide