Text I/O in C++

Data in a text file can be read by a text editor.

This section demonstrates how to perform simple text input and output.

Every file is placed in a directory in the file system. An absolute file name contains a file name with its complete path and drive letter. For example, c:\example\scores.txt is the abso­lute file name for the file scores.txt on the Windows operating system. Here c:\example is referred to as the directory path for the file. Absolute file names are machine dependent. On UNIX, the absolute file name may be /home/liang/example/scores.txt, where /home/liang/ example is the directory path for the file scores.txt.

A relative file name is relative to its current working directory. The complete directory path for a relative file name is omitted. For example, scores.txt is a relative file name. If its cur­rent working directory is c:\example, the absolute file name would be c:\example\scores.txt.

1. Writing Data to a File

The ofstream class can be used to write primitive data-type values, arrays, strings, and objects to a text file. Listing 13.1 demonstrates how to write data. The program creates an instance of ofstream and writes two lines to the file scores.txt. Each line consists of first name (a string), middle name initial (a character), last name (a string), and score (an integer).

Listing 13.1 TextFileOutput.cpp

1 #include <iostream>
2
#include <fstream>
3
using namespace std;
4
5
int main()
6 {

Since the ofstream class is defined in the fstream header file, line 2 includes this header file.

Line 7 creates an object, output, from the ofstream class using its no-arg constructor.

Line 10 opens a file named scores.txt for the output object. If the file does not exist, a new file is created. If the file already exists, its contents are destroyed without warning.

You can write data to the output object using the stream insertion operator (<<) in the same way that you send data to the cout object. Lines 13-16 write strings and numeric values to output, as shown in Figure 13.1.

The close() function (line 18) must be used to close the stream for the object. If this func­tion is not invoked, the data may not be saved properly in the file.

You may open an output stream using the following constructor:

ofstream output(“scores.txt”);

This statement is equivalent to

ofstream output;

output.open(“scores.txt”);

2. Reading Data from a File

The ifstream class can be used to read data from a text file. Listing 13.2 demonstrates how to read data. The program creates an instance of i fstream and reads data from the file scores.txt, which was created in the preceding example.

Listing 13.2 TextFileInput.cpp

1 #include <iostream>
2
#include <fstream>
3
#include <string>
4
using namespace std;
5
6
int main()
7 {
8    ifstream input(
“scores.txt”);
9
10   
// Read data
11    string firstName;
12   
char mi;
13    string lastName;
14   
int score;
15    input >> firstName >> mi >> lastName >> score;
16    cout << firstName <<
” ” << mi << ” ” << lastName << ” ”
17    << score << endl;
18
19    input >> firstName >> mi >> lastName >> score;
20    cout << firstName <<
” ” << mi << ” ” << lastName << ” ”
21    << score << endl;
22
23    input.close();
24
25    cout <<
“Done” << endl;
26
27   
return 0;
28 }

Since the ifstream class is defined in the fstream header file, line 2 includes this header file.

Line 8 creates an object, input, from the ifstream class for file scores.txt.

You can read data from the input object using the stream extraction operator (>>) in the same way that you read data from the cin object. Lines 15 and 19 read strings and numeric values from the input file, as shown in Figure 13.2.

The cl ose() function (line 23) is used to close the stream for the object. It is not necessary to close the input file, but doing so is a good practice in order to release the resources occupied by the file.

You may open an input stream using the following constructor:

ifstream input(“scores.txt”);

Figure 13.2   The input stream reads data from the file.

This statement is equivalent to

ifstream input;

input.open(“scores.txt”);

3. Testing File Existence

If the file does not exist when reading a file, your program will run and produce incorrect results. Can your program check whether a file exists? Yes. You can invoke the fai1() func­tion immediately after invoking the open function. If fai1() returns true, it indicates that the file does not exist.

1 // Open a file
2 input.open(“scores.txt”);
3
4
if (input.fail())
5 {
6    cout <<
“File does not exist” << endl;
7    cout <<
“Exit program” << endl;
8
9   
return 0;
10 }

4. Testing End of File

Listing 13.2 reads two lines from the data file. If you don’t know how many lines are in the file and want to read them all, how do you recognize the end of file? You can invoke the eof() function on the input object to detect it, as discussed in Listing 5.6, ReadAllData.cpp. However, this program will not work if there are extra blank characters after the last number. To understand this, let us look at the file that contains the numbers shown in Figure 13.3. Note there is an extra blank character after the last number.

If you use the following code to read all data and add the total, the last number will be added twice.

ifstream input(“score.txt”);

double sum = 0;

double number;

while (!input.eof()) // Continue if not end of file

{

input >> number; // Read data

cout << number << ” “;            // Display data

sum += number;

}

The reason for this is that when the last number 85.6 is read, the file system does not know it is the last number because there are blank characters after the last number. So, the eof() function returns false. When the program reads the number again, the eof() function returns true, but the variable number is not changed, because nothing is read from the file. The variable number still contains the value 85.6, which is added again to sum.

There are two ways to fix this problem. One is to check the eof() function right after reading a number. If the eof() function returns true, exit the loop, as shown in the follow­ing code:

ifstream input(“score.txt”);

double sum = 0;

double number;

while (!input.eof()) // Continue if not end of file

{

input >> number; // Read data

if (input.eof()) break;

cout << number << ” “;              // Display data

sum += number;

}

The other way to fix this problem is to write the code like this:

while (input >> number) // Continue to read data until it fails

{

cout << number << ” “;              // Display data

sum += number;

}

The statement input >> number is actually to invoke an operator function. Operator func­tions will be introduced in Chapter 14. This function returns an object if a number is read; oth­erwise it returns NULL. NULL is a constant value 0. C++ automatically casts it to a bool value false when it is used as a condition in a loop statement or a selection statement. If no number is read from the input stream, input >> number returns NULL and the loop terminates. Listing 13.3 gives a complete program that reads numbers from the file and displays their sum.

Listing 13.3 TestEndOfFile.cpp

1 #include <iostream>
2
#include <fstream>
3
using namespace std;
4
5
int main()
6 {
7   
// Open a file
8    ifstream input(“score.txt”);
9

10    if (input.fail())
11    {
12        cout <<
“File does not exist” << endl;
13        cout <<
“Exit program” << endl;
14       
return 0;
15    }
16
17   
double sum = 0;
18   
double number;
19   
while (input >> number) // Continue if not end of file
20    {
21        cout << number <<
” “; // Display data
22        sum += number;
23    }
24
25    input.close();
26
27    cout <<
“\nSum is ” << sum << endl;
28
29   
return 0;
30 }

The program reads data in a loop (lines 19-23). Each iteration of the loop reads one number and adds it to sum. The loop terminates when the input reaches the end of file.

5. Letting the User Enter a File name

In the preceding examples, the file names are string literals hard-coded in the program. In many cases, it is desirable to let the user enter the name of a file at runtime. Listing 13.4 gives an example that prompts the user to enter a file name and checks whether the file exists.

Listing 13.4 CheckFile.cpp

1 #include <iostream>
2
#include <fstream>
3
#include <string>
4
using namespace std;
5
6
int main()
7 {
8    string filename;
9    cout <<
“Enter a file name: “;
10   cin >> filename;
11
12   ifstream input(filename.c_str());
13
14   
if (input.fail())
15      cout << filename <<
” does not exist” << endl;
16   
else
17      cout << filename << ” exists” << endl;
18
19   
return 0;
20 }

Source: Liang Y. Daniel (2013), Introduction to programming with C++, Pearson; 3rd edition.

Leave a Reply

Your email address will not be published. Required fields are marked *