Last modified: Tue, 07 Dec 2010 14:31:19 +0200
Complete: ##################-- (90%)
9.1 Introduction
9.2 Overview of Streams in C++
9.3 Formatted Input/Output
9.4 Input/Output with Files
9.5 Examples
9.6 Exercises
9.1 Introduction
Until now, we have used cout to write data to the screen and cin to read data from the keyboard
without specifying any format. This section deals with formatted input/output (formatted I/O);
this allows the programmer to specify how numbers/characters are displayed or read.
In this section we will also look at how to read from and write to files (file I/O).
In this section, we will learn
- an overview of streams
- how to manage a formatted I/O using the <iomanip> library
- how to write to and read from files using streams
9.2 Overview of Streams in C++
In C++, as part of the language, no statements are defined for writing to a screen (or to a file) and for
reading data into a program. However, C++ includes some libraries to facilitate I/O.
These libraries contain some classes called stream
(which is an abstraction that represents a device on which input and output operations are performed).
The iostream classes view the flow of data from your program to the screen or a file.
The class cout is a stream of output stream ostream.
The reason cout is called a stream is that output sent to it flows like a stream of bytes.
If things are sent to cout, they fall in line, one after to the other are dropped into the stream.
Then they are displayed on the screen in that order.
(The name cout, pronounced see-out, stands for console output).
Input is analogous to output. The class cin is a stream of input stream istream.
In this case, we have data flowing in from the input stream.
(The name cin, pronounced see-in, stands for console input).
One principal goal of streams is to encapsulate the problems of getting the data to and from the external storage (e.g. a hard-drive) or the screen.
Once a stream is created, your program works with the stream and the stream hides the details.
Hence, a stream can basically be represented as a source or destination of characters of indefinite length.
Figure 9.1 illustrates this fundamental idea.
See also: http://www.cplusplus.com/reference/.
Fig 9.1: Encapsulation through streams
The standard C++ library provides the following classes to perform I/O operations:
- iostream: Stream class to facilitate basic I/O. It contains istream and ostream.
- ofstream: Stream class to output to files
- ifstream: Stream class to input from files
- fstream: Stream class to both read and write from/to files.
9.3 Formatted Input/Output
Generating cleanly formatted output is a common programming requirement.
Formatting improves your user interface and makes it easier to read any debugging messages that you might
output to the screen. In C++, the I/O formatting can be performed by either manipulators or using the methods of I/O classes and
format-state flags (a detailed overview can be found here).
We will use manipulators in these notes.
A manipulator is a function that can alter
the characteristics of the output (and input) stream. For cout, we have seen the
endl manipulator which ends a line (and calls the flush function of the ostream).
Using cout to Format Output
The following manipulators, defined in the header file <iomanip>, are the most commonly used for formatting output.
- setw(n) : sets the minimum width of the next output. The length of the width is n.
- setfill(c) : fills leading spaces in a number with a given character c.
- setprecision(n) : sets the maximum number of digits (given by n) that are displayed for a number.
- fixed : allows inserting floating-point values in fixed format
- scientific : allows inserting floating-point values in scientific format
- left : left-justify
- right : right-justify
- dec : insert or extract integer values in decimal format
- oct : insert or extract values in octal (base 8) format
- hex : insert or extract integer values in hexadecimal (base 16) format
For example, the following program section
int i = 1299;
float f = 314.15926;
cout << "numbers:" << setw(10) << i << f << "four" << endl;
will output
1 2 3
12345678901234567890123456789012345
numbers: 1299314.159four
The first two lines are not part of the output, they are just for gauging the output.
After outputting "numbers:",
setw(10) creates a 10-column empty field and then the number 1299
is placed in this field right-justified. This is followed by "314.159four".
Note that 314.15926 is output as "314.159" because of the default format of the compiler.
For the following assignment of variables
int i = 1453;
float f = 314.15926;
string s = "University of Gaziantep";
example program sections and the corresponding outputs are given below:
Program section |
Output (first lines are not shown) |
cout << setw(30) << s << endl; // default
cout << setw(30) << left << s << endl; // left-justified
cout << setw(30) << right << s << endl; // right-justified
|
12345678901234567890123456789012345
University of Gaziantep
University of Gaziantep
University of Gaziantep
|
cout << setw(10) << setfill('0') << i << endl;
|
12345678901234567890123456789012345
0000001453
|
cout << setw(10) << i << endl;
cout << setw(10) << left << i << endl;
cout << setw(10) << right << i << endl;
|
12345678901234567890123456789012345
1453
1453
1453
|
cout << setw(10) << dec << i << endl; // decimal (default)
cout << setw(10) << oct << i << endl; // octal (base 8)
cout << setw(10) << hex << i << endl; // hexadecimal (base 16)
|
12345678901234567890123456789012345
1453
2655
5ad
|
cout << setw(15) << fixed << setprecision(4) << f << endl;
cout << setw(15) << fixed << setprecision(2) << f << endl;
|
12345678901234567890123456789012345
314.1593
314.16
|
cout << setw(15) << scientific << setprecision(3) << f << endl;
|
12345678901234567890123456789012345
3.142e+02
|
Here an example programming application is given below. The program outputs the sine and cosine values of angles from
0o to 180o in steps of 10o.
09prg01.cpp: A formatted trigonometric table
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
|
// A formatted trigonometric table
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{
cout << setprecision(5) << fixed;
for(int deg=0; deg<=180; deg+=10)
{
double x = M_PI*deg/180.;
cout << setw(3) << deg
<< setw(10) << sin(x)
<< setw(10) << cos(x) << endl;
}
return 0;
} |
0 0.00000 1.00000
10 0.17365 0.98481
20 0.34202 0.93969
30 0.50000 0.86603
40 0.64279 0.76604
50 0.76604 0.64279
60 0.86603 0.50000
70 0.93969 0.34202
80 0.98481 0.17365
90 1.00000 0.00000
100 0.98481 -0.17365
110 0.93969 -0.34202
120 0.86603 -0.50000
130 0.76604 -0.64279
140 0.64279 -0.76604
150 0.50000 -0.86603
160 0.34202 -0.93969
170 0.17365 -0.98481
180 0.00000 -1.00000
|
Using cin to Format Input
cin, being responsible for input, is a class defined in <iostream>.
The extraction operator (>>) is used to put data into your program's variables. For example, the following operation
writes data from the buffer of cin to your local variable, var.
cin has some member functions to manipulate input data.
The famous one is get() that is used to get a single character, including a white space, or a string for input.
For example, the following program section
char a, b, c;
cout << "Enter three letters: ";
cin.get(a).get(b).get(c);
cout << a << " " << b << " " << c;
will output
Enter three letters: one
o n e
Here is the another usage
char str1[256], str2[256];
cout << "Enter string one: ";
cin.get(str1, 256);
cout << "string one: " << str1 << endl;
cout << "Enter string two: ";
cin >> str2;
cout << "string two: " << str2 << endl;
an example I/O is
Enter string one: Now is the time
string one: Now is the time
Enter string two: Now is the time
string two: Now
In the second input str2 is assigned a string from a space-delimited input so only the first word is stored.
Note that the getline() function can be used to input a whole line into a string:
string s;
cout << "Input your message: ";
getline(cin, s);
9.4 Input/Output with Files
Reading from and writing to files is performed using data streams.
The ifstream class is used for reading (inputting) data from a file, and
the ofstream class is used for writing (outputting) data to a file.
These two class require the fstream to be included in the program.
There are several methods associated with ifstream and ofstream.
The most useful are given in the following table.
Method (function) |
Description |
open(filename, mode) |
filename is the name (and path) of the file to open.
mode is an optional parameter and can have the following flags:
ios::in - open for input operations (default for ifstream)
ios::out - open for output operations (default for ofstream)
ios::binary - open in binary mode (default is text mode)
ios::ate - set the initial position at the end of the file (default is the beginning of the file)
ios::app - append the content to the current content of the file
ios::trunc - delete the previous content and replaced the new one
|
is_open() |
Returns true if a file is successfully opened. |
eof() |
Returns true if a file open (for reading) has reached the end. |
close() |
Closes the file. |
File Output
As an example, the following line opens the file student.txt for an output operation.
ofstream myFile;
myFile.open("student.txt", ios::out);
As ios::out is the default behaviour for ofstream, this is equivalent to:
ofstream myFile;
myFile.open("student.txt");
A combination of flags can also be used.
ofstream f1, f2;
f1.open("student1.txt", ios::out | ios::app); // output or append
f2.open("student2.txt", ios::out & ios::app); // output and append
Data input/output from a file can be performed in the same way as for cin/cout.
Here we will give some examples.
The following program writes two lines of strings to the file example.txt.
09prg02.cpp: Writing data to a text file
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
|
// Writing data to a text file
#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
ofstream myFile("example.txt");
// check if the file is open
if (myFile.is_open())
{
myFile << "This is first line.\n";
myFile << "This is second line.\n";
myFile.close();
}
else
cout << "Unable to open file example.txt";
return 0;
} |
[in the file example.txt]
This is first line.
This is second line.
|
cout manipulators can also work with file I/O.
The program given below, writes sine and cosine values of the angles given in Program 9.1 to the file trigo.data
instead of the screen.
09prg03.cpp: Writing trigonometric data to a text file
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
|
// Writing trigonometric data to a text file
#include <iostream>
#include <cmath>
#include <iomanip>
#include <fstream>
using namespace std;
int main ()
{
const float PI=3.1415926;
string filename = "trigo.data";
ofstream myFile(filename.c_str());
if (myFile.is_open())
{
cout << "Writing data to the file: " << filename << endl;
myFile << setprecision(5) << fixed;
for(int deg=0; deg<=180; deg+=10)
{
float x = PI*deg/180.;
myFile << setw(3) << deg
<< setw(10) << sin(x)
<< setw(10) << cos(x) << endl;
}
myFile.close();
}
else
cout << "Unable to open file " << filename;
return 0;
} |
[on the screen]
Writing data to the file: trigo.data
[in the file trigo.data]
0 0.00000 1.00000
10 0.17365 0.98481
20 0.34202 0.93969
30 0.50000 0.86603
40 0.64279 0.76604
50 0.76604 0.64279
60 0.86603 0.50000
70 0.93969 0.34202
80 0.98481 0.17365
90 1.00000 0.00000
100 0.98481 -0.17365
110 0.93969 -0.34202
120 0.86603 -0.50000
130 0.76604 -0.64279
140 0.64279 -0.76604
150 0.50000 -0.86603
160 0.34202 -0.93969
170 0.17365 -0.98481
180 0.00000 -1.00000
|
Note that at line 13 the c_str() method must be appended to the string filename.
File Input
The following example program provides a basic method for inputting data from a file
mydata.txt.
09prg04.cpp: Reading data from a file
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
|
// Reading data from a file
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ifstream fin("mydata.txt");
double x, sum=0.0;
for (int i=0; i<10; i++) {
fin >> x;
sum = sum + x;
}
fin.close();
cout << "The sum of all values in mydata.txt is " << sum << endl;
} |
The sum of all values in mydata.txt is 59.2
|
Note that the program assumes that there are exactly ten values in the file. If there are more or less values in the file
then the sum will not be correct (probably without warning!).
We can expand on the above basic statements adding more useful features.
For example, it is important to check that the file has been opened successfully, this can be done with the is_open() function.
Also the eof() function can be used to check if the end of the file has been reach.
Consider a file
kelvin.tmp that contains 100 lines of temperature values.
The following program reads data from the file and outputs the mean temperature to the screen.
Note that the file name is stored in a string, and the is_open() function is used to check if the file was opened succesfully.
09prg05.cpp: Reading data from a file with a check for is_open()
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
|
// Reading data from a file with a check for is_open()
#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
string filename = "kelvin.tmp";
ifstream kelvin(filename.c_str());
double k;
if (kelvin.is_open())
{
double s;
int i;
cout << "Reading data from file: " << filename << endl;
for(s = 0.0, i=0; i<100; i++, s += k )
kelvin >> k;
kelvin.close();
double mean = s/100.0;
cout << "mean of the data = " << mean << endl;
}
else
cout << "Unable to open file " << filename;
return 0;
} |
Reading data from file: kelvin.tmp
mean of the data = 412.652
|
Below 09prg05.cpp is modified
such that it reads temperatures in Kelvin (K) from the file
kelvin.tmp, converts them
to degrees celsius (C) according to K = C + 273.15 and writes degrees celsius values to an another file
degrees.tmp.
However, in this case we assume that we do not know how many lines of data the file kelvin.tmp contains.
09prg06.cpp: Reading an unknown number of lines of data from a file
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
|
// Reading an unknown number of lines of data from a file
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int main ()
{
string source = "kelvin.tmp"; // source file
string target = "degrees.tmp"; // target file
ifstream kelvin(source.c_str());
ofstream degrees(target.c_str());
// Check if files can be opened
if ( ! kelvin.is_open() ) {
cout << "Unable to open file " << source << endl;
return 1; // stop the execuation of the program
}
if ( ! degrees.is_open() ) {
cout << "Unable to open file " << target << endl;
return 1;
}
double s = 0.0, mean, k, c;
int n = 0;
cout << "Reading data from file: " << source << endl;
cout << "Writing data to file: " << target << endl;
// Start an infinte loop
while(1)
{
kelvin >> k; // Read a line from source file
if( kelvin.eof() ) break; // Do you reach end of file?
c = k + 273.15; // Convert
degrees << setw(8) << fixed // Write to the target file
<< setprecision(2)
<< c << endl;
s += k; // Sum the temperatures
n++; // Count number of lines
} // Goto next line in the file
kelvin.close(); // Close the files
degrees.close();
mean = s/n;
cout << "number of data = " << n << endl;
cout << "mean of the data = " << mean << endl;
return 0;
} |
Reading data from file: kelvin.tmp
Writing data to file: degrees.tmp
number of data = 100
mean of the data = 412.652
|
Notes:
- lines 16 and 20: the symbol "!" is the logical NOT operator.
- lines 18 and 22: an integer 1 is returned to the operating system indicating that an error occured.
- line 34 attempts to read data, then line 35 breaks out of the read loop if the EOF condition is true.
9.5 Examples
[NEEDS EXAMPLES]
9.6 Exercises
- What is a stream?
- Why is cout called a stream?
- What is a manipulator?
- What does the ios::ate argument do?
- What does the method eof() do?
- Modify 09prg05.cpp such that it also outputs the minimum
and maximium values of the temperatures recorded in the file kelvin.tmp.
- Write a program that outputs to a file called numbers.dat the integer numbers 1 to 100 and their square-roots.
The output should be formatted as illustrated below.
1234567890
1 1.000
2 1.414
3 1.732
. .
. .
. .
100 10.000
|
- The file gravity.dat contains the following measured values for the acceleration due to gravity.
Write a program to input the data into an array and output the mean value to the screen.
9.81
9.79
9.83
9.79
9.90
9.82
9.84
9.78
9.85
|
- The file student.dat contains the names and corresponding exam scores of 20 students in a class (the data is given below).
Write a program which reads the data from the file and calculates and outputs
a) the mean score of the class excluding zeros and b) the name and score of the students getting the maximum and minimum score.
UGUR 67
KADIR 72
SEMIH 00
GOZDE 73
FIRAT 30
EDA 51
FULYA 41
GULISTAN 67
EMRE 30
AHMET 76
ISMAIL 67
MELIKE 71
TANER 59
SEHER 79
ALI 90
EMIN 88
HAVVA 76
FERDA 00
MUKRIME 54
TUGBA 61
|
- What is the output of the following program?
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{
int i = 1;
while(i<=10)
cout << setw(4) << i++ << fixed
<< setw(6) << setprecision(2) << log(i)
<< setw(6) << setprecision(2) << log10(i) << endl;
return 0;
}
- What is the output of the following program?
// Program to show that the maximum power delivered to the
// load resistance R occurs when the load resistance
// matches the internal resistance r (namely R = r)
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
double R=0.0, r = 1.0e+3, Rmax = 5.0e+3;
cout << scientific << setprecision(1);
do{
double power = 100.0* R/(R+r)/(R+r);
cout << setw(9) << r << setw(9) << R
<< setw(9) << power << endl;
R += 500;
}while(R <= Rmax);
return 0;
}
|