| Name: _____________________ | Class: Comp 217 |
| SSN/ID: _____________________ | Section & Group: ____________ |
So far, you have read the input to your programs from the keyboard
and have written (displayed) your results on the screen. Input data read
from the keyboard and output data written to the screen are temporary and
will be lost when the program ends. In this lab, you will learn to
read from/write to a file which will remain on the hard disk until you
manually remove them. The reading from/writing to a file in a program
is usually referred to as file I/O (Input/Output).
You will use constructs called streams to read/write your data to
or from a file. Streams are the first examples of objects
introduced
in this course. An object is simply a special kind of
variable. C++
is an Object Oriented Programming (OOP) language, i.e., it has the ability
to handle objects.
In order to read from/write to a file, we need to take some precise steps. Missing any of these steps will result in failure to correctly read from/write to a file. Following are the steps that you need to go through to successfully perform the file I/O.
"Remember you cannot use a stream of type input to write to a file and vice versa"
Step (1): Include the required directives
#include <fstream> // This enables you to do file I/O #include <iosream> // For cin and cout #include <cstdlib> // To use exit(1) that terminates the program #include <string> // For string functionality using namespace std;
Step (2): Create the input/output streams
|
|
|
|
Create (declare) the streams of type input or
output to use them for reading a file or writing to a file.
|
(A)
string inp_file, out_file; (B) Create (declare) the streams of type input or output to use them for reading a file or writing to a file. ifstream inp_stream; // create an input stream type ofstream out_stream; // create an output stream type |
Step (3): Connect the input stream to an input
file/the output stream to an output file
At this point you must be most careful. If, by
mistake, you connect an out_stream to an input file, you can destroy the
input file.
|
|
|
|
For an input file we have:
inp_stream.open("input_file.txt"); // Assumes a text file named input_file.txt
// exists in the same directory on the disk
if ( inp_stream.fail() ) {
cout << "Input file opening failed. \n";
exit(1); //exit the program
}
Similarly, for an output file we have:
out_stream.open("output_file.txt");
if ( out_stream.fail() ) {
cout << "Output file opening failed. \n";
exit(1); // exit the program
}
|
For an input file we have: (A) cout << "Input the name of input file\n"; cin >> inp_file; (B)
inp_stream.open(inp_file.c_str());
if ( inp_stream.fail() ) {
cout << "Input file opening failed. \n";
exit(1); //exit the program
}
Similarly, for an output file we have:
out_stream.open(out_file.c_str());
if ( out_stream.fail() ){
cout << "Output file opening failed. \n";
exit(1); //exit the program
}
|
If you decide to append to an existing
file, use:
out_stream.open("output_file.txt", ios::app);
Step (4): Use the input stream to read from the input file/the output stream to write the output file
Declare your string variables:
string first_data, second_data;
To read:
inp_stream >> first_data >> second_data;
To write:
out_stream << first_data << second_data;
Step (5): Close the input and output files
by disconnecting the corresponding streams
inp_stream.close( );
out_stream.close( );
Note that we have used two different methods to get a file name into the program. In the method on the left hand side of the table in Steps (2) and (3), we have fixed input and/or output file names. If the file name is different, the file name within " and " must be changed and the program must be recompiled for the new changes to become effective. In the method on the right hand side of the table in Steps (2) and (3), we can ask for the file name when we run the program instead of editing and recompiling the program. This method seems to be more convenient.
The following program reads a file containing some integer values (we do not know how many values). It displays the number, the number to the power of two, and the sum up to that point. At last it displays the average of these numbers.
|
// P61.cpp - This program reads some integers from a file and displays:
// The number, number2, and the sum of all numbers read up to that point #include<iostream> #include<fstream> // Step (1) #include<cstdlib> #include<cmath> #include <string> // For string functionality using namespace std; int main( )
ifstream fin; // Step (2)-B - declaration of the stream of type input cout << "Please input the input file name \n"; //
Step (3)-A Get the file name
fin.open(input_file.c_str()); //
Step (3)-B - connect to the input file and test
cout << "\t x \t\t x^2 \t\t Current Sum
\n";
while( fin >> x) // Step
(4)-Read all numbers one-by-one to the end of the file
avg = sum/count;
fin.close( ); // Step (5)-Close the connection (close the file) return 0;
|
Every input or output file seems to have two names. The actual names, or external file, is the name of the file as it appears on your computer disk. The name of the stream used to read from/write to a file is referred to as internal file name. The internal name is actually the name of the stream that you are using to read from/write to the input/output file.
Introduction to Classes and Objects
In C++ the streams cin, cout, and
any other streams that you may declare are called objects.
You use the class ifstream to define objects of type ifstream
and class ofstream to declare objects of type ofstream.
An object is a new type of variable that allows you to include functions,
as well as data, in it. An object may include several variables and
functions of various types. In the above program, we have an object called
fin.
This object has several functions that were used in that program.
These functions are open(....), close( ), and fail( ). The functions
are called member functions. Note that you would have similar
functions for a stream of type output, but they may not have the same functionality
as they are members of a different object type. As you can see in
the above program, the member functions are called using the dot operator
(ex. fin.close( ) ). The period between the fin (calling object)
and the close( ) (member function) is referred to as the dot
operator.
Exercise 6.1
Carefully copy or cut and paste the program P61.cpp into a file called
ex61.cpp. Compile and run the program to make sure it compiles without
any error. Create a file, input.txt, and type the following 8 integers
in it: 4 4 4 4 4 4 4 4. Save the file and exit. Now, run your
program and when the program asks for the input file, type input.txt.
Your program should display an output similar to the one given below:
Please input the input file name.
input.txt
x
x^2 Current
Sum
===
=== ==========
4
16
4
4
16
8
4
16
12
4
16
16
4
16
20
4
16
24
4
16
28
4
16
32
The average of these 8 numbers is: 4
This is the correct result.
Exercise 6.2
Modify the above program such that the program writes to the output to
a file called output.txt, instead of displaying it.
A stream can be the argument to a function. The only restriction
is that any input or output must be passed to a function must be passed
as call-by-reference. Here is a modified version of P61.cpp
in which we have used a function that reads a file name and then returns
a stream, fin, that is connected to that file to the main function.
|
// P62.cpp - This program reads some integers from a file and displays:
// The number, number2, and the sum of all numbers read up to that point #include<iostream> #include<fstream> // Step (1) #include<cstdlib> #include<cmath> #include <string> // For string functionality using namespace std; void get_stream(ifstream & fin); int main( )
ifstream fin; // Step (2)-B - declaration of the stream of type input get_stream(fin); cout << "\t x \t\t x^2 \t\t Current Sum
\n";
while( fin >> x) // Step
(4)-Read all numbers one-by-one to the end of the file
avg = sum/count;
fin.close( ); // Step (5)-Close the connection (close the file) return 0;
void get_stream(ifstream &fin)
fin.open(input_file.c_str()); //
Step (3)-B - connect to the input file and test
|
Exercise 6.3
Modify the above program such that the program writes to the output file
output.txt. You need to modify the function get_stream such
that it returns two streams to the main, one for the input and the other
for the output. Call your new program ex63.cpp.
In Program P62.cpp, you read all the integers from a file and did the
required computations. In that program, you used:
while( fin >> x) { // Step
(4)-Read all numbers one-by-one to the end of the file
....
}
to do the reading. Let's see if we can use a similar technique to read a text file and display its contents. In order to do this, let's first create the following input file.
Exercise 6.4
Create a file called act64.txt and type the following text exactly
as it appears below into that file. You may cut and paste the following
10 lines into that file.
We have learned that "\n" means go to a new line
when it is used with the cout statement.
In C++, '\n' and "\n" look very similar.
In fact, in a cout statement, they both
act the same.
However, they do not mean the same in all situations.
'\n' is a value of type char and can be
stored in a variable
of type char, for example: int c = '\n';
On the other hand, "\n" is a string,
that happens to be made up of one character.
The following program uses a similar technique as in program P62.cpp to read the entire contents of the act64.txt file and to display its entire contents exactly as they appear above.
|
// P64.cpp - This program reads the entire contents of an input file
and will
// display it with the same format. #include<iostream> #include<fstream> // Step (1) #include<cstdlib> #include <string> // For string functionality using namespace std; void get_input_stream(ifstream & fin); int main( )
get_input_stream(fin); cout << "Here are the entire contents of the input file \n"; while( fin >> c) // Step (4)-Read all numbers one-by-one
to the end of the file.
cout << "\n I am done with writing the contents of the file \n"; fin.close( ); // Step (5)-Close the connection (close the file) return 0;
void get_input_stream(ifstream & fin)
fin.open(input_file.c_str()); // Step (3)-B - Connect to
the input file and test
|
Exercise 6.5
Cut and paste or carefully copy the P64.cpp program into a file called
ex65.cpp. Compile the program to make sure it compile without any
error. Then run the program and use the act64.txt file as the input
file.
Does this program produce the same exact output as shown above?
What do you think the problem is?
The get and put Member Functions
We will help you find the answer very soon. The problem is that cin does not read the white spaces, i.e., it skips blank spaces, tabs (\t), and new lines (\n). Thus, the entire text will appear in one piece without the separating spaces and new lines. In order to read and write the entire text with correct spacing, we will use a member function with the input stream. The get(c) function, where c is a character, allows us to read all characters from the file one character at a time. So to fix the above program we could simply us this function instead of the cin. We used:
while ( fin >> c) ( // Step (4)-Read all numbers one-by-one
to the end of the file
....
}
to read the contents of the file. Now we can replace the fin >> c with fin.get(c).
Exercise 6.6
Modify the ex65.cpp program by replacing fin >> c
with fin.get(c) in
the while loop. Compile, then run the program for the act63.txt input.
Call your new program ex66.cpp.
Does your program produce the correct output this time?
The member function put(c) will
do the opposite of what the member function
get(c) does.
It writes to the output stream one character at a time. To
practice with this function, in program ex66.cpp, you can replace the:
cout << c;
with
cout.put(c);
That does the same thing.
The eof Member Function
There is yet another way to read a file (any file) to the end.
The member function eof( ) can be used
with a stream of input type to determine the End-Of-File. This function
returns true when the end of the input file is reached. Thus, it
can be used in a while loop to control the looping process. In general,
you need to read one character before you check to see if the end of the
file is reached. Here is a way to use the eof(
). Please note that we haven't shown the complete program.
// Other lines of program
ifstream fin;
char next_char;
// Other lines of programs
fin.get(next_char);
while( ! fin.eof( ) )
{
cout << next_char;
// you could use cout.put(next_char) too
fin.get(next_char);
}
Exercise 6.7
Modify the program ex65.cpp by using the eof(
) to read to the end of file act63.txt
and to display its entire contents. Make sure to check that the displayed
contents are exactly the same and in the same format.
In C++, we have several predefined character functions. These
functions are listed below:
|
|
|
|
| toupper(a_character) | Returns the uppercase version of the argument character. If the character is already an uppercase, it will remain unchanged. | char c, d = 'a';
c = toupper(d); cout << c; Output is: A |
| tolower(a_character) | Returns the lowercase version of the argument character. If the character is already a lowercase, it will remain unchanged. | char c, d = 'A';
c = tolower(d); cout << c; Output is: a |
| isupper(a_character) | Returns true if the character is an uppercase letter, otherwise it returns false | char d = 'A';
cout << isupper(d); Output is: 1 Note: it can be used in an if statement |
| islower(a_character) | Returns true if the character is a lowercase letter, otherwise it returns false | char d = 'A';
cout << islower(d); Output is: 0 Note: it can be used in an if statement |
| isalpha(a_character) | Returns true if the character is one of the letters of the alphabet, otherwise it returns false | char d = 'A';
cout << isalpha(d); Output is: 1 Note: it can be used in an if statement |
| isdigit(a_character) | Returns true if the character is one of the digits '0' to '9', otherwise it returns false | char d = 'A';
cout << isdigit(d); Output is: 0 Note: it can be used in an if statement |
| isspace(a_character) | Returns true if the character is a whitespace character, blank space, newline, or tab, otherwise it returns false | char d = '\n';
cout << isspace(d); Output is: 1 Note: it can be used in an if statement |
The following program reads one character from the keyboard and will display the character in uppercase if it is lowercase and does the opposite when the character is in uppercase. If the character is a digit, it displays a message with the digit.
|
// P64.cpp - This program reads one character
from the keyboard and will
// convert it to uppercase, if it is lowercase // convert it to lowercase, if it is uppercase // display a message, if it is a digit #include<iostream>
int main( )
cout << "Enter a character
\n";
if(isalpha(c))
return 0;
|
Exercise 6.8
Modify the above program such that if one of
the whitespaces is entered, it displays a message and tells what the character
was (Note: Please recall what the extraction operator does with
whitespace). Call your new program ex68.cpp.
Hand In: This lab handout with the answers filled in attached
to a listing of your final programs
(use the enscript command from your Programming Style Sheet to print it out:
enscript -E -G -2rj -M Letter -PECT2_PS <filename> or a2ps <filename>).