9.1 C++ STREAMS:
The I/O system in C++
is designed to work with a wide variety of devices including terminals, disks,
and tape drives. Although each device is very different; the I/O system supplies
an interface to the programmer that is independent of the actual device being
accessed. This interface is known as stream.
A stream is a sequence of bytes. It acts
either as a source from which the
input data can be obtained or as a destination
to which the output data can be sent. The source stream that provides data
to the program is called the input stream
and the destination stream that receives output from the program is called
the output stream. In other words, a
program extracts the bytes from input
stream and inserts bytes into an
output stream. The data in the input stream can come from the keyboard or any
other storage device. Similarly, the data in the output stream can go to the
screen or any other storage device. As mentioned earlier, a stream acts as an
interface between the program and the input/output device handles data (input
or output) independent of the devices used.
C++ contains several
pre-defined streams that are automatically opened when a program begins its
execution. These include cin and cout, which have been used very often
in our earlier programs. We know that cin
represents the input stream connected to the standard input device (usually
the keyboard) and cout represents
the output stream connected to the standard output device (usually the screen).
Note that the keyboard and the screen are default options. We can redirect
streams to other devices or files, if necessary.
9.2 C++ Stream Classes:
The C++ I/O system
contains a hierarchy of classes that are used to define various streams to deal
with both the console and disk files. These classes are called stream classes. Figure shows the
hierarchy of the stream classes used for input and output operations with the
console unit. These classes are declared in the header file iostream.h. This file should be included in all
the programs that communicate with the console unit.
9.3 Unformatted I/O Operations:
Overloaded Operators >> and <<: We have used the objects cin and cout (pre-defined
in the iostream.h file) for the input
and output of data of various types. This has been made possible by overloading
the operators >> and << to recognize all the basic C++ types. The
>> operator is overloaded in the istream
class and << is overloaded in the ostream
class. The following is the general format for reading data from the keyboard:
cin
>> variable1 >> variable2 >>…… >> variableN;
variable1, varible2, ...are valid C++ variable names
that have been declared already. This statement will cause the computer to stop
the execution and look for input data from the keyboard. The input data for
this statement would be:
data1, data2 ………data N
The input data are
separated by white spaces and should match the type of variable in the cin list. Spaces, newlines and tabs
will be skipped.
The operator >>
reads the data character by character and assigns it to the indicated location.
The reading for a variable will be terminated at the encounter of a white space
or a character that does not match the destination type. For example, consider
the following code:
int code;
cin
>> code;
Suppose the following
data is given as input:
4258D
The operator will
read the characters up to 8 and the value 4258 is assigned to code. The
character D remains in the input
stream and will be input to the next cin
statement.
The general form for
displaying data on the screen is:
cout << item1 << item2 << ..,. << itemN;
The items item1 through itemN may be variables or constants of any basic type. We have used
such statements in a number of examples illustrated in previous chapters.
put() and get() Functions: The classes istream
and ostream define two member
functions get( ) and put( ) respectively to handle the
single character input/output operations. There are two types of get( ) functions. We can use both get(char *) and get(void) prototypes to fetch a character including the blank
space, tab and the newline character. The get(char
*) version assigns the input character to its argument and the get(void) version returns the input
character.
Since these functions
are members of the input/output stream classes, we must invoke them using an
appropriate object. For example:
char c;
cin.get(c);
// get a character from
keyboard and assign it to c
while(c!=
'\n') {
cout << c; //
display the character on screen
cin.get(c); //
get another character
}
This code reads and
displays a line of text (terminated by a newline character). The operator
>> can also be used to read a character but it will skip the white spaces
and newline character. The above while
loop will not work properly if the statement.
cin >> c;
is used in place of
cin.get(c);
Try using both of
them and compare the results.
The get(void) version is used as follows:
……
char c;
c =
cin.get( ); // cin.get(c);
replaced
……
……
The value returned by
the function get( ) is assigned to
the variable c.
The function put( ), a member of ostream class, can be used to output a
line of text, character by character. For example,
cout.pt('x');
displays the
character x and
cout.put(ch);
displays the yalue of
variable ch.
The variable ch must contain a character value. We
can also use a number as an argument to the function put( ). For example,
cout.put(68);
displays the character
D. This statement will convert the
int value 68 to a char value and display the character whose ASCII value is 68.
The following segment of a program reads a line of text from the keyboard and
displays it on the screen.
char c;
cin.get(c);
II read a character
while(c
!= '\n') {
cout.put(c);
II display the character on screen
cin.get(c);
}
Program illustrates
the use of these two character-handling functions.
void main( )
{ int count = 0;
char c;
cout
<< "INPUT TEXT\n" ;
cin.get(c);
while(c
!= '\n') {
cout.put(c);
count ++;
cin.get(c);
}
cout
<< "\nNumber of characters = “ << count <<
“\n";
}
When we type a line
of input, the text is sent to the program as soon as we press the RETURN key.
The program then reads one character at a time using the statement cin.get(c); and displays it using the
statement cout.put(c);. The process
is terminated when the newline character is encountered.
getline( ) and write( ) Functions: We can read and
display a line of text more efficiently using the line-oriented input/output
functions getline( ) and write( ). The getline( ) function reads a whole line
of text that ends with a newline character (transmitted by the RETURN key).
This function can be invoked by using the object cin as follows:
cin.getline(line, size);
This function call
invokes the function getline( )
which reads character input into the variable line . The reading is terminated as soon as either the newline
character '\n ' is encountered or size-1characters
are read (whichever occurs first). The newline character is read but not saved.
Instead, it is replaced by the null character. For example, consider the
following code:
char
name[20];
cin.getline(name,20);
Assume that we have
given the following input through the keyboard:
Bjarne
Stroustrup <press RETURN>
This input will be
read correctly and assigned to the character array name. Let us suppose the
input is as follows:
Object
Oriented Programming <press RETURN >
In this case, the
input will be terminated after reading the following 19 characters:
Object Oriented Pro
The two blank spaces
contained in the string are also taken into account.
We can also read
strings using the operator >> as follows:
cin
>> name;
But cin can read strings that do not
contain white spaces. This means that cin
can read just one word and not a series of words such as "Bjarne
Stroustrup". But it can read the following string correctly:
Bjarne_Stroustrup
After reading the
string, cin automatically adds the
terminating null character to the character array.
// Program to
demonstrate cin and getline( )
# include
<iostream.h>
void main( )
{
int size
= 20;
char city
[20];
cout
<< "Enter city name: \n";
cin
>> city:
cout
<< "City name:" <<
city << "\n\n":'
cout
<< "Enter city name again: \n";
cin.getline(city,
size);
cout
<< “City name now: " << city << "\n\n";
cout
<< “Enter another city name: \n”;
cin.getline(city,
size):
cout
<< “ New city name:” << city << “\n\n";
}
The write( ) function displays an entire
line and has the following form:
cout.write(line,size);
The first argument line represents the name of the string
to be displayed and the second argument size
indicates the number of characters to display. Note that it does not stop
displaying the characters automatically when the null character is encountered.
If the size is greater than the
length of line, then it displays
beyond the bounds of line. Program
below illustrates how write( )
method displays a string.
#include
<iostream.h>
#include
<string.h>
void main ( )
{
char *
stringl = "C++ ";
char *
string2 = "Programming” ;
int m =
strlen(stringl);
int n =
strlen(string2) ;
for(int i
= 1; i < n; i++)
{ cout.write(string2, i); cout <<
"'n"; }
for(i =
n; i > 0; i--)
{ cout.write(string2. i); cout <<
"'n"; }
cout.write(string1,
m) .write(string2. n);
cout
<<"n";
cout.write(stringl.
10);
}
The statement
cout.write(string1,
10);
displays more
characters than what is contained in stringl.
It is possible to concatenate
two strings using the write( )
function. The statement
cout.write(string1,
m).write(string2, n);
is equivalent to the
following two statements:
cout.write(string1,
m);
cout.write(string2,
n);
9.4 Formatted Console I/O Operations
C++ supports a number
of features that could be used for formatting the output. These features
include:
- ios class functions and flags
·
Manipulators.
- User-defined output functions.
The ios class contains a large number of
member functions that would help us to format the output in a number of ways.
The most important ones among them are listed in Table
Function Task
width( ) To specify the required
field size for displaying an output value
precision( ) To specify the number of digits
to be displayed after the
decimal point of a float value.
fill( ) To specify a
character that is used to fill the unused portion of a
field.
setf( ) To specify format
flags that can control the form of output
display (such as left-justification and
right-justification).
unsetf( ) To clear the flags
specified.
Manipulators are
special functions that can be included in the I/O statements to alter the
format parameters of a stream. Table shows some important manipulator functions
that are frequently used. To access these manipulators, the file iomanip.h should be included in the
program.
Table Manipulators
Manipulators Equivalent ios function
setw( ) width( )
setprecision(
) precision( )
setfill(
) fill( )
setiosflags( ) setf( )
resetiosflags( ) unsetf( )
In addition to these
functions supported by the C++ library, we can create our own manipulator
functions to provide any special output formats. The following sections will
provide details of how to use the pre-defined formatting functions and how to
create new ones.
width( ): We can use the width( )
function to define the width of a field necessary for the output of an item.
Since, it is a member function, we have to use an object to invoke it, as shown
below:
cout.width
(w);
where w is the field width (number of
columns). The output will be printed in a field of w characters wide at the right end of the field. The width( )
function can specify the field width for only one item (the item that follows
immediately). After printing one item (as per the specifications) it will
revert back to the default. For example, the statements
cout.width(5);
cout
<< 543 << 12 << " \n";
The value 543 is
printed right-justified in the first five columns. The specification width(5)
does not retain the setting for printing the number 12. This can be improved as
follows:
cout.width(5);
cout
<< 543;
cout.width(5);
cout
<< 12 << " \n";
The field width
should be specified for each item separately. C++ never truncates the values
and therefore, if the specified field width is smaller than the size of the
value to be printed, C++ expands the field to fit the value. Program
demonstrates how the function width( ) works.
#include
<iostream.h>
void main( )
{
int
items[4) = 110, 8, 12, 151 ;
int
cost[4] = 175, 100, 60, 991 ;
cout.width(5)
;
cout <
< "ITEMS" ;
cout.width(8);
cout <
< "COST" ;
cout.width(15);
cout <
< "TOTAL VALUE" < < "\n" ;
int sum =
0;
for(int i
= 0; i < 4; i++)
{
cout.width(5);
cout <<
items(i);
cout.width(8);
cout <<
cost[i];
int value
= items[i ] * cost[i];
cout.width(15)
; cout << value <<
"\n";
sum = sum
+ value;
}
cout
< < " \n Grand Total = " ;
cout.width(2)
; cout << sum << "\n"; 3
}
Note that a field of
width two has been used for printing the value of sum and the result is not
truncated.
Setting Precision: precision( ): By default, the floating numbers
are printed with six digits after the decimal point. However, we can specify
the number of digits to be displayed after the decimal point while printing the
floating-point numbers. This can be done by using the precision( ) member
function as follows:
cout.precision(d);
where d is the number of digits to the right
of the decimal point. For example, the statements
cout.precision(3);
cout <<
sqrt(2) << " \n";
cout <<
3.14159 << “ \n";
cout <<
2.50032 << " \n";
will produce the
following output:
1.141
(truncated)
3.142
(rounded to the nearest point)
2.5 (no
trailing zeros)
Note that, unlike the
function width( ), precision( ) retains the setting in
effect until it is reset. That is why we have declared only one statement for
the precision setting, which is used by all the three outputs.
We can set different
values to different precision as follows:
cout.precision(3);
cout
<< sqrt(2) << " \n";
cout.precision(5);
//Reset the precision
cout
<< 3.14159 << " \n";
We can also combine
the field specification with the precision setting. Example:
cout.precision(2);
cout.width(5);
cout
<< 1.2345;
Program shows how the
functions width( ) and precision( ) are jointly used to
control the output format.
#include<iostream.h>
#include
<math.h>
void main( )
{
cout
<< "Precision set to 3 digits \n\n” ;
cout.precision(3)
;
cout.width(10);
cout
<< "VALUE” ;
cout.width(15);
cout
<< "SQRT OF VALUE" << "\n" ;
for(int n
= 1; n-<= 5; n++)
{
cout.width(8)
;
cout
<< n;
cout.width(13);
cout
<< sqrt(n) << "\n";
}
cout
<< "\n Precision set to 5 digits \n\n” ;
cout.precision(5);
//precision parameter changed
cout
<< " sqrt(10) = " << sqrt(10) << "\n\n”;
cout.precision(0);
//precision set to default
cout
<< " sqrt(10) = 0. << sqrt(10) << " (default
setting)\n"; I
}
Here is the output of
Program
Precision
set to 3 digits
VALUE SQRT-OF-VALUE
1
1
2
1.414
3
1.732
4
2
5
2.236
Precision
set to 5 digits
sqrt(10)
= 3.16228
sqrt(10)
= 3.162278 (default setting)
Observe the following
from the output:
- The output is rounded to the nearest cent (i.e., 1.6666 will be 1.67 for two digit precision but 1.3333 will be 1.33).
- Trailing zeros are truncated.
- Precision setting stays in effect until it is reset.
- Default precision is 6 digits.
Filling and Padding fill(): We have been
printing the values using much larger field widths than required by the values.
The unused positions of the field are filled with white spaces, by default.
However, we can use the fill( )
function to fill the unused positions by any desired character. It is used in
the following form:
cout.fill(ch);
Where ch represents the character which is
used for filling the unused positions. Example:
cout.fill(“*”);
cout.width(10);
cout
<< 5250 << "\n";
Financial
institutions and banks use this kind of padding while printing cheques so that
no one can change the amount easily. Like precision(
), till( ) stays in effect till
we change it.
# include
<iostream.h>
void main( )
{
cout.fill('<');
cout.precision(3)
;
for(int n = 1; n <= 6; n++)
{
cout.wid.th
(5) ;
cout
<< n;
cout.width(10)
;
cout
<< 1.0 / float(n) << "\n";
if(n ==
3) cout.fill('>');
}
cout
<< "\nPadding changed \n\n";
cout.fill('#');
// fill() reset
cout.width(15)
;
cout
<< 12.345678 << "\n";
}
Exercise:
- Write a program, which reads a text from the keyboard and displays the following details.
- Number of lines
- Number of characters
- Number of words
- Design a program to provide the following output specification for printing float vales.
- 10 columns width
- Right-justified
- Two digits precision
- Filling of unused places with *
- Write a program to display the details as shown below:
NAME CODE COST
Turbo C++ 1001 250.50
C primer 890 350.00
Java 1120 550.90