Chapter 9
Text Files
User Defined Data Types
User Defined Header Files
9-2
Using Text Files in Your C++ Programs
1. A text file is a file containing data you wish to use in your program. A
text file does not contain any C++ declarations or statements – just the
data. Enter the CodeWarrior editor and create your text file. Save your
file with a .dat file extension. It will make things easier if your file has
any string data on a line by itself. Numeric data is easily read when you
have several items per line as white space is used to delimit the various
data items.
2. To use the file in your program you need to include the fstream header
file in your program #include<fstream>
3. The function used to read from the file requires a local variable to
represent your actual file on disk ifstream inFile You may choose any
name you like (I typically use inFile for files I am reading from and
outFile for files I am writing to).
4. You must open the file for reading with the open statement using the
variable you declared and the actual file on disk
inFile.open(“people.dat”) is the statement used to associate the
variable in your program (inFile) with an actual file on disk (people.dat).
From now on in your program when the variable name inFile is used the
program will look at the file on disk specified in the open statement. The
open statement also sets the file pointer to the top of the file.
5. To read from the file instead of the keyboard, replace the cin variable
with the variable you declared in your program. Examples:
getline(inFile,name[i]) inFile>>age[i] etc.
6. Always close the file before you exit the function that opened it.
inFile.close
7.
STUDY THE FOLLOWING PROGRAMS CAREFULLY AND
YOU SHOULD HAVE NO PROBLEMS USING TEXT FILES IN
YOUR PROGRAMS
.
// This program demonstrates the loading of an array when the number of // data items is known
#include <iostream> #include <iomanip> #include <string> #include <fstream> using namespace std;
void LoadArrays(string nm[], int ag[]); void OutputArrays(string nm[], int ag[]); void main(void)
{
string names[5]; // array of 5 names - READ from file int ages[5]; // array of 5 ages - READ from file
// call functions to read info and print contents of the arrays LoadArrays(names, ages);
OutputArrays(names, ages); }
void LoadArrays(string nm[], // array for names - OUT int ag[]) // array of ages - OUT {
ifstream inFile; // declared locally as no other fns need the file // open the file
-inFile.open("people.dat"); for(int i=0; i < 5; ++i) {
getline(inFile,nm[i]); inFile >> ag[i];
inFile.ignore(100,'\n'); }
// close the file inFile.close; }
void OutputArrays(string nm[], // array of names - IN int ag[]) // array of ages - IN {
for(int i=0; i < 5; ++i) {
// note use of length function to format output
cout << endl << nm[i] << setw(25- nm[i].length( )) << ag[i]; }
9-4
// This program reads an unknown number of elements from a file #include <iostream>
#include <iomanip> #include <string> #include <fstream> using namespace std;
void LoadArrays(string nm[], int ag[], int& ct); void OutputArrays(string nm[], int ag[], int ct); void main(void)
{
string names[25]; // array holds up to 25 names - READ from file int ages[25]; // array holds up to 25 ages - READ from file int counter; // counts array elements as the are read - CALC // initialize counter to count people as they are read from the file counter = -1;
// Call functions to load and output the arrays LoadArrays(names, ages, counter);
cout << "There are " << counter+1 << " names & ages in the file\n\n"; OutputArrays(names, ages, counter);
}
void LoadArrays(string nm[], // array of names - OUT int ag[], // array of ages - OUT
int& ct) // array location counter - INOUT {
ifstream inFile; // file variable for input file // open the file
inFile.open("people.dat"); while(!inFile.eof())
{
// increment the counter each time the loop is entered ++ct;
// note that the name of the file variable replaces cin getline(inFile,nm[ct]);
inFile >> ag[ct]; // "flush" the buffer inFile.ignore(1,'\n'); }
// close the file inFile.close; }
void OutputArrays(string nm[], // array of names - IN int ag[], // array of ages - IN
int ct) // number of items in arrays - IN {
for(int i=0; i <= ct; ++i) {
// note the use of the length function to format the output cout << endl << nm[i] << setw(25- nm[i].length( )) << ag[i]; }
Following is the datafile, people.dat, used in the previous programs. Sam Jones 55 Susie Jones 12 Sally Jones 50 Josh Jones 15 Adam Jones 78
9-6
The typedef Statement
The typedef statement is used not to create a new type but instead to give a new name to
an existing type. The data type bool is relatively new. Prior to the introduction of the
bool type we could define our own type to add readability to a program.
typedef int Boolean;
const int TRUE = 1;
const int FALSE = 0;
Boolean loopFlag; // a variable that may contain TRUE or FALSE
Although loopFlag actually contains an integer value, the program is made more clear by
using the named constants TRUE and FALSE.
Array data type example:
typedef float FloatArrayType[100];
// anything of type FloatArrayType is defined
// as a 100 element array of float values
FloatArrayType myArray;
// myArray is a variable representing a 100 element
// array of float values
Because the compiler knows the size and type of the array from the definition of the type
FloatArrayType, we can now use this type in a formal parameter list.
void LoadArray(FloatArrayType anArray);
The typedef statement allows us to create code that is more self documenting and easier
to understand.
Modified 2-dimensional array program using the typedef statement
#include <fstream.h> #include <iomanip.h> const int NUMOFROWS = 4; const int NUMOFCOLS = 5;
// declaration of a two-dimensional array data type
typedef float SalesArrayType[NUMOFROWS][NUMOFCOLS]; void LoadSalesData(SalesArrayType sale);
void PrintSalesData(SalesArrayType sale); void CalcWeeklySales(SalesArrayType sale); void main(void)
{
SalesArrayType sales;
// call function to load the arrays with the month's sales LoadSalesData(sales);
// call function to output monthly sales table PrintSalesData(sales);
// call function to sum and output weekly sales total CalcWeeklySales(sales);
}
void LoadSalesData(SalesArrayType sale) {
ifstream inFile; // open the file
inFile.open("sales.dat"); // load the array
for(int i = 0; i < NUMOFROWS; i++) { for(int j = 0; j < NUMOFCOLS; j++) { inFile >> sale[i][j]; } } inFile.close; }
void PrintSalesData(SalesArrayType sale) {
// output headings
cout << setw(45) << "Monthly Sales\n\n";
cout << "\t\t\tMonday Tuesday Wednesday Thursday Friday\n\n"; // print the array
for(int i = 0; i < NUMOFROWS; i++) {
9-8
for(int j = 0; j < NUMOFCOLS; j++) {
cout << setw(12) << sale[i][j]; }
cout << endl; }
}
void CalcWeeklySales(SalesArrayType sale {
for(int i = 0; i < NUMOFROWS; i++) {
float sum; sum = 0.0;
for(int j = 0; j < NUMOFCOLS; j++) {
sum = sum + sale[i][j]; }
cout << "\n\nSales for week " << i+1 << " = " << sum; }
Enumeration Types
Enumeration types are used primarily to add readability to a program and make it more
self documenting. Example:
enum Dogs {POODLE, COLLIE, LABRADOR, GOLDEN_RETRIEVER};
We have created a new type called Dogs and listed the elements (possible values) inside
the braces. We can now declare variables of this type.
Dogs myDog;
Dogs yourDog;
myDog = GOLDEN_RETRIEVER;
yourDog = POODLE;
yourDog = myDog;
yourDog = “COLLIE”;
// invalid
Each element has a numeric value associated with it, that is to say they are ordered. The
value of POODLE is 0, the value of COLLIE is 1, etc. This allows us to use the
relational operators when working with enumeration types. While each element has an
int value associated with it, you may not work with this type as though it was an int.
Suppose I wanted to have the value of myDog become the next value in the list.
myDog = myDog + 1;
// invalid
myDog++;
// invalid
We need to use type casting
9-10
Enumeration types may be used in switch statements and as the loop control variable in a
for loop.
For(Dogs myDog = POODLE; myDog <= GOLDEN_RETRIEVER; myDog = Dogs(myDog+1))
It is not possible to input or output an enumeration type directly. To output the value of
the members of type Dogs a switch statement is necessary.
switch(myDog)
{
case POODLE
: cout << “Poodle”;
break;
case COLLIE
: cout << “Collie”;
break;
case LABRADOR
: cout << “Labrador”;
break;
case GOLDEN_RETRIEVER
: cout << “Golden Retriever”;
break;
User Defined Header Files
We have been using the #include pre-processor directive in our programs to gain access
to routines supplied by the C++ standard libraries. It is also possible for us to create our
own files of declarations and functions that may be written and compiled once and
accessed by any program via the #include directive.
Suppose I want to declare an enumeration type called Days and make this type available
to any program that wishes to use it. Additionally, I would like to declare a data type for
an array used to hold sales figures for the week. The declarations will be stored in a file
called “myheader.h”. Any program wishing to access these declarations may do so by
using the following directive
#include “myheader.h”
Note the use of the quotation marks. The directive
#include <iostream.h>
indicates that the header file will be found in the directory with the standard C++ libraries
where the directive
#include “myheader.h”
indicates that the header file is located in the current directory (in our case, the current
project folder).
9-12
// User defined header file demonstration #include <iostream.h>
#include <iomanip.h> #include <fstream.h>
#include "myheader.h" // file is located in the project folder // Function to load the weekly sales
void LoadSales(SalesArrayType sales); // Function to output the weekly sales void OutputSales(SalesArrayType sales); void main(void)
{
// declaration of array variable using type defined in myheader.h SalesArrayType salesArray; cout.setf(ios::fixed, ios::floatfield); cout.setf(ios::showpoint); LoadSales(salesArray); OutputSales(salesArray); }
// Function to load the weekly sales void LoadSales(SalesArrayType sales) {
ifstream inFile;
inFile.open("sales.dat");
for (Days index = SUN; index <= SAT; index = Days(index + 1)) {
inFile >> sales[index]; }
inFile.close; }
// Function to output the weekly sales void OutputSales(SalesArrayType sales) {
cout << "\n\nSales for the Week\n"; cout << "---\n";
for (Days index = SUN; index <= SAT; index = Days(index + 1)) {
// recall that enum types may not be output directly switch (index)
{
case SUN : cout << "\nSunday: "; break;
case MON: cout << "\nMonday: "; break;
case TUE : cout << "\nTuesday: "; break;
case WED : cout << "\nWednesday: "; break;
case THU : cout << "\nThursday: "; break;
case FRI : cout << "\nFriday: "; break;
case SAT : cout << "\nSaturday: "; break;
}
cout << setw(8) << setprecision(2) << sales[index] << endl; }
9-14
// file myheader.h
// user defined header file to specify two user defined data types // enumeration type for days of the week
enum Days {SUN, MON, TUE, WED, THU, FRI, SAT}; // typedef for a one-dimensional array
typedef float SalesArrayType[7];
It is also possible to create header files that contain more than declarations. In the
following example there are three files used.
1. A program file containing the main function.
2. A header file (myheader.h) containing the enum and typedef statements as well as two
function prototypes.
3. A program file (myheader.cpp) containing the code for the functions specified in
myheader.h.
The actual implementation of the functions is kept separate from the header file where the
prototypes appear. Anyone wishing to use the data types and functions provided need
only see the declaration of the types and the function prototypes. There is no need for the
user to have access to the actual implementation.
// This file contains the main function
#include "myheader.h" // file is located in the project folder void main(void)
{
// declaration of array variable using type defined in myheader.h SalesArrayType salesArray;
// Calls to functions – prototypes contained in myheader.h and // implementation contained in myheader.cpp
LoadSales(salesArray); OutputSales(salesArray); }
9-16
// file myheader.h
// user defined header file to specify two user defined data types // and the prototypes for two functions to act on the array // enumeration type for days of the week
enum Days {SUN, MON, TUE, WED, THU, FRI, SAT}; // typedef for a one-dimensional array
typedef float SalesArrayType[7]; // Function to load the weekly sales void LoadSales(SalesArrayType sales); // Function to output the weekly sales void OutputSales(SalesArrayType sales);
// File myheader.cpp contains the implementation portion of myheader.h #include <iostream.h>
#include <iomanip.h> #include <fstream.h>
#include "myheader.h" // file is located in the project folder // Function to load the weekly sales
void LoadSales(SalesArrayType sales) {
ifstream inFile; inFile.open("sales.dat");
for (Days index = SUN; index <= SAT; index = Days(index + 1)) {
inFile >> sales[index]; }
inFile.close; }
// Function to output the weekly sales void OutputSales(SalesArrayType sales) {
cout.setf(ios::fixed, ios::floatfield); cout.setf(ios::showpoint);
cout << "\n\nSales for the Week\n"; cout << "---\n";
for (Days index = SUN; index <= SAT; index = Days(index + 1)) {
// recall that enum types may not be output directly switch (index)
{
case SUN : cout << "\nSunday: "; break; case MON : cout << "\nMonday: ";
break; case TUE : cout << "\nTuesday: ";
break; case WED : cout << "\nWednesday: ";
break; case THU : cout << "\nThursday: ";
break; case FRI : cout << "\nFriday: ";
break;
case SAT : cout << "\nSaturday: "; break;
}
cout << setw(8) << setprecision(2) << sales[index] << endl; }
9-18
// File myheader.cpp contains the implementation portion of myheader.h // user defined header file demonstration
#include <iostream.h> #include <iomanip.h> #include <fstream.h>
#include "myheader.h" // file is located in the project folder // Function to load the weekly sales
void LoadSales(SalesArrayType sales) {
ifstream inFile; inFile.open("sales.dat");
for (Days index = SUN; index <= SAT; index = Days(index + 1)) {
inFile >> sales[index]; }
inFile.close; }
// Function to output the weekly sales void OutputSales(SalesArrayType sales) {
cout << "\n\nSales for the Week\n"; cout << "---\n";
for (Days index = SUN; index <= SAT; index = Days(index + 1)) {
// recall that enum types may not be output directly switch (index)
{
case SUN : cout << "\nSunday: "; break; case MON : cout << "\nMonday: ";
break; case TUE : cout << "\nTuesday: ";
break; case WED : cout << "\nWednesday: ";
break; case THU : cout << "\nThursday: ";
break; case FRI : cout << "\nFriday: ";
break;
case SAT : cout << "\nSaturday: "; break;
}
cout << setw(8) << setprecision(2) << sales[index] << endl; }
Notes on User Defined Header Files
1. Make certain all related files are in the project folder.
2. You may have only one .cpp file that contains a main function listed in the Sources
section of the project.
3. The name of the .cpp file containing the implementation of the functions listed in the
header file must be listed under the Sources section of the project. Use the Add Files
option from the Project menu to add this file to the list of sources. You may
eventually have several files active under Sources but remember that ONLY ONE
may contain a main function.
9-20
Header Files Assignment
Name __________________________
Due Date _______________
1. Create a header file that contains the following:
- a typedef to define a one dimensional array of 10 integers
- the prototype for a function to load the array from a datafile
- the prototype for a function to calculate the sum of the elements in the array
- the prototype for a function to output the contents of the array
2. Create the necessary .cpp file that contains the code for the functions listed in #1.
3. Create a file that contains the main function. The file will do the following:
- call the load function
- assign to a variable called theSum the return value from the function that sums the
array
- call the output function
- output the value of theSum