13. Applications with Files – Object-Oriented Programming with ANSI and Turbo C++

13

CHAPTER

Applications with Files

C
H
A
P
T
E
R

O
U
T
L
I
N
E
—• 13.1 Introduction
—• 13.2 File Stream Classes
—• 13.3 Steps of File Operations
—• 13.4 Checking for Errors
—• 13.5 Finding End of a File
—• 13.6 File Opening Modes
—• 13.7 File Pointers and Manipulators
—• 13.8 Manipulators with Arguments
—• 13.9 Sequential Read and Write Operations
—• 13.10 Binary and ASCII Files
—• 13.11 Random Access Operation
—• 13.12 Error Handling Functions
—• 13.13 Command Line Arguments
—• 13.14 Strstreams
—• 13.15 Sending Output to Devices

13.1 INTRODUCTION

With the advancement of information technology a great amount of information is available on Internet. Huge amount of data is processed in computer networking. The information can be uploaded or downloaded from the desktop computer. The information transfer in computer networking in day-to-day life is in the form of files. The files can be written, read, or updated depending upon the applications. The data is saved in the file on the disk. The file is an accumulation of data stored on the disk. The stored data can be retrieved or updated. The console I/O function reads data through input devices and displays on the screen. The data read through these functions are temporarily stored in variables or in arrays. The data stored vanishes when the program ends. In order to store the data permanently, we need to apply disk I/O function. The disk I/O functions are associated with disk files. These functions perform read and write operations with the file. Like other languages, C++ also provides function that allows a programmer to perform read/write operation with the file. The disk I/O functions in C++ are very different as compared to C, though the entire disk I/O functions of C can be used in C++. However, these functions are not appropriate with the object-oriented conditions.

Secondary storage devices such as floppy disks, hard disks etc. are used to store data in the form of file. The main memories of computer such as random access memory or read only memory are not used for storage of files. This is because the main memory of computer is limited and cannot hold large amount of data. Another reason is that the main memory is volatile i.e., when the computer is switched off the contents of RAM are vanished. The operating system is a set of system programs. The operating system provides programs for file management and controlling storage devices such as hard disks, floppy disks etc., as shown in Figure 13.1.

Fig. 13.1 Communication between program, file and output device

As shown in Figure 13.1, data read from keyboard are stored in variables. Variables are created in RAM (type of primary memory). On applying disk, I/O operations selected or all variables created in RAM can be stored to secondary storage devices such as hard disk or floppy disk. In Figure 13.1 floppy disk is indicated. It is also possible to read data from secondary storage devices. When data is read from such devices it is placed in the RAM and then using console I/O operations it is transferred to screen. RAM is used to hold data temporarily. The variables are used to store data during program execution and the variables are created in RAM. Hence, secondary storage device RAM plays an important role.

The file is an accumulation of data stored on the disk created by the user. The programmer assigns file name. The file names are unique and are used to identify the file. No two files can have the same name in the same directory. There are various types of files such as text files, program files, data files, executable files etc. Data files contain a combination of numbers, alphabets, symbols etc. called as data.

Data communication can be performed between program and output devices or files and program. File streams are used to carry the communication among above-mentioned devices. The stream is nothing but flow of data in bytes in sequence. If data were received from input devices in sequence then it is called as source stream and when the data were passed to output devices then it is called as destination stream. Figure 13.2 shows the input and output streams. The input stream brings data to the program and the output stream collects data from the program. In this way, input stream extracts data from the file and transfers it to the program while the output stream stores the data into the file provided by the program.

Fig. 13.2 Input and output streams

13.2 FILE STREAM CLASSES

Stream is nothing but flow of data. In object-oriented programming the streams are controlled using the classes. The operations with the files are mainly of two types. They are read and write. C++ provides various classes as shown in Figure 13.3 to perform these operations. The ios class is the base class. All other classes are derived from the ios class. These classes contain several member functions that perform input and output operations. The streambuf class has low-level routines for controlling data buffer.

Fig. 13.3 iostream class summary

The istream and ostream classes control input and output functions respectively. The ios is the base class of these two classes. The member functions of these classes handle formatted and unformatted operations (for more details about formatted and unformatted functions please refer to Chapter “INPUT and OUTPUT in C++”). The functions get( ), getline( ), read( ) and overloaded extraction operators (>>) are defined in the istream class. The functions put( ), write( ) and overloaded insertion operators (<<) are defined in the ostream class.

The iostream class is also a derived class. It is derived from istream and ostream classes. There are also another three useful derived classes. They are istream_withassign, ostream_withassign, and istream_withassign. They are derived from istream, ostream, and iostream classes, respectively.

The classes ifstream and ofstream are derived from istream and ostream respectively. These classes handle input and output with the disk files. The header file fstream.h contains declaration of ifstream, ofstream and fstream classes including iostream.h file. This file should be included in the program while doing disk I/O operations.

THE FILEBUF Filebuf accomplishes input and output operations with files. The streambuf class does not organize streams for input or output operations. The derived classes of streambuf perform these operations. It also arranges a space for keeping input data and for sending output. The I/O functions of classes istream and ostream invoke the filebuf functions to perform the insertion or extraction on the streams. It holds constant openprot used in function open( ) and close( ) as a member.

THE FSTREAMBASE The fstreambase acts as a base class for fstream, ifstream, and ofstream. The functions such as open( ) and close( ) are defined in fstreambase.

THE IFSTREAM This class is derived from fstreambase and istream by multiple inheritance. It can access the member functions such as get ( ), getline ( ), seekg ( ), tellg ( ) and read ( ). It allows input operations and provides open( ) function with default input mode.

THE OFSTREAM This class is derived from fstreambase and ostream classes. It can access the member functions such as put( ), seekp( ), write( ) and tellp( ). It allows output operations and provides member function open( ) with default output mode.

THE FSTREAM Allows simultaneous input and output operations on a filebuf. The member functions of base classes istream and ostream start the input and output. For example, fstream invokes the member function istream::getline( ) to read characters from the file. It provides open( ) function with default input mode.

13.3 STEPS OF FILE OPERATIONS

Before performing file operations, it is necessary to create a file. Operation of a file involves the following basic activities:

■ File name

■ Opening file

■ Reading or writing the file (File processing)

■ Detecting errors

■ Closing the file

The file name can be a sequence of characters, called as a string. Strings are always declared with character array. Using file name a file is recognized. The length of file name depends on the operating system, for example, WINDOWS-98 supports long file names whereas MS-DOS supports only eight characters. A file name also contains extension of three characters. The file name should not be device name such as LPT1, CON etc. The list of device name is given in Table 13.6. You might have observed the .cpp extension to the C++ program file name separated by dot (.). The extension is optional. The following file names are valid in MS-DOS and WINDOWS-98 operating systems.

   data.dbf      // extension is .dbf
   tc.exe        // extension is .exe
   Prg.cpp       // extension is .cpp
   Prg.exe       // extension is .exe
   Prg.obj       // extension is .obj
   Marks         // without extension

The first step in the disk file I/O operation is creation of a file stream object and connecting it with the file name. The classes ifstream, ofstream, and fstream can be used for creating file stream defined in the header file fstream.h. The selection of the class is according to the operation that is to be carried out with the file. The operation may be read or write. There are two methods for opening of a file.

Constructor of the class

Member function open( )

(1) Constructor of the Class

When objects are created, constructor is automatically executed and objects are initialized. In the same way, the file stream object is created using suitable class and it is initialized with the file name. The constructor itself uses the file name as the first argument and opens the file. The class ofstream creates output stream objects and ifstream creates input stream objects.

Consider the following examples:

(i) ofstream out (“text”);

(ii) ifstream in (“list”);

In statement (i), out is an object of the class ofstream and file name text is opened and data can be written to this file. The file name text is connected with the object out. Similarly, in statement (ii), in is an object of the class ifstream. The file list is opened for input and connected with the object in. It is also valid to use same name for input and output operations.

It is possible to use these file objects in program statements like stream objects. Consider the following statements:

cout<<“One Two Three”;

The above statement displays the given string on the screen.

out<<“One Two Three”;

The above statement writes the specified string into the file pointed by the object out as shown in Figure 13.4. The insertion operator << has been overloaded appropriately in the ostream class to write data to appropriate stream.

Fig. 13.4 Interaction between fstream object and disk file

Consider the following statements:

out<<“One Two Three”;   // Write string to the file

out<<age;                           // Write contents of variable

out<<5000;                        // Write 5000 to file

out<<’A’;                            // Write character ‘A’ to file

out<<123.14;                      // Write 123.14 to file

out<<123.34<<endl<<5000<<’A’; //Multiple values in one statement

In the last statement we have separated each value using endl manipulator. It is essential because when we stored values such as 15 and 123.34 they are stored in the file as strings i.e., 123.34 would be stored as ‘1’,’2’,’3’,’.’, ‘3’,’4’.

The value 123.34 requires four bytes but when stored in a file occupies six bytes. When we need to store more numeric values more bytes are occupied and file size is increased. Every data item must be separated by delimiter. This is essential because during read operation, the extraction operator cannot determine where one number is ending and another is beginning. The same problem can be observed while reading strings. The above limitation can be overcome using binary file operation that is discussed later in the same chapter.

Similar are the following statements:

in>>string;    // Reads string from the file where string is a character array

in>>num;         // Reads number from the file where num is an integer variable

In the above statements, the object in reads data from the file associated with it as shown in Figure 13.5. For reading data from a file we have to create an object of ifstream class. The new line character ( “\n” ) inserted at the end of every line helps the overloaded operator to separate the various items stored in the file. When numbers are read back from file they are converted into their binary format.

Fig. 13.5 Interaction between ifstream object and disk file

13.1 Write a program to open an output file using fstream class.

# include <fstream.h>
# include <conio.h>

int main ( )
{
    clrscr( );
    ofstream out("text");
    out <<"One Two Three Four\n";
    out << "1   2   3   4";
    out <<"\n** The End ** ";
    return 0;
}

Explanation: In the above program, the statement ofstream out(“text”) text is opened and connected with the object out.

           Use of object out

out <<“One Two Three Four \n”;

out << “1   2   3   4”;

out <<“\n** The End ** ”;

The above statements write data (enclosed in quotation marks) to the file pointed by the object out i.e., text. The operator << is an insertion operator and writes the data in the file named text. The contents of the file can be seen by the user and it appears as follows:

Contents of the file text

One Two Three Four

1   2   3   4

** The End **

While opening a file for writing operations the user should give the new file name. If the given file already exists, its contents are erased and treated as a new file.

13.2 Write a program to read data from file using object of ifstream class.

# include <fstream.h>
# include <conio.h>

int main ( )
{
  clrscr( );
  char *n;
  ifstream in("text");    // Opens a file in read mode
  in >>n;                 // Reads string from file
  cout<<n <<" ";          // Displays string to the console
  in >>n ;
  cout<<n <<" ";
  in >>n ;
  cout<<n <<" ";
  return 0;
}

OUTPUT
One Two Three

Explanation: In the above program, the statement ifstream in ( “text” ) is opened and connected with the object in. The statement in >>n reads data from file and assigns it to the variable followed by the (>>) extraction operator. Here, the variable *n is a character pointer. If numeric value is read using character type, data cannot be used for arithmetic operations. If character type data is read using numeric type variable, ASCII values of character read will be displayed. Hence, the variable type should match with data type. The statement cout<<n <<” ”; displays the data stored in variable n.

In the above programs, the file associated with the objects, are automatically closed when the stream object goes out of scope. In order to explicitly close the file following statement is used:

Closing of files

out.close( );

in.close( );

Here, out is an object and close( ) is a member function that closes the file connected with the object out. Similarly, file associated with object in is closed by the member function close( ).

13.3 Write a program to write and read text in a file. Use ofstream and ifstream classes.

# include <fstream.h>
# include <conio.h>


int main ( )
{
  clrscr( );
  char name[15];
  int age;
  ofstream out("text");
  cout <<"\n Name : ";
  cin >>name;
  cout <<"Age   : ";
  cin>>age;
  out<<name<<"\t";
  out<<age <<"\n";
  out.close( );    // File is closed


  ifstream in ("text");
  in>>name;
  in>>age;
  cout <<"\nName\t: "<<name<<"\n";
  cout <<"Age     : "<<age;
  in.close( );
  return 0;
}

OUTPUT
Name : Sameer
Age : 24
Name : Sameer
Age : 24

Explanation: The above program, is a combination of the last two programs. The out is an object of ofstream class and it is linked with the output file text. The data entered by the user is written in the file text. The close( ) function closes the file associated with the object out. Again, the same file is opened by in object of class ifstream for reading purpose. The data recently written is read and displayed on the screen. Thus, in a program both write and read operations are performed. The use of function close( ) is essential to change the mode of the file. In case if a file is not closed and again an attempt is made to open it in another mode, no compile time error is generated. However, the result will not be satisfactory.

(2) The open( ) Function

In the last few programs, we have studied how files could be opened for reading and writing using constructors. Now the second approach can be used with open( ) function. The function open( ) is used to open a file. The open( ) function uses the stream object. The open( ) function has two arguments. First is file name and second is the mode. The mode specifies the purpose of opening a file i.e., read, write, append etc. The details are discussed in section 13.5. In the following examples, default mode is considered. The default values for ifstream is (ios:: in), reading only and fstream is (ios : : out), writing only.

(A) Opening file for write operation

      ofstream out;           // Creates stream object out

     out.open (“marks.dbf”);  // Opens file and links with the object out

     out.close ( )                                      // Closes the file pointed by the object out

    out.open (“result.dbf”)          // Opens another file

(B) Opening file for read operation

     ifstream in;                                  // Creates stream object in

     in.open (“ marks.dbf”);      // Opens file and links with the object in

     in.close( ) ;                                // Closes the file pointed by object in

     in.open (“result.dbf”);    // Opens another file

13.4 Write a program to open multiple files for writing and reading purposes. Use open( ) function.

# include <fstream.h>
# include <conio.h>


int main ( )
{
  clrscr( );
  ofstream out;


  // Writing data //


  out.open ("months");   // Opens file
  out<<"March\n";        // Writes string to the f ile

  out<<"April\n";
  out <<"June\n";
  out.close( );           // Closes the file
  out.open ("days");     // Opens another file
  out <<"31\n";
  out <<"30\n";
  out <<"30\n";
  out.close( );           // closes the file


// reading data //


# define T 20


  char text[T];
  ifstream in;
  in.open ("months");   // opens file for reading
  cout <<"\nMonth Names \n";


  while (in)
{
     in.getline(text,T);
     cout<<text<<"\n";
}


  in.close( );


  in.open ("days");
cout <<"\nDays \n";
while (in)
{
     in.getline(text,T);
     cout<<text<<"\n";
}


  in.close( );
  return 0;
}

OUTPUT

Month Names
March
April
June

Days
31
30
30

Explanation: In the above program, out is an object of ofstream class. The object out is used with open( ) function to open files for write operation. Two files are opened i.e., months and days. Month names are written in file months and number of days is written in the file days. The data is written in the files one after another. The same object is used for both the files; hence, it is necessary to close previously linked file with the object before opening new file. In this program, month file is opened first and after closing it the days file is opened. The files are closed using the function close( ). The same procedure is implemented for opening the same files for reading purpose. When end of file is reached, the while loop terminates.

Fig. 13.6 Stream objects with multiple files

As shown in Figure 13.6 above the out object opens months and days file one after another for writing. The object in opens these files for reading. Before opening next file, the previously associated file with the object is closed. A single object cannot open multiple files simultaneously.

13.4 CHECKING FOR ERRORS

Until now, we carried out the file operations without thinking whether it is performed successfully or not. If any fault occurs during file operation, fault cannot be detected. Various errors can be made by the user while performing file operation. Such errors must be reported in the program to avoid further program failure. When the user attempts to read file that does not exist or opens a read-only file for writing purpose, in such situations operation fails. Such errors must be reported and proper actions have to be taken before further operations.

The ! (Logical negation operator) overloaded operator is useful for detecting the errors. It is a unary operator and in short it is called as not operator. The ( ! ) not operator can be used with object of stream classes. This operator returns non-zero value if stream error is found during operation. Consider the following program.

13.5 Write a program to check whether the file is successfully opened or not.

# include <fstream.h>
# include <constream.h>

void main ( )
{
  clrscr( );
  ifstream in ("text");


  if (!in)  cerr <<"\n File is not opened "<<in;
  else      cerr <<"\n file is  opened "<<in;
}

OUTPUT

File is opened 0x8f15ffd2

Explanation: In the above program, an existing file “text” is opened for reading. The file is opened successfully. Hence, no error is generated. The if( ) statement checks the contents in objects using the following statement if (! in) . The value of object is 0x8f15ffd2. In case the operation fails the value of object in would be 0x8f160000.

13.6 Write a program to detect error in file operation using ! operator.

# include <fstream.h>
# include <constream.h>
# include <iomanip.h>


main ( )
{
     clrscr( );
     char c,  f_name[10];
     cout <<"\n Enter file name : ";
     cin>>f_name;


     ifstream in(f_name);


     if (!in)
  {
     cerr<<" Error in  opening file "<<f_name<<endl;
     return 1;
  }


  in>>resetiosflags(ios::skipws);

  while (in)

  {
     in>>c;
     cout<<c;
  }
     return 0;
}

OUTPUT

Enter file name : TEXT
One Two Three Four
1  2  3  4
** The End **

Explanation: In the above program, using constructor of a class ifstream a file is opened. The file that is to be opened is entered by the user during program execution. If the file does not exist, the ifstream object (in) contains 0. The if( ) statement checks the value of object in and if operation fails a message will be displayed and program is terminated. In case the file exists then using while ( ) loop, contents of file is read one character at a time and displayed on the screen. You can observe use of not operator with object in if ( ) and while ( ) statement. If the statement in>>resetiosflags (ios::skipws); is removed the contents of file would be displayed without space in one line. The operator >> ignores white space character. Consider the following statement:

With not operator

if (!in)
{
    statement1;
    else
    statement2;
}

The not operator is used in association with the object. It is also possible to perform an operation without the use of not operator. The statement would be as follows and it works opposite as compared to the above statement.

Without not operator

if (in)
{
    statement1;
    else
    statement2;
}

13.5 FINDING END OF A FILE

While reading a data from a file, it is necessary to find where the file ends i.e., end of file. The programmer cannot predict the end of file. In a program while reading the file, if the program does not detect end of file, the program drops in an infinite loop. To avoid this, it is necessary to provide correct instruction to the program that detects the end of file. Thus, when end of file is detected, the process of reading data can be easily terminated. The eof( ) member function is used for this purpose. The eof ( ) stands for end of file. It is an instruction given to the program by the operating system that end of file is reached. It checks the ios::eofbit in the ios::state. The eof( ) function returns non-zero value when end of file is detected, otherwise zero.

13.7 Write a program to read and display contents of file. Use eof( ) function.

# include <fstream.h>
# include <constream.h>
# include <iomanip.h>


 main ( )
 {
     clrscr( );
     char c,  f_name[10];
     cout <<"\n Enter file name : ";
     cin>>f_name;


  ifstream in(f_name);


  if (!in)
  {
     cerr<<" Error in  opening file "<<f_name<<endl;
     return 1;
  }


  while (in.eof( )==0)
  {
     in.get(c);
     cout<<c;
  }


  return 0;
}

OUTPUT

Enter file name : text

Programming with ANSI and TurboC

Explanation: > The above program is same as the previous one. Here, the member function eof( ) is used in the if( ) statement. The program displays the contents of file “text.” While specifying a file name for reading purpose, be sure it must exist.

13.8 Write a program to detect end of file using function eof( ); Display the values returned by the eof( ) function.

# include <fstream.h>
# include <constream.h>
# include <iomanip.h>


 main ( )
 {
     clrscr( );
     char c;
     ifstream in("text");


  while (in.eof( )==0)
  {
     in.get(c);
     cout <<in.eof( );
  }


  return 0;
}

OUTPUT

00000000000000000000000000000000000000000000000001

Explanation: As explained earlier, the eof( ) returns one when end of file is found, otherwise zero. Thus, until it returns zero, the program continues to read data from file and when end of file is detected, the reading routine is terminated and one is displayed. In the above program, the while( ) loop checks return value of eof( ) function. The codes executed when eof( ) function is called is given next.

  ios::operator void *( )
  {
  return fail( ) ? 0 : this;
}

The above function converts an ifstream object into a void pointer. It also invokes ios::fail ( ) function, which is as follows:

  int  fail ( )
{
  return & (failbit | badbit | hardfail):
}

The above function returns non-zero file when end of file is not encountered. The function returns address of object using this pointer. Zero is returned when end of file is reached. The while( ) or if( ) statement checks whether the value is zero or non-zero (address of object ). Here, zero means false and non-zero means true. The details of the above functions are discussed later in the same chapter.

13.6 FILE OPENING MODES

In previous examples we have learnt how to open files using constructor and open( ) function by using the objects of ifstream and ofstream classes. The opening of file also involves several modes depending upon operation to be carried out with the file. The open( ) function has two arguments as given below:

Syntax of open( ) function

object.open ( “file_ name”, mode);

Here object is a stream object, followed by open( ) function. The bracket of open function contains two parameters. The first parameter is name of the file and second is mode in which file is to be opened. In the absence of mode parameter default parameter is considered. The file mode parameters are given in Table 13.1.

Table 13.1 File modes

Mode parameter Operation
ios::app Adds data at the end of file
ios::ate After opening character pointer goes to the end of file
ios:: binary Binary file
ios::in Opens file for reading operation
ios::nocreate Open unsuccessful if the file does not exist
ios::noreplace Open files if its already present
ios::out Open files for writing operation
ios::trunc Erases the file contents if the file is present

(1) The mode ios::out and ios::trunc are the same. When ios::out is used, the contents of specified file (if present) will be deleted (truncated). The file is treated as a new file.

(2) When file is opened using ios:app and ios::ate modes, the character pointer is set to end of the file. The ios:: app lets the user to add data at the end of file whereas ios:ate allows user to add or update data anywhere in the file. If the given file does not exist, new file is created. The mode ios::app is applicable to the output file only.

(3) The ifstream creates input stream and ofstream creates output stream. Hence, it is not compulsory to give mode parameters.

(4) While creating an object of fstream class, the programmer should provide the mode parameter. The fstream class does not have default mode.

(5) The file can be opened with one or more mode parameters. When more than one parameters are necessary, bitwise or operator separates them. The following statement opens a file for appending. It does not create a new file if the specified file is not present.

File opening with multiple attributes

out.open (“filel”, ios::app | ios:: nocreate)

13.9 Write a program to open a file for writing and store float numbers in it.

# include <fstream.h>
# include <iomanip.h>


void main ( )
{
     float a=784.52, b=99.45,c =12.125;
     ofstream out ("float.txt",ios::trunc);
     out<<setw(10)<<a<<endl;
     out<<setw(10)<<b<<endl;
     out<<setw(10)<<c<<endl;
}

Explanation: In the above program, the file “float.txt” is opened. If the file already exists, its contents are truncated. The three float numbers are written in the file.

13.10 Write a program to open a file in binary mode. Write and read the data.

# include <fstream.h>
# include <conio.h>


int main ( )
{
     clrscr( );
     ofstream out;
     char data[32];

     out.open ("text",ios::out | ios::binary);
     cout <<"\n Enter text  "<<endl;
     cin.getline(data,32);
     out <<data;
     out.close( );
     ifstream in;
     in.open("text", ios::in | ios::binary);
     cout <<endl<<"Contents of the file \n";
     char ch;
     while (in.eof( )==0)
  {
     ch= in.get( );
     cout<<ch;
  }
  return 0;
}

OUTPUT
Programming In ANSI and TURBO-C
Contents of the file
Programming In ANSI and TURBO-C

Explanation: The above program is the same as the last one. The only difference is that files are opened here in binary mode.

13.7 FILE POINTERS AND MANIPULATORS

All file objects hold two file pointers associated with the file. These two file pointers provide two integer values. These integer values indicate exact position of file pointers in number of bytes in the file. The read or write operations are carried out at the location pointed by these file pointers .One of them is called as get pointer (input pointer) and the second one is called as put pointer (output pointer). During reading and writing operations with files, these file pointers are shifted from one location to another location in the file. The (input) get pointer helps in reading the file from the given location and the output pointer helps for writing data in the file at specified location. When read and write operations are carried out, respective pointer is moved.

While file is opened for reading or writing operation, the respective file pointer, input or output is by default set at the beginning of the file. This makes possible for performing read or write operation from the beginning of file. The programmer need not explicitly set the file pointers at the beginning of files. To explicitly set the file pointer at the specified position, the file stream classes provide following functions:

Read Mode When a file is opened in read mode, the get pointer is set at the beginning of the file as shown in Figure 13.7. Hence, it is possible to read the file from the first character of the file.

Fig. 13.7 Status of get pointer in read mode

Write Mode When a file is opened in write mode, the put pointer is set at the beginning of the file as shown in Figure 13.8. Thus, it allows write operation from beginning of the file. In case the specified file already exists, its contents will be deleted.

Fig. 13.8 Status of put pointer in write mode

Append Mode This mode allows to add data at the end of file. When file is opened in append mode, the output pointer is set at the end of file as shown in Figure 13.7. Hence, it is possible to write data at the end of file. In case the specified file already exists, new file is created, and the output is set at the beginning of the file. When a pre-existing file is successfully opened in append mode, its contents remain safe and new data is appended at the end of file.

Fig. 13.9 Status of put pointer in append mode

C++ has four functions for setting of pointers during file operation. The position of curser in file can be changed using these functions. These functions are described in Table 13.2.

Table 13.2File pointer handling functions

 

Function Uses Remark
seekg( ) Shifts input (get) pointer to a given location. Member of ifstream class
seekp( ) Shifts output (put) pointer to a given location. Member of ofstream class
tellg( ) Provides the present position of the input pointer. Member of ifstream class
tellp( ) Provides the present position of the output pointer. Member of ofstream class

As given in Table 13.2 the seekg( ) and tellg( ) are member functions of ifstream class. The functions seekp( ) and tellp( ) are member functions of ofstream class. All the above four functions are present in the class fstream. The class fstream is derived from ifstream and ofstream classes. Hence, this class supports both input and output modes as shown in Figure 13.10. The seekp( ) and tellp( ) works with put pointer and tellg( ) and seekg( ) works with get pointer.

Fig. 13.10 Derivation of fstream class

Now consider the following examples.

13.11 Write a program to append a file.

# include <fstream.h>
# include <conio.h>


int main ( )
{
     clrscr( );
     ofstream out;
     char data[25];


     out.open ("text",ios::out);
     cout <<"\n Enter text  "<<endl;

     cin.getline(data,25);
     out <<data;
     out.close( );


     out.open ("text", ios::app );
     cout <<"\n Again Enter text "<<endl;
     cin.getline (data,25);
     out<<data;
     out.close( );


     ifstream in;
     in.open("text", ios::in);
     cout <<endl<<"Contents of the file \n";


     while (in.eof( )==0)
  {
     in>>data;
     cout<<data;
  }
return 0;
}

OUTPUT

Enter text
C-PLUS-

Again Enter text
PLUS

Contents of the file
C-PLUS-PLUS

Explanation: In the above program, the file text is opened for writing i.e., output. The text read through the keyboard is written in the file. The close( ) function closes the file. Once more, the same file is opened in append mode and data entered through the keyboard is appended at the end of file i.e., after previous text. The append mode allows the programmer to write data at the end of file. The close( ) function closes the file. The same file is opened using the object of ifstream class for reading purpose. The while loop is executed until the end of file is detected. The statements within the while loop reads text from file and displays it on the screen.

13.12 Write a program to read contents of the file. Display the position of the get pointer.

# include <fstream.h>
# include <conio.h>

int main ( )
{
  clrscr( );
  ofstream out;
  char data[32];

  out.open ("text",ios::out);
  cout <<"\n Enter text  "<<endl;
  cin.getline(data,32);
  out <<data;
  out.close( );

  ifstream in;
  in.open("text", ios::in);
  cout <<endl<<"Contents of the file \n";
  int r;

     while (in.eof( )==0)
  {
     in>>data;
     cout<<data;
     r=in.tellg( );
     cout <<" ("<<r <<")";
  }
return 0;
}

OUTPUT
Enter text
Programming In ANSI and TURBO-C

Contents of the file
Programming (11)In (14)ANSI (19)and (23)TURBO-C (31)

Explanation: The above program is same as the previous one. In addition here, the function tellg ( ) is used. This function returns current file pointer position in number of bytes from beginning of the file. The number shown in brackets in output specifies position of file pointer from the beginning of file. The same program is illustrated below using binary mode.

13.8 MANIPULATORS WITH ARGUMENTS

The seekp( ) and seekg( ) functions can be used with two arguments. Their formats with two arguments follows below:

seekg ( offset, pre_position);

seekp ( offset,pre_position);

The first argument offset specifies the number of bytes the file pointer is to be shifted from the argument pre_position of the pointer. The offset must be a positive or negative number. The positive number moves the pointer in forward direction whereas negative number moves the pointer in backward direction. The pre_position argument may have one of the following values.

ios::beg   Beginning of the file

ios::cur   Current position of the file pointer

ios::end   End of the file

Figure 13.11 shows status of pre_position arguments.

Fig. 13.11 Status of pre_position arguments

In the above figure, status of ios::beg and ios::end is shown. The status ios::cur cannot be shown like ios::beg or ios::end. The ios::cur means present position of file pointer. The ios::beg and ios::end may be referred as ios::cur. Suppose the file pointer is in the middle of file and you want to read the file from the beginning, then you can set the file pointer at the beginning using ios::beg. However, if you want to read the file from current position, you can use the option ios::cur.

The seekg( ) function shifts the associated file’s input (get) file pointer. The seekp( ) function shifts the associated file’s output (put) file pointer. Table 13.3 describes few pointer offsets and their working.

Table 13.3 File pointer with its arguments

Seek option Working
in.seekg (0,ios :: beg) Go to the beginning of file
in.seekg (0,ios :: cur) Rest at the current position
in.seekg (0,ios ::end) Go to the end of file
in.seekg (n,ios :: beg) Shifts file pointer to n+1 byte in the file
in.seekg (n,ios :: cur) Go front by n byte from current position
in.seekg (-n,ios :: cur) Go back by n bytes from the present position
in.seekg (-n,ios::end) Go back by n bytes from the end of file

In Table 13.3, in is an object of class ifstream class.

13.13 Write a program to write text in the file. Read the text from the file from end of file. Display the contents of file in reverse order.

# include <fstream.h>
# include <conio.h>


int main ( )
{
  clrscr( );
  ofstream out;
  char data[25];
  out.open ("text",ios::out);
  cout <<"\n Enter text  "<<endl;
  cin.getline(data,25);
  out <<data;
  out.close( );


  ifstream in;
  in.open("text", ios::in);
  cout <<endl<<"Reverse Contents of the file \n";
  in.seekg(0,ios::end);
  int  m=in.tellg( );
  char ch;


for (int i=1;i<=m;i++)
{
     in.seekg(-i,ios::end);
     in>>ch;
     cout<<ch;
}
return 0;
}

OUTPUT

Enter text
Visual_C_+_+

Reverse Contents of the file
+_+_C_lausiV

Explanation: In the program, text file is opened in output mode and string entered is written to the file. Again the same file is opened for reading purpose. The statement in.seekg (0,ios::end); moves the get pointer at the end of file. The tellg( ) function returns the current position of the file pointer in the file. Hence, file pointer is set to the end of file. The tellg( ) returns the number of last byte i.e., size of the file in bytes and it is stored in the integer variable m. The for loop executes from 1 to m. The statement in.seekg(-i, ios::end) reads ith byte from the end of file. The statement in>>ch reads the character from file indicated by the file pointer. The cout statement displays the read character on the screen. Thus, the contents of the file displayed is in reverse order.

13.14 Write a program to enter a text and again enter a text and replace the first word of the first text with the second text. Display the contents of the file.

# include <fstream.h>
# include <conio.h>


int main ( )
{
  clrscr( );
  ofstream out;
  char data[25];


  out.open ("text",ios::out);
  cout <<"\n Enter text  "<<endl;
  cin.getline(data,25);
  out <<data;


  out.seekp(0,ios::beg);
  cout<<"\nEnter text to replace the first word of first text:";
  cin.getline(data,25);
  out<<data;
  out.close( );


  ifstream in;
  in.open("text", ios::in);
  cout <<endl<<"Contents of the file \n";


  while (in.eof( )!=1)
  { in>>data;
     cout<<data;   }

return 0;
}

OUTPUT

Enter text
Visual C++

Enter text to replace the first word of first text : Turbo-

Contents of the file
Turbo-C++

Explanation: In the above program, text is entered and written in the file text. This process is explained in previous examples. Here again, the statement out.seekp(0,ios::beg) sets the file pointer (put pointer) at the beginning of file. Again, text is entered and written at the current file pointer position. The previous text is overwritten.

13.9 SEQUENTIAL READ AND WRITE OPERATIONS

C++ allows file manipulation command to access file sequentially or randomly. The data of sequential file must be accessed sequentially i.e., one character at a time. In order to access nth number of bytes, all previous characters are read and ignored. There are number of functions to perform read and write operations with the files. Some function read /write single character and some function read/write block of binary data. The put( ) and get( ) functions are used to read or write a single character whereas write( ) and read( ) are used to read or write block of binary data.

The put( ) and get( ) Functions

The function get( ) is a member function of the class fstream. This function reads a single character from the file pointed by the get pointer i.e., the character at current get pointer position is caught by the get( ) function.

The put( ) function writes a character to the specified file by the stream object. It is also a member of fstream class. The put( ) function places a character in the file indicated by put pointer.

13.15 Write a program to write and read string to the file using put( ) and get( ) functions.

# include <fstream.h>
# include <conio.h>
# include <string.h>


int main( )

{
  clrscr( );


  char text[50];
  cout <<"\n Enter a Text : ";
  cin.getline(text,50);
  int l=0;
  fstream io;
  io.open("data", ios::in | ios::out);


  while (l[text]!='\0')
  io.put(text[l++]);


  io.seekg(0);
  char c;
  cout <<"\n Entered Text : ";
  while (io)
  {
     io.get(c);
     cout<<c;
  }
return 0;
}

OUTPUT

Enter a Text : PROGRAMMING WITH ANSI AND TURBO-C
Entered Text : PROGRAMMING WITH ANSI AND TURBO-C

Explanation: In the above program, the file data is opened in read and write mode at once. The getline( ) function reads the string through the keyboard and stores in the array text[50]. The statement io.put(text[l++]) in the first while loop reads one character from array and writes it to the file indicated by the stream object io. The first while loop terminates when the null character is found in the text.

The statement io.seekg(0) sets the file pointer at the beginning of the file. In the second while loop, the statement io.get(c) reads one character at a time from the file and cout( ) statement displays the same character on the screen. The while loop terminates when end of file is detected.

13.10 BINARY AND ASCII FILES

The insertion and extraction operators, known as stream operator, handles formatted data. The programmer needs to format data in order to represent it in a suitable fashion. The description of formatted and unformatted data is given in Chapter “INPUT and OUTPUT IN C++”. ASCII codes are used by the I/O devices to share or pass data to the computer system, but central processing unit (CPU) manipulates the data using binary numbers i.e., 0 and 1. For this reason, it is essential to convert the data while accepting data from input devices and displaying the data on output devices. Consider the following statements:

cout<<k;    // Displays value of k on screen

cin>>k;     // Reads value for k from keyboard

Here, k is an integer variable. The operator << converts value of integer variable k into stream of ASCII characters. In the same fashion, the << operator converts the ASCII characters entered by the user to binary. The data is entered through the keyboard, a standard input device. For example, you enter 21. The stream operator >> gets ASCII codes of the individual digits of the entered number 21 i.e., 50 and 49. ASCII code of 2 and 1 are 50 and 49 respectively. The stream operator >> converts the ASCII value to equivalent binary format and assigns it to the variable k. The stream operator << converts the value of k (21) that is stored in binary format into equivalent ASCII codes i.e., 50 and 49. Figure 13.9 shows representation of integer number in ASCII and binary format.

Fig. 13.12 Representation in BINARY and ASCII formats

13.16 Write a program to demonstrate that the data is read from the file using ASCII format.

# include <fstream.h>
# include <constream.h>
int main( )
{
  clrscr( );
  char c;
  ifstream in("dat");


  if (!in)
  {
     cerr<<" Error in  opening file. ";
     return 1;
  }


while (in.eof( )==0)

{
  cout<<(char)in.get( );
}


return 0;
}

OUTPUT

PROGRAMMING WITH ANSI AND TURBO-C

Explanation: In the above program, the data file is opened in read mode. The file already exists. Using get( ) member function of ifstream class, the contents of file is read and displayed. Consider the following statement:

cout<<(char)in.get( );

The get( ) function reads data from file in ASCII format. Hence, it is necessary to convert the ASCII number to equivalent character. The typecasting format (char) converts ASCII number to equivalent character. In case the conversion is not done, the output would be as follows:

8082797182657777737871328773847232657883733265786832848582667967-1

The output displayed above are ASCII numbers and –1 at the end indicates end of file.

After typecasting the original string will be as shown in the output.

(1) The write( ) and read( ) Functions

The data entered by the user are represented in ASCII format. However, the computer can understand only machine format i.e., 0 and 1. When data is stored in text format numbers are stored as characters and occupy more memory space. The functions put( ) and get( ) read/ write a character. The data is stored in the file in character format. If large number of numeric data is stored in the file, it will occupy more space. Hence, using put( ) and get( ) creates disadvantages.

This limitation can be overcome using write( ) and read( ) functions. The write( ) and read( ) functions use binary format of data during operation. In binary format, the data representation is same in file and system. Figure 13.12 shows difference between ASCII and binary format. The bytes required to store an integer in text form depends upon its size whereas in binary format the size is fixed. The binary form is exact and allows quick read and write operation because no conversion takes place during operations. The formats of the write( ) and read( ) functions are given below.

in.read((char *)  & P, sizeof(P));

out.write((char *) & P, sizeof(P));

These functions have two parameters. The first parameter is the address of the variable P. The second is the size of the variable P in bytes. The address of the variable is converted to char type. Let us consider program 13.17.

13.17 Write a program to perform read and write operations using write( ) and read( ) functions.

# include <fstream.h>
# include <conio.h>
# include <string.h>


int main( )
{
  clrscr( );
  int num[]={100,105,110,120,155,250,255};
  ofstream out;
  out.open("01.bin");
  out.write((char *)  &num, sizeof(num));
  out.close( );


  for (int i=0;i<7;i++) num[i]=0;


  ifstream in;
  in.open("01.bin");
  in.read((char *) & num, sizeof(num));


  for (i=0;i<7;i++)   cout<<num[i]<<"\t";
  return 0;
}

OUTPUT
100  105  110  120  155  250  255

Explanation: In the above program, integer array is initialized with 7 integer numbers. The file 01.bin is opened. The statement out.write((char *) & num, sizeof(num)) writes the integer array in the file. The &num argument provides the base address of the array and the second argument provides total size of the array. The close( ) function closes the file. The same file is opened again for reading purpose. Before reading the contents of the file, the array is initialized to zero that is not necessary. The statement in.read((char *) & num, sizeof(num)) reads data from the file and assigns it to the integer array. The second for loop displays the contents of the integer array. The size of file “01.bin” will be 14 bytes i.e., two bytes per integer. If the above data is stored without using write( ) command, the size of the file will be 21 bytes.

(2) Reading and Writing Class Objects

The functions read( ) and write( ) perform write and read operations in binary format that is exactly same as internal representation of data in the computer. Due to these capabilities of the functions, large data can be stored in small amount of memory. Both these functions are also used to write and read class objects to and from file. During read and write operation only data members are written to the file and the member functions are ignored. Consider the following program.

13.18 Write a program to perform read and write operations with objects using write( ) and read( ) functions.

# include <fstream.h>
# include <conio.h>


class boys
{
  char name [20];
  int age;
  float height;
  public :
     void get( )
     {
       cout << "Name   : "; cin>>name;
       cout << "Age    : "; cin>>age;
       cout << "Height : "; cin>>height;
     }


  void show ( )
  {
     cout <<"\n"<<name<<"\t"<<age <<"\t"<<height;
  }
  };


int main( )
{
  clrscr( );
  boys b[3];
  fstream out;
  out.open ("boys.doc", ios::in | ios::out);
  cout <<"\n Enter following information :\n";


  for (int i=0;i<3;i++)
  {
     b[i].get( );
     out.write ((char*) & b[i],sizeof(b[i]));

  }
  out.seekg(0);
  cout  <<"\n Entered information\n";
  cout  <<"Name   Age     Height";


  for (i=0;i<3;i++)
  {
     out.read((char *) & b[i], sizeof(b[i]));
     b[i].show( );
  }
     out.close( );
     return 0;
}

OUTPUT

Enter following information:
Name : Kamal
Age : 24
Height : 5.4
Name : Manoj
Age : 24
Height : 5.5
Name : Rohit
Age : 21
Height : 4.5

Entered information
Name  Age   Height
Kamal  24   5.4
Manoj  24   5.5
Rohit  21   4.5

Explanation: In the above program, the class boys contains data members’ name, age, and height of char, int, and float type. The class also contains member functions get( ) and show( ) to read and display the data. In function main( ) an array of three objects is declared i.e., b[3]. The file “boys.doc” is opened in output and input mode to write and read data. The first for loop is used to call the member function get( ) and data read via get( ) function is written to the file by write( ) function. The same method is repeated while reading the data from file. While reading data from file, read( ) function is used and the member function show( ) displays the data on the screen.

13.11 RANDOM ACCESS OPERATION

Data files always contain large information and the information always changes. The changed information should be updated otherwise the data files are not useful. Thus to update data in the file we need to update the data files with latest information. To update a particular record of data file it may be stored anywhere in the file but it is necessary to obtain at which location (in terms of byte number) the data object is stored.

The sizeof( ) operator determines the size of object. Consider the following statements.

(a) int size=sizeof(o);

Where, o is an object and size is an integer variable. The sizeof( ) operator returns the size of object o in bytes and it is stored in the variable size. Here, one object is equal to one record.

The position of nth record or object can be obtained using the following statement.

(b) int p=(n-1 * size);

Here, p is the exact byte number of the object that is to be updated, n is the number of object, and size is the size in bytes of an individual object (record).

Suppose we want to update 5th record. The size of individual object is 26.

(c) p=(5-1*26) i.e. p= 104

Thus, the fifth object is stored in a series of bytes from 105 to 130. Using functions seekg( ) and seekp( ) we can set the file pointer at that position.

13.19 Write a program to create a text file. Add and modify records in the text file. The record should contain name, age, and height of a boy.

# include <stdio.h>
# include <process.h>
# include <fstream.h>
# include <conio.h>


class boys
{
  char name [20];
  int age;
  float height;
  public :


void input( )
{
  cout << "Name    : ";  cin>>name;
  cout << "Age    : ";     cin>>age;
  cout << "Height : ";   cin>>height;
}

void show (int r)
{
  cout <<"\n"<<r<<"\t"<<name<<"\t"<<age <<"\t"<<height; }


};


boys b[3];
fstream out;


void main ( )
{
  clrscr( );
  void menu (void);
  out.open ("boys.doc", ios::in | ios::out | ios::noreplace);
  menu( );
}



void menu(void)
{
  void get(void);
  void put(void);
  void update(void);
  int x;
  clrscr( );
  cout <<"\n Use UP arrow key for selection";
  char ch=' ';
  gotoxy(1,3);
  printf ("ADD  ( )");
  gotoxy(1,4);
  printf ("ALTER( )");
  gotoxy(1,5);
  printf ("EXIT ( )");
  x=3;
  gotoxy(7,x);
  printf ("*");


  while (ch!=13)
  {
     ch=getch( );

     if (ch==72)
     {
       if (x>4)
       {
            gotoxy(7,x);
            printf ( " ");
            x=2;
       }


  gotoxy(7,x);
  printf (" ");
  gotoxy(7,++x);
  printf ("*");
}
}


switch(x)
{
  case 3   :   get( );  put( ); getche( ); break;
  case 4   :   put( ); update( );  put( );  getche ( ); break;
  default  :   exit(1);
}
  menu( );
}


void get ( )
{
  cout <<"\n\n\n\n Enter following information :\n";
  for (int i=0;i<3;i++)
  {
     b[i].input( );
     out.write ((char*) & b[i],sizeof(b[i]));
  }
}
void put ( )
{
  out.seekg(0,ios::beg);
  cout  <<"\n\n\n Entered information \n";
  cout  <<"Sr.no   Name   Age     Height";
  for (int i=0;i<3;i++)

  {
     out.read((char *) & b[i],
     sizeof(b[i]));
     b[i].show(i+1);
  }
}


void update( )
{
  int r, s=sizeof(b[0]);
  out.seekg(0,ios::beg);
  cout <<"\n"<<"Enter record no. to update : ";
  cin>>r;
  r=(r-1)*s;
  out.seekg(r,ios::beg);
  b[0].input( );
  out.write ((char*) & b[0],sizeof(b[0]));
  put( );
}

OUTPUT
Use UP arrow key for selection
ADD (*)
ALTER( )
EXIT ( )

Enter following information :
Name : Sachin
Age : 28
Height : 5.4
Name : Rahul
Age : 28
Height : 5.5
Name : Saurav
Age : 29
Height : 5.4

Entered information
Sr.no    Name    Age    Height
1         Sachin      28      5.4
2         Rahul       28      5.5
3         Saurav     29      5.4

Explanation: In the above program, the class boys contain data member name, age, and height. The class boys also contain member functions input( ) and show( ). The input( ) function is used to read data and show( ) function displays data on the screen.

After class definition and before main( ) function, array of objects b[3] and fstream object out are declared. They are declared before main( ) for global access. The file boys.doc is opened in input and output modes to perform both read and write operation.

The menu( ) function displays menu on the screen. The menu items can be selected using up arrow key. To start the operation hit enter. There are three more user-defined functions. They are get( ), put( ) and update( ). The get( ) function calls the member function input( ) to read data through the keyboard. The get( ) function writes the data using write( ) function. The put( ) function calls the member function show( ) . The put( ) function calls the member function show( ). The put( ) function reads the data from the file using read( ) function.

The update( ) function is used to modify the previous record. The seekg( ) function sets the file pointer at the beginning of the file. The sizeof( ) operator determines the size of object and stores it in the variable s.

13.12 ERROR HANDLING FUNCTIONS

Until now, we have performed the file operation without any knowledge of failure or success of the function open( ) that opens the file. There are many reasons and they may result in error during read/write operation of the program.

(1) An attempt to read a file which does not exist.

(2) The file name specified for opening a new file may already exist.

(3) An attempt to read contents of file when file pointer is at the end of file.

(4) Insufficient disk space.

(5) Invalid file name specified by the programmer.

(6) An effort to write data to the file that is opened in read only mode.

(7) A file opened may already be opened by another program.

(8) An attempt to open read only file for writing operation.

(9) Device error.

The ‘stream state’ member from the class ios receives values from the status bit of active file. The class ios also contains many different member functions. These functions read the status bit of the file where error occurred during program execution are stored. These functions are given in Table 13.3 and various status bits are described in Table 13.4.

All streams such as ofstream, ifstream, and fstream contain state connected with it. Faults and illegal conditions are managed (controlled) by setting and checking the state properly. Figure 13.13 describes it more clearly.

Fig. 13.13 Status bits

Table 13.4 Status bits

eofbit End of file encountered 0×01
failbit Operation unsuccessful 0×02
badbit Illegal operation due to wrong size of buffer 0×04
hardfail Critical error 0×08

Table 13.5 Error trapping functions

Functions Working and return value
fail( ) Returns non-zero value if an operation is unsuccessful. This is carried out by reading the bits ios::failbit, ios:: badbit, and ios::hardfail of ios::state.
eof( ) Returns non-zero value when end of file is detected otherwise returns zero. The ios::eofbit is checked.
bad( ) Returns non-zero value when error is found in operation. The ios::badbit is checked.
good( ) Returns non-zero value of no error occurred during file operation i.e., no status bit were set. This also indicates that the above functions are false. When this function returns true, we can proceed the file operation.
rdstate ( ) Returns the stream state. It returns value of various bits of ios::state.

The following examples illustrate techniques of error checking.

(A) An attempt to open a non-existing file for reading

       ifstream in(“data.txt”);

 

       if (!in)

       {

             cout<< “File not found”;

       }

In above format an attempt is made to open a file for reading. If the file already exists, it will be opened otherwise operation fails. Thus, by checking the value of object in we can confirm failure or success of the operation and accordingly further processing can be decided.

(B) An attempt to open a read only file for writing

       ofstream out(“data.txt”);

 

       if   (!out)

            cout<<“Unable to open file”;

       else

            cout<<"File opened";

Suppose that the data.txt file is protected (marked read-only) or used by another application in multitasking operating environment. If the same file is opened in write mode as shown above, the operation fails. By checking value of object out with if( ) statement we can catch the error and transfer the program control to suitable sub-routine.

(C) Checking end of file

    ifstream in("data.txt");

    while (!in.eof( ))
   {
 // read   data from file
 //  display on screen
 }

We may seek to open an existing file and read its contents. After opening a file in read mode, it is necessary to read the characters from file using appropriate function (read( ) or get( ) ). While reading a file, the get pointer is advanced to successive characters and the same process can be repeated using loops. The compiler cannot determine by itself the end of file. The eof( ) function determines the end of file. Thus, by checking the value of eof( ) function we can determine the end of file. In addition, by checking the value of object the end of file is determined. Such conditions must be placed in the while loop parenthesis. While reading file, use only while or for loop.

(D) Illegal file name

    ifstream in("*+**");


   while (!in.eof( ))
  {
 // read data from file
 // display on screen
 }

While performing file operation, it is the user’s responsibility to specify the correct file name. If illegal file name is specified by the user, file operation fails. In the above format “*+**” is given as file name that is invalid.

(E) Operation with unopened file

    ifstream in("DATA");

     while (!in.eof( ))

     {
 // read data from file
 // display on screen
 }

Suppose “DATA” file does not exist and an attempt is made to open it for reading. Any operation applied with this file will be of no use. Hence, while performing file operation first we have to check whether the file is opened successfully or not. After the confirmation, we can proceed to the next step.

Programs referred to above discussions are explained below.

13.20 Write a program to detect whether the file is opened successfully or not.

# include <fstream.h>
# include <constream.h>
# include <string.h>


ifstream in;  // Global object


void  main( )
{
  clrscr( );
  void show (void);
  in.open("dat") ;
  char c;


  if (in!=0)   show( );
  else        cout <<"\n File not found";
}


void show( )
{
  char c;
  cout <<"\n Contents of file : ";


  while (in)
  {
     in.get(c);
     cout<<c;
  }
}

OUTPUT

File not found

Explanation: In the above program, object in of ifstream class is declared globally. It can be accessed by any normal function. In function main( ) using the object in a file is opened. If the open( ) function fails to open file, it returns zero otherwise non-zero value. The if statement checks the value of object in and if it is non-zero show( ) function is invoked, otherwise “File not found” message is displayed. The show( ) function reads file and displays the contents on the screen. In the above program, the open( ) function tries to open “dat” file, which does not exist. Hence, the output is “File not found.” If the specified file exists, the contents of file will be displayed.

13.21 Write a program to display status of various error trapping functions.

# include <fstream.h>
# include <conio.h>


void main ( )
{
  clrscr( );
  ifstream in;
  in.open ("text.txt", ios::nocreate);
  if (!in)
  cout <<"\n File not found";
  else
  cout<<"\nFile ="<<in;
  cout <<"\nError state = "<<in.rdstate( );
  cout <<"\ngood ( )      = "<<in.good( );
  cout <<"\neof ( )      = "<<in.eof( );
  cout <<"\nfail( )       = "<<in.fail( );
  cout <<"\nbad ( )      = "<<in.bad( );
  in.close( );
}

OUTPUT

File not found
Error state = 4
good ( )        = 0
eof ( )           = 0
fail( )            = 4
bad ( )          = 4

Explanation: In the above program, an attempt is made to open a non-existent file. The if statement checks the value of object in. The specified file does not exist, hence it displays the message “File not found.” The program also displays the values of various bits using the functions good( ), eof( ), bad( ), fail( ) and rdstate( ) error trapping functions. For more information about these functions, please refer to Table 13.4.

13.13 COMMAND LINE ARGUMENTS

An executable program that performs a specific task for operating system is called as command. The commands are issued from the command prompt of operating system. Some arguments are to be associated with the commands hence these arguments are called as command line arguments. These associated arguments are passed to program.

Like C, in C++ every program starts with a main( ) function and it marks the beginning of the program. We have not provided any arguments so far in the main( ) function. Here, we can make arguments in the main( ) like other functions. The main( ) function can receive two arguments and they are argc (argument counter) and argv (argument vector). The first argument contains the number of arguments and the second argument is an array of char pointers. The *argv points to the command line arguments. The size of array is equal to value counted by the argc. The information contained in the command line is passed on to the program through these arguments when the main( ) is called up by the system.

(1) Argument argc An argument argc counts total number of arguments passed from command prompt. It returns a value that is equal to total number of arguments passed through the main( ).

(2) Argument argv It is a pointer to an array of character strings that contains names of arguments. Each word is an argument.

Syntax – main ( int argc, char * argv [ ]);

Example – ren file1 file2.

Here, file1 and file2 are arguments and copy is a command. The first argument is always an executable program followed by associated arguments. If argument is not the first program name itself becomes an argument but the program will not run properly and will flag an error. The contents of argv[ ] would be as per following:

argv [0] → ren

argv [1] → file1

argv [2] → file2

13.22 Write a program to simulate rename command using command line arguments.

# include <stdio.h>
# include <fstream.h>
# include <conio.h>
# include <process.h>

main(int argc, char *argv[])
{
  fstream out;
  ifstream in;


if (argc<3 )
{
  cout<<"Insufficient Arguments";
  exit(1);
}


in.open(argv[1],ios::in | ios::nocreate);


if (in.fail( ))
{
  cout <<"\nFile Not Found";
  exit(0);
}
  in.close( );
  out.open(argv[2],ios::in | ios::nocreate);


if (out.fail( ))
{  rename(argv[1],argv[2]); }
else
cout <<"\nDuplicate file name or file is in use.";
return 0;
}

Explanation: In the above program, the main( ) receives two file names. The existence of file can be checked by opening it in read mode. If the file does not exist the program terminates. On the other hand if the second file exists the rename operation cannot be done. The rename operation is carried out only when first file exists and the second file does not exist. Make exe file of this program and use it on the command prompt.

13.14 STRSTREAMS

(1) ostrstream

The strstream class is derived from istrstream and ostrstream classes. The strstream class works with memory. Using objects of ostrstream class different type of data values can be stored in an array.

13.23 Write a program to demonstrate use of ostrstream objects.

# include <strstream.h>
# include <iomanip.h>
# include <conio.h>


main ( )
{
  clrscr( );
  char h='C';
  int j=451;
  float PI=3.14152;
  char txt[]="applications";
  char buff[70];


  ostrstream o (buff,70);
  o<<endl <<setw(9)<<"h="<<h<<endl <<setw(9) <<"j="<<oct<<j<<endl
  <<setw(10)<<"PI="<<setiosflags(ios::fixed)<<PI<<endl  <<setw(11)
  <<"txt="<<txt <<ends;
  cout<<o.rdbuf( );
return 0;
}

OUTPUT
       h=C
       j=703
       PI=3.14152
       txt= applications

Explanation: The strstream deals with memory. If we want to pick characters from a strstream or we want to add characters into strstream, this can be done by creating istrstream and ostrstream objects. When object o is created the constructor of ostrstream is executed. Once an object of ostrstream is created we can assign any formatted text to array associated with it. The statement cout<<o.rdbuf( ) displays the formatted information on the screen.

(2) istrstream

It is one of the base classes of the strstream class. Using objects of istrstream class, data can be extracted from an array. Suppose a character array contains numbers and characters. You can extract number from an array and assign it to an integer variable. Similarly, other values can be extracted from an array. The following program illustrates this.

13.24 Write a program to demonstrate the use of istrstreams.

# include <strstream.h>
# include <conio.h>


 main ( )
{
  clrscr( );
  char *book;
  int pages;
  float price;
  char *text="550 175.75 C++";


  istrstream  o(text);
  o>>pages>>price>>book;
  cout  <<endl <<pages <<endl <<price<<endl<book;
  cout <<o.rdbuf( );
  return 0;
}

OUTPUT

550
175.75
C++

Explanation: The istrstream is opposite of the strstream. It picks different types of data from an array. In the above program, character pointer text contains data of integer, float, and character type. Using the object of istrstream class we can separate the contents and store them in appropriate variable. The *book pointer variable displays string. The remaining contents are displayed by the function rdbuf( ).

13.15 SENDING OUTPUT TO DEVICES

It is also possible to send information of file directly to devices like printer or monitor. Table 13.6 describes various devices with their names and descriptions. The program given next illustrates the use of such devices.

Table 13.6 Standard devices

Device Name Description
CON Console (monitor screen)
COM1 or AUX Serial port – I
COM2 Serial port – II
LPT1 OR PRN Parallel printer – I
LPT2 Parallel printer – II
LPT3 Parallel printer – III
NUL Dummy device

13.25 Write a program to read a file and send data to the printer.

# include <fstream.h>
# include <iostream.h>
# include <conio.h>
# include <process.h>


# define   eject out.put('\x0C');


void  main ( )
{clrscr( );
  char h;
  char name[20];
  cout <<"Enter file name : ";
  cin>> name;


ifstream in (name);


if (!in)
{
  cerr <<endl<<"File opening error";
  _cexit( );
}


ofstream out ("LPT1");


if(!out)
{
  cerr <<endl<<"device opening error";
  _cexit( );
}

  while (in.get(h)!=0)
  out.put(h);
  eject;


}

Explanation: In the above program, the file name is entered through the keyboard and it is opened for reading purpose. The ifstream object in opens the file. The ofstream object out activates the printer. The if statement checks both the objects for detect operation status whether the operations have failed or are successful. The while loop reads data from the file and using put ( ) statement passes it to the devices associated with the object out. In this program data read is passed to the printer. The macro eject defined at the beginning of the program advances page of printer. In case printer is not attached, the message displayed will be as under:

    Error Message
    System Message
Error accessing LPT1 device
  >> Retry << Cancel

The user can select retry if the printer is attached otherwise by selecting cancel, the operation can be cancelled.

SUMMARY

(1) These days, huge amount of data is processed in computer networking. The information is uploaded or downloaded from the desktop computer. The information transfer in computer networking in day-to-day life is done in the form of files. The data is saved in the file on the disk. The file is an accumulation of data stored on the disk.

(2) Stream is nothing but flow of data. In object-oriented programming the streams are controlled using the classes.

(3) The istream and ostream classes control input and output functions respectively.

(4) The iostream class is also a derived class. It is derived from istream and ostream classes. There are three more derived classes which are useful. They are istream_withassign, ostream_withassign, and iostream_withassign. They are derived from istream, ostream, and iostream respectively.

(5) Filebuf accomplishes input and output operations with files. The fstreambase acts as a base class for fstream, ifstream, and ofstream. The ifstream class is derived from fstreambase and istream by multiple inheritance. It can access member functions such as get( ), getline( ), seekg( ), tellg( ) and read( ). The ofstream class is derived from fstreambase and ostream classes. It can access the member functions such as put( ), seekp( ), write( ) and tellp( ). The fstream class allows for simultaneous input and output on a filebuf. The member function of base classes istream and ostream starts the input and output.

(6) There are two methods (a) constructor of the class and (b) member function open( ) of the class for opening a file.

(7) The class ofstream creates output stream objects and ifstream creates input stream objects.

(8) The close( ) member function closes the file.

(9) The open( ) function uses the same stream objects. The open( ) function has two arguments. First is file name and second mode.

(10) When end of file is detected, the process of reading data can be easily terminated. The eof( ) function is used for this purpose. The eof( ) stands for end of file. It is an instruction given to the program by the operating system that end of file is reached. The eof( ) function returns 1 when end of file is detected.

(11) The mode ios::out and ios::trunc are near about same. The ios:: app lets the user to add data at the end of file whereas ios:: ate allows user to add or update data anywhere in the file.

(12) The seekg( ) function shifts the associated file’s input (get) file pointer. The seekp( ) function shifts the associated file’s output (put) file pointer.

(13) seekg( ) — Shifts input ( get ) pointer to a given location.

(14) seekp( ) — Shifts output (put) pointer to a given location.

(15) tellg( ) — Provides the present position of the input pointer.

(16) tellp( ) — Provides the present position of the output pointer.

(17) The put( ) and get( ) functions are used to read or write a single character whereas write( ) and read( ) are used to read or write block of binary data.

(18) The fail( ), eof( ), bad( ) and good( ) are error trapping functions.

(19) An executable program that performs a specific task for operating system is called as command. The commands are issued from the command prompt of operating system. Some arguments are to be associated with the commands and hence these arguments are called as command line arguments.

(20) Syntax main( int argc, char * argv[ ])

EXERCISES

[A] Answer the following questions.

(1) What is a stream?

(2) What is a file?

(3) Describe the different derived classes from ios that control the disk I/O operations.

(4) Describe the two methods of opening of file.

(5) Explain detection of end of file with function eof( ).

(6) Describe the syntax of open( ) function with its arguments.

(7) Which are the different types of file opening modes? List their names with meaning.

(8) Describe file manipulators with their syntaxes.

(9) Describe the various errors trapping functions.

(10) What are the possible reasons for failure of open( ) function?

(11) What are command line arguments?

(12) Explain the use of not operator and eof( ) function.

(13) Explain sequential and random file operations.

(14) How do you write a data in file in binary format?

(15) What are the limitations of using put( ) and get( ) functions?

(16) Explain the uses of ostrstream and istrstream class.

(17) Explain the difference between Binary and ASCII files.

[B] Answer the following by selecting the appropriate option.

(1) The eof( ) stands for

(a) end of file

(b) error opening file

(c) error of file

(d) none of the above

(2) Command line arguments are used with function

(a) main ( )

(b) member function

(c) with all functions

(d) none of the above

(3) The statement in.seekg(0,ios::end) sets the file pointer

(a) at the end of file

(b) at the beginning of file

(c) in the middle of file

(d) none of the above

(4) The close( ) function

(a) closes the file

(b) closes all files opened

(c) closes only read mode file

(d) none of the above

(5) The write( ) function writes

(a) single character

(b) object

(c) string

(d) none of the above

(6) What will be the value of variable c after execution of the following program?

    # include <fstream.h>

    void main ( )
    {
   char text[5];
   ofstream out ("data.txt");
   out<<"Programming with ANSI and Turboc C";
   out.close( );

   ifstream in ("data.txt");
   int c=0;

   while (!in.eof( ))
   { in.getline(text,5);
   c++;    }
   }
  (a)   c=9                                            (b)   c=2
  (c)   c=5                                            (d)   c=1

(7) What will be the values of variable j and k after execution of the following program?

    # include <fstream.h>

    void main ( )
   {

   ofstream j;
   ifstream k;
   cout <<"j="<<sizeof(j)<<endl;
   cout <<"k="<<sizeof (k);
   }

(a) j=78 k=80

(b) j=80 k=80

(c) j=80 k=78

(d) none of the above

(8) The object of fstream class provides

(a) both read and write operations

(b) only read operation

(c) only write operation

(d) none of the above

(9) To add data at the end of file the file must be opened in

(a) append mode

(b) read mode

(c) write mode

(d) both (a) and (c)

(10) When a file is opened in read or write mode the file pointer is set

(a) at the beginning of file

(b) at the end of file

(c) in the middle of file

(d) none of the above

(11) While performing file operation this file must be included in

(a) fstream.h

(b) iostream.h

(c) constream.h

(d) all of the above

(11) The constructor of this class requires file name and mode for opening file

(a) ifstream

(b) ofstream

(c) fstream

(d) all of the above

[C] Attempt the following programs.

(1) Write a program to open a file in output and input mode. Accept data and write to the file. Display the contents of the file.

(2) Write a program to write and read data in a file using object I/O functions write( ) and read( ). Declare class with data members name[20], int billno, int amount_debited, and int received _amount and int balance. Add 10 records and display the list of persons with balances. The user should have a facility to modify the existing records.

(3) Write a program to read and write a data file. While writing data follow the following instructions:

(a) Add one space between two successive words.

(b) Capitalize the first character of sentences.

(c) If numerical data is present put them in a bracket.

(4) Write a program to copy contents of one file to another file. Use command line arguments.

(5) Write a program to read a file. Display the total number of characters, words, lines, and blank spaces in the file.

(6) Write a program to exchange contents of two files. Use command line arguments.

(7) Write a program to compare two files in terms of number of bytes.

(8) Write a program to count characters and numericals present in a file.

(9) Write a program to print the contents of a file on printer.

(10) Write a program to check whether the given file exists or not. Display suitable message. User should enter the file name.

(11) Write a program to write contents of one file in reverse into another file.

(12) Write a program to find length of a file.

[D] Find the bugs in the following programs.

(1)
   ifstream in;
   void  main( )
   {
      ifstream in;
      void show (void);
      in.open("data") ;
      if (in!=0)    show( );
      else    cout <<"\n File not fount";
   }

   void show ( )
   {  char c;
      cout <<"\n Contents of file : ";
      while (in)  { in.get(c);   cout<<c;  }   }

   Tip: Assume the file "data" exists.
(2)

   void main ( )
   {
      char name[15];
      ofstream out("text");
      cin >>name;
      out<<name<<"\t";
      ifstream in("text"); in>>name;
      cout <<"\nName\t: "<<name<<"\n";
      in.close( );
   }
(3)
   void  main ( )
   {
      ifstream in("data");
      while (in)  {  cout<<(char)in.get( );  }
      return 0;
   }

   Tip: Assume the file "data" exists.
(4)
       void main ( )
       {
       fstream in("data");

       while (in.eof( )==0)
       {
         cout<<(char)in.get( );
       }
       }