Anda di halaman 1dari 16

Files

This lecture shows how to read data from files and how to write data to files. Files are stored in
secondary storage devices and make it possible to store data in a more permanent form than when it is
stored in primary memory. Data in primary memory is lost when the program comes to an end or when
the power to the CPU is switched off. However, before showing how files are used in a program, two
new variable types are introduced for storing character data and Boolean values.

14.1 Two New Variable Types

So far, we have been writing programs which manipulate only integer and floating point data.
Consequently, the types of variables used in our programs have been int, float, and double. However,
there are other kinds of data which a program needs to manipulate. In this section, we introduce two
new variable types, one for storing character data and the other one for storing Boolean values.

14.1.1 Character Variables

A character is any one of the following:

1. A letter of the alphabet. These can be lowercase letters (a, b, c, d, e, f, g, h, i, j, k, l, m, n,


o, p, q, r, s. t, u, v, w, x, y, z) or uppercase letters (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O,
P, Q, R, S, T, U, V, W, X, Y, Z). Note that a lowercase character is considered different
from its uppercase counterpart, so ‘a’ is different from ‘A’.
2. A digit (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
3. A special symbol such as +, *, =, <, $, etc.

Generally, a character is any symbol that can be obtained by pressing a key on the keyboard. In terms of
storage requirements, a byte (or 8 bits) is the amount of storage (primary memory or secondary storage)
which is needed to store one character. For example, 19 characters (which are stored in 19 bytes) are
required to store the following sentence,

Hello, how are you?

1
Note that blanks (spaces) and punctuation symbols are included in the count since they are all
valid characters.

To declare a variable to store a single character, the type char must be used. For example, the following
statement declares tempScale to be a character variable:

char tempScale;

The variable will store F to indicate that a temperature is in the Fahrenheit scale and C to indicate that
the temperature is in the Celcius scale. To store the character, C, in tempScale, the following assignment
statement must be used:

tempScale = 'C';

Note that single quotes are used in front of the character as well as after the character in the
assignment statement. This notation will always be used to refer to a single character in a program.

Just like with integer variables, we can test if a character variable is equal to a certain character using a
relational expression. For example,

if (tempScale == 'C') {
newTemp = (9.0/5.0) * temp + 32.0;
}
else
if (tempScale == 'F') {
newTemp = (temp - 32.0) * (5.0/9.0);
}
else
cout << "Temperature is in an unknown scale" << endl;

We can read a character from the keyboard and assign it to a character variable just like with integer
and floating point variables. The following program reads a temperature value from the keyboard and
assigns it to the variable, temp. It then reads a character from the keyboard and assigns it to the
character variable, tempScale. If the temperature scale is in Fahrenheit, the equivalent temperature in
Celcius is calculated and displayed. If it is in Celcius, the equivalent temperature in Fahrenheit is
calculated and displayed.

2
#include <iostream>

using namespace std;

int main ()
{
float temp;
float newTemp;
char tempScale;

cout << "Please enter temperature and scale (C or F): ";


cin >> temp;
cin >> tempScale;

if (tempScale == 'C') {
newTemp = (9.0/5.0) * temp + 32.0;
cout << "Temperature is " << temp << " Celcius" << endl;
cout << "This is equivalent to " << newTemp << " Fahrenheit" << endl;
}
else
if (tempScale == 'F') {
newTemp = (temp - 32.0) * (5.0/9.0);
cout << "Temperature is " << temp << " Fahrenheit" << endl;
cout << "This is equivalent to " << newTemp << " Celcius" << endl;
}
else
cout << "Temperature is in an unknown scale" << endl;

return 0;
}

When the program is executed, it waits for the user to type the temperature followed by a character to
indicate the temperature scale. The cin statement searches for the first non-blank character that was
typed and assigns it to tempScale. If there were only blank characters following the temperature value,
the cin statement will wait for a non-blank character to be entered before proceeding.

14.1.2 Boolean Variables

A Boolean variable can store one of two values, true or false. It is declared using the bool type. For
example, the following statement declares that found is a Boolean variable:

3
bool found;

The Boolean variable can be set to true as follows:

found = true;

Boolean variables are very useful in programming. They can be used to take note that an event has
happened, for later processing in a program. For example, suppose we wish to input a set of numbers
from the keyboard and find the sum of the numbers. We would also like to know if a certain number,
say, 23, was present in the input. The program to do so is as follows:

#include <iostream>

using namespace std;

int main ()
{
int num;
int sum;
int key;
bool found;

key = 23;
found = false;
sum = 0;

cout << "Please enter an integer (-1 to stop): ";


cin >> num;

while (num >= 0) {


sum = sum + num;

if (num == key)
found = true;

cout << "Please enter an integer (-1 to stop): ";


cin >> num;
}

cout << "The sum of the numbers is: " << sum << endl;

if (found == true)
cout << "The number " << key << " was present.";
else
cout << "The number " << key << " was not present.";

return 0;
}

In the program, the Boolean variable, found, is set to true if the value 23 is found in the input. At the end
of the loop, we can check the value of found to find out if the number 23 was present in the input:

4
if (found == true)
cout << "The number " << key << " was present.";
else
cout << "The number " << key << " was not present.";

Now, the relational expression, (found == true), evaluates to true if found is true. It evaluates to false
if found is false. However, the relational expression, (found), also evaluates to true if found is true and
evaluates to false, if found is false. Thus, the two relational expressions, (found == true), and (found)
are logically equivalent. So, the if-then-else statement above could be written as follows:

if (found)
cout << "The number " << key << " was present.";
else
cout << "The number " << key << " was not present.";

In a similar manner, it can be shown that the relational expression, (found == false) is logically
equivalent to the relational expression (!found) so these two expressions can be used interchangeably.

It should be also observed that if a Boolean variable is being used to keep a record of a certain event, it
must be set to either true or false initially. In the program above, it was initially set to false, since at the
start, the value 23 was not yet found in the input data.

Consider the following modification of the if-then-else statement within the while loop:

while (num >= 0) {


sum = sum + num;

if (num == key)
found = true;
else
found = false;

cout << "Please enter an integer (-1 to stop): ";


cin >> num;
}

In the code above, if the key (23) is present in the input, found is set to true. Otherwise, it is set to false.
However, this code will only work if the key is the last value in the input data. Suppose that the key
occurred earlier in the input data. This means that found would have been set to true. If the last data
item is not equal to key, found would be set to false, overwriting the true value previously assigned.

5
14.1.3 Functions Which Return Characters or Boolean Values

Since char and bool are variable types just like int and double, they can be used in the formal parameter
list of a function as well as the return type of a function. If the return type of a function is char, that
function must return a single character. If the return type of a function is bool, that function must return
either true or false. Consider a function, isEven(), which returns true if its formal parameter n is an even
number or false, otherwise:

bool isEven (int n) {


if (n % 2 == 0)
return true;
else
return false;
}

As mentioned in a previous lecture on functions, code that calls the isEven() function must have a
variable to receive the value returned by the function when it is called. The variable must be of the same
type as the return value, namely, bool. For example,

bool result;
.
.
.
result = isEven (num);

The result variable can then be used in other statements, for example,

if (result)
cout << num << " is even." << endl;
else
cout << num << " is odd." << endl;

It is possible to use the value returned by the isEven() function as the condition of an if-then-else
statement, without first receiving the return value in a Boolean variable. For example,

if (isEven(num))
cout << num << " is even." << endl;
else
cout << num << " is odd." << endl;

Thus, it is not always necessary to receive the value returned by a function in a separate variable.

6
14.2 Text Files

A text file is a file consisting of a set of characters typed at the keyboard. The files in which your
programs are saved are really text files since the program code consists of a set of characters which
were typed at the keyboard.

A text file can be used to save data which can be input into a program instead of having to type the data
at the keyboard every time the program is executed. A program can also send output data to a text file
instead of displaying it on the monitor.

A text file can be created using a software tool called a text editor. There are many text editors
available. All of them present a screen which can be used to type the characters to be saved to the file.
Traditionally, text files have the extension, “.txt”, e.g., Input.txt and Output.txt. All the files we will
use in this course are text files. For simplicity, the text files should be saved in the same folder as the C++
program which will be using them.

14.3 File Streams

A stream is a flow of data into or out of a program. If the flow is into a program, it is referred to as an
input stream. If the flow is out of a program, it is referred to as an output stream. When the input comes
from a file, the flow of input can be referred to as an input file stream. When the output goes to a file,
the flow of output can be referred to as an output file stream.

There are essentially two operations that a program can perform on a file: it can read data from a file or
it can write data to the file. In order to read data from a file, your program must first connect the file to
an ifstream object (short for “input file stream” object). Similarly, in order to write data to a file, your
program must first connect the file to an ofstream object (short for “output file stream” object). These
two objects can be made available to your program by adding the following line at the top:

#include <fstream>

7
So, the top of your program will contain the following lines:

#include <iostream>
#include <fstream>

using namespace std;

We will now show how to read data from a file using an ifstream object and how to write data to a file
using an ofstream object.

14.3.1 Reading Data from a File

An ifstream object must be declared using a normal variable. For example, the following code declares
inputFile to be an ifstream object:

ifstream inputFile;

Any other name can be used to declare the ifstream object (e.g., fin, inputStream, etc.).

Now that we have the ifstream object, we must connect it to the text file from which contains the values
to be input by the program. Connecting the ifstream object to the text file is called opening the file. The
ifstream object contains a function, open(), which opens the text file and connects the ifstream object to
the text file. It is called as follows:

inputfile.open("input1.txt");

The parameter “input1.txt” is the name of the text file containing the data values that will be read by
the program.

Assume that the text file contains two integer values followed by another set of integer values. Once the
file is opened, the first two values can be read and stored in two variables as follows:

int num1, num2;


.
.
.
inputFile >> num1;
inputFile >> num2;

8
As can be seen, the syntax to read values from the file is identical to the syntax for reading values from
the keyboard except that the cin stream is used for keyboard input.

Suppose we wish to read all the values from the file and find the sum of the values. How do we know
how many values there are in the file? When we were dealing with keyboard input, we used a special
value to indicate that there are no more data values in the file. We can follow a similar approach and
insert a number such as -1 as the last number in the file. The code to read all the numbers from the file
is as follows:

sum = 0;

inputFile >> num;

while (num != -1) {


sum = sum + num;
inputFile >> num;
}

cout << "The sum of the numbers in the file is " << sum << endl;

Another approach is to use the eof() function (eof stands for end-of-file). The ifstream object contains a
function, eof(), which returns true when there are no more data to be read from the associated file.
Otherwise, eof() returns false, which means that the file still has data values that can be read. The eof()
function of the ifstream object function can be called as follows:

sum = 0;

inputFile >> num;

while (inputFile.eof() == false) {


sum = sum + num;
inputFile >> num;
}
cout << "The sum of the numbers in the file is " << sum << endl;

As mentioned previously in this lecture, the relational expression (inputFile.eof() == false) is


equivalent to (!inputFile.eof()) so the latter expression can be used instead as the while condition.

After reading the data from a file, the file should be closed. This can be done using the close() function of
the ifstream object:

inputFile.close();

9
It should be mentioned that several errors can occur when reading data from a file. For example, when
connecting the ifstream object to a text file, it is possible that the text file does not exist. Before going
on to read data from the file, the program must make sure that a connection was indeed established
between the ifstream object and the input file.

The ifstream object contains a Boolean function, is_open(), which returns true if the file was successfully
opened for reading, and false, otherwise. The value returned by this function should be examined
before doing further processing on the file. For example,

if (inputFile.is_open() == false) {
cout << "Error opening input file. Aborting ...";
return 0;
}

As previously mentioned, the relational expression (inputFile.is_open() == false) is equivalent to


(!inputFile.is_open()), so the latter expression can be used instead.

The complete program for opening the file, checking if it was successfully opened, reading the first two
values, and then reading and finding the sum of the remaining values is given below.

10
#include <iostream>
#include <fstream>

using namespace std;

int main ()
{

ifstream inputFile;
int num, num1, num2;
int sum;

inputFile.open("input1.txt");

if (!inputFile.is_open()) {
cout << "Error opening input file. Aborting ...";
return 0;
}

inputFile >> num1;


inputFile >> num2;

cout << "The first value in the file is: " << num1 << endl;
cout << "The second value in the file is: " << num2 << endl;

cout << "The remaining values in the file are: " << endl;

sum = 0;

inputFile >> num;

while (!inputFile.eof()) {
sum = sum + num;
inputFile >> num;
}

cout << "The sum of the numbers in the file is " << sum << endl;

inputFile.close();

return 0;

It should be mentioned that the integer values in the file need not be separated by one space or be on
the same line. The values can be separated by as many spaces as required and can even be in different
lines of the file. The “>>” extraction operator of the ifstream will find the values, as long as the values
are present in the file.

Suppose the text file contains “garbage” between two integer values. For example, suppose it contains a
dot (.) between the values:

25 . 56

Consider what happens when the following two lines of code are executed:

11
inputFile >> num1;
inputFile >> num2;

The first statement causes 25 to be read from the file and assigned to num1. The second statement
attempts to read an integer from the file but encounters a dot. This causes the program to malfunction
and its behavior is unpredictable. So, if a program is expecting to read integer values from a file, the file
must only contain integer values.

Suppose each line of the input file contained two integer values separated by a dot, e.g.,

25 . 56
30 . 29
35 . 22

The problem of the dots can be solved in various ways. They can be manually deleted from the data in
the file. Or, a character variable can be used to read the dot before reading the second integer. For
example,

char dot;
.
.
.
inputFile >> num1;
inputFile >> dot;
inputFile >> num2;

14.3.2 Writing Data to a File

Writing data to a file is analogous to reading data from a file. An ofstream object must be declared using
a normal variable. For example, the following code declares outputFile to be an ofstream object:

ofstream outputFile;

Any other name can be used to declare the ofstream object (e.g., fout, outputStream, etc.).

Now that we have the ofstream object, we must connect it to the text file to which the program will be
writing values. Again, this is done via the open() function of the ofstream object. It is called as follows:

12
outputfile.open("output1.txt");

The parameter “output1.txt” is the name of the text file to which the program will write data.

Once the file is opened, values can be written to the file using the “<<” operator. For example, the
following statements cause the values 25 and 30 to be written to the file:

int num1, num2;


.
.
.
num1 = 25;
num2 = 30;
outputFile << num1 << endl;
outputFile << num2 << endl;

The following statements uses a for loop to generate the numbers from 1 to 20 which are stored in the
file, one per line. The for loop also calculates the sum of the numbers which is written to the file at the
end of the loop.

sum = 0;
for (i=1; i<=20; i=i+1) {
outputFile << i << endl;
sum = sum + i;
}
outputfile << "The sum of the numbers from 1 to 20 is: " << sum << endl;

After writing data to the file, the file should be closed. This can be done using the close() function of the
ofstream object:

outputFile.close();

The complete program for opening the file, checking if it was successfully opened, writing the first two
values, and then writing the numbers between 1 and 20 and their sum is given below.

13
#include <iostream>
#include <fstream>

using namespace std;

int main ()
{
ofstream outputFile;
int num1, num2;
int i, sum;

outputFile.open("output1.txt");

if (!outputFile.is_open()) {
cout << "Error opening output file. Aborting ...";
return 0;
}

num1 = 25;
num2 = 30;

outputFile << num1 << endl;


outputFile << num2 << endl;

sum = 0;
for (i=1; i<=20; i=i+1) {
outputFile << i << endl;
sum = sum + i;
}

outputFile << "The sum of the numbers from 1 to 20 is: " << sum << endl;

outputFile.close();

return 0;
}

The contents of the output1.txt file created by the program is given below:

5
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
The sum of the above numbers is: 210

14
14.4 Using Data from Different Streams

It is possible to read data from the keyboard (using cin) and also read data from a file input stream in the
same program. It is also possible to write data to a file and display some or all of that data on the
monitor (using cout).

A program can also read data from more than one file input streams. It can also write data to more than
one file output streams. Each stream must be accessed independently of the other streams using its
own ifstream object or ofstream object.

11.5 Exercises

1. A file, angles.txt, contains three angles per line, all of which are integer quantities. Write a
program which reads all the lines of data and determines the type of triangle formed by the angles
in each line of data.

2. A file, temperature.txt, contains two data items per line, a temperature value followed by the
character C or F (for Celcius or Fahrenheit). For each input line, write two output lines to the file,
output.txt, consisting of the temperature in Celcius and the equivalent temperature in Fahrenheit.

Each pair of output lines must be separated by a blank line.

3. A file, numbers.txt, contains a set of numbers terminated by -1. For each number read from the
file, calculate the amount of digits in that number and write the number and the amount of digits to
an output file, digits.txt.

4. A file, message.txt, contains a set of characters comprising a message. The message must be
modified as follows and stored in another file, coded.txt:

a. Read two characters, a and b, from message.txt. Write b and a to coded.txt. If there is only
one character, a, to be read from message.txt, write a to coded.txt.

b. Repeat (a) until there are no more characters in the file, message.txt.

15
5. A message has been stored in two files, message1.txt, and message2.txt. Recreate the original
message and store it in message.txt based on the following:

(a) Read a character from message1.txt and store it in message.txt


(b) Read a character from message2.txt and store it in message.txt
(c) Repeat (a) and (b) until there are no more characters in message1.txt and message2.txt.

16

Anda mungkin juga menyukai