0% found this document useful (0 votes)
224 views

Ads Unit III

Exception handling in C++ allows programs to gracefully handle runtime errors. A try block contains code that may throw exceptions. When an exception is thrown, it is caught by an associated catch block, which handles the exception. There can be multiple catch blocks for different exception types. Exceptions can be of built-in or user-defined types. The catch blocks are tried in order, so a base class exception catch must come after any derived class catches.

Uploaded by

api-26548538
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
224 views

Ads Unit III

Exception handling in C++ allows programs to gracefully handle runtime errors. A try block contains code that may throw exceptions. When an exception is thrown, it is caught by an associated catch block, which handles the exception. There can be multiple catch blocks for different exception types. Exceptions can be of built-in or user-defined types. The catch blocks are tried in order, so a base class exception catch must come after any derived class catches.

Uploaded by

api-26548538
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 37

EXCEPTION HANDLING

• Exception handling allows one to manage run-time errors in an


orderly fashion.

• Using exception handling, the program can automatically invoke


an error-handling routine when an error occurs.

Fundamentals:

• C++ exception handling is built upon 3 keywords-


o try
o catch
o throw

• Program statements that one wants to monitor for exceptions are


contained in a try block.

• If an exception occurs within the try block, it is thrown (using


throw).

• The exception is caught, using catch and processed.

• General form:

try
{ //try block
}

catch(type1 arg)
{ //catch block
}

..
..
..

catch(typen arg)
{ //catch block
}

• When an exception is thrown, it is caught by its corresponding


catch statement which processes the exception.

• There can be more than one catch associated with a try.

UNIT III 1
• General form of the throw statement is:

o throw exception;

o throw generates the exception specified by exception.

o If this exception is to be caught, the throw must be


executed either from within the try block itself or from
any function called from within the try block(directly or
indirectly)

• Throwing an unhandled exception causes the std library function


terminate() to be invoked.

o By default, terminate() calls abort() to stop the program.

Ex:
#include <iostream.h>

int main()
{
cout << "Start\n";

try
{ // start a try block

cout << "Inside try block\n";


throw 100; // throw an error
cout << "This will not execute";
}

catch (int i)
{ // catch an error

cout << "Caught an exception -- value is: ";


cout << i << "\n";
}

cout << "End";

return 0;
}

UNIT III 2
• Usually the code within a catch statement attempts to remedy an
error by taking appropriate action. If the error cant be fixed,
execution will continue with the statements following the catch.

o Often an error cant be fixed and a catch block will


terminate the program with a call to exit() or abort().

• An exception can be thrown from outside the try block as long as


it is thrown by a function that is called from within a try
block.

Ex:
#include <iostream.h>

void Xtest(int test)


{
cout << "Inside Xtest, test is: " << test << "\n";
if(test)
throw test;
}

int main()
{
cout << "Start\n";

try
{ // start a try block
cout << "Inside try block\n";
Xtest(0);
Xtest(1);
Xtest(2);
}

catch (int i)
{ // catch an error
cout << "Caught an exception -- value is: ";
cout << i << "\n";
}

cout << "End";

return 0;
}

UNIT III 3
• A try block can be localized to a function. When this is the
case, each time the function is entered, the exception handling
relative to that function is reset.

Ex:
#include <iostream.h>

void Xhandler(int test)


{
try
{
if(test)
throw test;
}
catch(int i)
{
cout << "Caught Exception #: " << i << '\n';
}
}

int main()
{
cout << "Start\n";

Xhandler(1);
Xhandler(2);
Xhandler(0);
Xhandler(3);

cout << "End";

return 0;
}

• It is important to understand that the code associated with a


catch statement will be executed only if it catches an
exception. Otherwise execution simply bypasses the catch
altogether.

UNIT III 4
Catching Class Types:

• An exception can be of any type, including class types that the


user creates.

• The most common reason that one wants to define a class type for
an exception is to create an object that describes the error
that occurred. This information can be used by the exception
handler to help it process the error.

Ex:
#include <iostream.h>
#include <cstring.h>

class MyException
{ public:

char str_what[80];
int what;

MyException() { *str_what = 0; what = 0; }

MyException(char *s, int e)


{ strcpy(str_what, s);
what = e;
}
};

int main()
{
int i;

try
{
cout << "Enter a positive number: ";
cin >> i;
if(i<0)
throw MyException("Not Positive", i);
}
catch (MyException e)
{ // catch an error
cout << e.str_what << ": ";
cout << e.what << "\n";
}

return 0;
}

UNIT III 5
Using Multiple Catch Statements:

• There can be multiple catch statements associated with a try.


• Each catch must catch a different type of exception.

Ex:
#include <iostream.h>

// Different types of exceptions can be caught.

void Xhandler(int test)


{
try
{
if(test)
throw test;
else
throw "Value is zero";
}
catch(int i)
{
cout << "Caught Exception #: " << i << '\n';
}
catch(const char *str)
{
cout << "Caught a string: ";
cout << str << '\n';
}
}

int main()
{
cout << "Start\n";

Xhandler(1);
Xhandler(2);
Xhandler(0);
Xhandler(3);

cout << "End";

return 0;
}

UNIT III 6
Handling derived Class Exceptions:

• We need to be very careful in ordering catch statements when


trying to catch exception types that involve base and derived
classes, because a catch clause for a base class will also
match any class derived from that base.

• If one wants to catch exceptions for both base and derived


class type, put the derived class first in the catch sequence.
Otherwise the base class catch will also catch all derived
class.

Ex:
#include <iostream.h>

class B
{
};

class D: public B
{
};

int main()
{
D derived;

try
{
throw derived;
}
catch(B b)
{
cout << "Caught a base class.\n";
}
catch(D d)
{
cout << "This won't execute.\n";
}

return 0;
}

UNIT III 7
Exception Handling Options:

1. Catching All Exceptions:


If we want an exception handler to catch all exceptions instead of
just a certain type, then we use
catch(…)
{ //body
}
Note: the ellipsis matches any type of data.
Ex: #include <iostream.h>

void Xhandler(int test)


{ try
{
if(test==0)
throw test; // throw int
if(test==1)
throw 'a'; // throw char
if(test==2)
throw 123.23; // throw double
}
catch(...)
{ // catch all exceptions
cout << "Caught One!\n";
}
}
int main()
{ cout << "Start\n";

Xhandler(0);
Xhandler(1);
Xhandler(2);

cout << "End";

return 0;
}

Note: One good use of catch(…) is as the last catch of a cluster


of catches. In this capacity, it provides a useful default or
“catch all” statement.

UNIT III 8
2. Restricting Exceptions:

• We can restrict the type of exceptions that a function can


throw outside of itself.
• We can even prevent a function from throwing any exceptions
whatsoever.
• To do so, we add a throw to the function definition.
• General form:

ret-type function(arg-list) throw (type-list)


{ //body
}

Here, only those data types contained in the comma-


seperated type-list may be thrown by the function.

Ex:
#include <iostream.h>

void Xhandler(int test) throw(int, char, double)


{
if(test==0) throw test; // throw int
if(test==1) throw 'a'; // throw char
if(test==2) throw 123.23; // throw double
}

int main()
{
cout << "start\n";

try
{ Xhandler(0); // try passing 1 and 2 to Xhandler()
}
catch(int i)
{ cout << "Caught an integer\n";
}
catch(char c)
{ cout << "Caught char\n";
}
catch(double d)
{ cout << "Caught double\n";
}

cout << "end";

return 0;
}

UNIT III 9
• Attempting to throw an exception that is not supported by a
function will cause the std library function unexpected()
to be called.

• By default, this causes abort() to be called, which causes


abnormal program termination.

• It is important to understand that a function can be


restricted only in what types of exceptions it throws back
to the try block that called it.

• That is, a try block within a function may throw any type
of exception so long as it is caught within that function.

• The restriction applies only when throwing an exception


outside of the function.

3. Rethrowing an Exception:

If we want to rethrow an expression from within an exception


handler, we can do so by calling throw, by itself, with no
exception.

• This causes the current exception to be passed to an outer


try/catch sequence.

• Reason for doing so is to allow multiple handlers access to


the exception.

• An exception can be rethrown from within a catch block or from


any function called from catch block.

• When an exception is rethrown, it will not be recaught by the


same catch statement. It will propogate outward to the next
catch statements.

UNIT III 10
Ex:
#include <iostream.h>

void Xhandler()
{
try
{
throw "hello"; // throw a char *
}

catch(const char *)
{
// catch a char *
cout << "Caught char * inside Xhandler\n";

throw ; // rethrow char * out of function

}
}

int main()
{
cout << "Start\n";

try
{
Xhandler();
}

catch(const char *)
{
cout << "Caught char * inside main\n";
}

cout << "End";

return 0;
}

UNIT III 11
terminate()

• This function requires the header <exception.h>

• This function is called whenever the exception handling


subsystem fails to find a matching catch statement for an
exception.

• Also called if the program attempts to rethrow an exception


when no exception is originally thrown.

• In general, terminate() is the handler of the last resort when


other handlers for an exception are not available.

• By default terminate() calls abort().

• We can change the function that is called by terminate().

o Doing so allows the program to take full control of the


exception handling subsystem.

o To change terminate handler, use set_terminate()

terminate_handler set_terminate(terminate_handler newhandler)throw();

o newhandler is a pointer to the new terminate handler.

o Function returns a pointer to the old terminate handler.

o The new terminate handler must be of type


terminate_handler , which is defined as

typedef void (*terminate_handler)();

o The only thing that the terminate handler must do is to


stop the program execution.

o It must not return to the program or resume it in anyway.

UNIT III 12
Ex:

// Set a new terminate handler.


#include <iostream.h>
#include <cstdlib.h>
#include <exception.h>

void my_Thandler()
{
cout << "Inside new terminate handler\n";
abort();
}

int main()
{
// set a new terminate handler

set_terminate(my_Thandler);

try
{
cout << "Inside try block\n";
throw 100; // throw an error
}

catch (double i)
{ // won't catch an int exception
// ...
}

return 0;
}

UNIT III 13
unexpected()

• This function requires the header <exception.h>

• This function is called when a function attempts to throw an


exception that is not allowed by its throw list.

• By default unexpected() calls terminate().

• We can change the function that is called by unexpected().

o To change unexpected handler, use set_unexpected()

unexpected_handler set_unexpected(unexpected_handler newhandler)


throw();

o newhandler is a pointer to the new unexpected handler.

o Function returns a pointer to the old unexpected handler.

o The new unexpected handler must be of type


unexpected_handler , which is defined as

typedef void (*unexpected_handler)();

o The handler may throw an exception, stop the program


execution or call terminate().

o It must not return to the program or resume it in anyway.

Note: Both set_terminate() and set_unexpected() require <exception.h>

uncaught_exception()

• Prototype is bool uncaught_exception();

• This function returns true if an exception has been thrown but


not yet caught.

• Once caught, the function returns false.

UNIT III 14
Note:

• When a function supplied by C++ std library throws an exception,


it will be an object derived from the base class “exception”.

• An object of the class “bad_exception” can be thrown by an


unexpected handler.

• These classes require the header <exception.h>

Applying exception handling

• Exception handling is designed to provide a structured means by


which the program can handle abnormal events.
• This implies that the error handler must do something rational
when an error occurs.

Ex: #include <iostream.h>

void divide(double a, double b)


{
try
{
if(!b) throw b; // check for divide-by-zero
cout << "Result: " << a/b << endl;
}
catch (double b)
{
cout << "Can't divide by zero.\n";
}
}
int main()
{
double i, j;

do
{
cout << "Enter numerator (0 to stop): ";
cin >> i;
cout << "Enter denominator: ";
cin >> j;
divide(i, j);
} while(i != 0);

return 0;
}

UNIT III 15
C++ CONSOLE AND FORMATTED I/O

C++ Streams

• A stream is a logical device that either produces or consumes


information.

• A stream is linked to a physical device by I/O system.

• Because all streams behave the same, the same I/O functions can
operate on virtually any type of physical device.

• The advantage to this approach is that we learn only one I/O


system.

C++ Stream Classes

• Standard C++ provides support for its I/O system in <iostream.h>

• The I/O classes begin with a system of template classes.

• Standard C++ creates 2 specializations of the I/O template


classes- one for 8-bit character & another for wide characters.

• C++ I/O system is built upon 2 related but different template


class hierarchies –

1. Derived from low-level I/O class called “basic_streambuf”. This


class supplies the basic, low-level input and output operations,
& provides the underlying support for the entire C++ I/O system.

2. Derived from “basic_ios”. This is high level I/O class that


provides formatting, error checking, and status information
related to stream I/O.

UNIT III 16
basic_ios is used as a base for several derived classes, including
basic_stream, basic_ostream and basic_iostream.
These classes are used to create streams capable of input, output and
input/output respectively.

Templates Char-based Class Wide-char based Class

1. basic_streambuf streambuf wstreambuf


2. basic_ios ios wios
3. basic_istream istream wistream

• The ios class contains many member functions & variables that
control or monitor the fundamental operation of a stream.

• If <iostream.h> is included in the program we get access to


this class.

C++ Predefined Streams

When a C++ program begins execution, 4 built-in streams are


automatically opened.

1. cin standard input - keyboard


2. cout standard output - monitor
3. cerr standard error output - monitor
4. clog Bufferred version of cerr - monitor

Formatted I/O

There are 2 related but conceptually different ways that you can
format data.

1. Directly access members of ios class. We can set various format


status flags defined inside the ios class or call various ios
member functions.

2. Use special functions called manipulators that can be included


as part of an I/O expression.

UNIT III 17
Formatting using ios Members

Each stream has associated with it a set of format flags that control
the way information is formatted.

The ios class declares a bitmask enumeration called “fmtflags” in


which various values are defined –

1. skipws flag – When set, leading white-spaces are discarded when


performing input on a stream.

2. left flag – When set, output is left justified.


3. right flag – When set, output is right justified.
4. internal flag – When set, a numeric value is padded to fill a
field by inserting spaces between any sign or base character.

These 3 are referred to as “adjustfield”. If none of these flags


are set, output is right justified by default.

5. oct flag – Causes output to be displayed in octal.


6. hex flag – Causes output to be displayed in hexadecimal.
7. dec flag – Causes output to be displayed in decimal.

These 3 together are referred to as “basefield”. By default,


numeric values are output in decimal.

8. scientific flag – floating-point numeric values are displayed


using scientific notation. Eg: 1.4 e +02
9. fixed flag – floating-point numbers are displayed using
normal notation.
These 2 together are referred to as “floatfield”.

10. showbase flag – causes the base of numeric values to be


shown. Eg: 1F is shown as 0x1F.
11. uppercase flag – causes the characters to be displayed in
uppercase.
12. showpos flag – causes a leading plus sign to be displayed.
13. showpoint flag – causes a decimal point & trailing zeroes
to be displayed for all floating-point output.
14. unitbuf flag – buffer is flushed after each insertion
operation.
15. boolalpha flag – Booleans can be input or output using the
keywords true or false.

UNIT III 18
Setting the format flags

• Use the setf() function. General form is

fmtflags setf(fmtflags flags);

o Returns the previous settings of the format flags & turns


on those flags specified by flags.
o Eg: stream.setf(ios::showpos);
o Stream is the stream i.e. to be affected.
o Since showpos is an enumerated constant defined by the ios
class, it must be qualified by ios when it is used.
Ex:
#include <iostream.h>
int main()
{
cout.setf(ios::showpoint);

cout.setf(ios::showpos);

cout << 100.0; // displays +100.000


return 0;
}

Note: Any call done to self is done relative to a specific


stream. There is no concept of calling setf() by itself.

Clearing Format Flags

Complement of setf() is unsetf(). General form is

void unsetf(fmtflags flags);

Eg: #include <iostream.h>


int main()
{
cout.setf(ios::uppercase | ios::scientific);

cout << 100.12; // displays 1.001200E+02

cout.unsetf(ios::uppercase); // clear uppercase

cout << " \n" << 100.12; // displays 1.001200e+02

return 0;
}

UNIT III 19
An overloaded form of setf()

fmtflags setf( fmtflags f1, fmtflags f2);

• Only flags specified by f2 are affected.


• They are first cleared and then set according to the flags
specified by f1.
• Even if f1 contains other flags, only those specified by f2 are
affected.

Eg:
#include <iostream.h>
int main( )
{
cout.setf(ios::showpoint | ios::showpos, ios::showpoint);

cout << 100.0; // displays 100.000, not +100.000

return 0;
}

showpoint is set, but not showpos.

• The most common use of 2-parameter form of setf() is when


setting the number-base, justification and float format flags (
i.e. basefield, adjust field & floatfield).

o Since the flags that comprise of these groupings are


mutually exclusive, we may need to turn off one when
setting another.

Eg:
#include <iostream.h>

int main()
{
cout.setf(ios::hex, ios::basefield);

cout << 100; // this displays 64

return 0;
}

Here, basefield flags are first cleared & hex is set.

UNIT III 20
Examining the Formatting Flags

• Use the function flags(), which returns the current setting of


each format flag.
fmtflags flags();

• Setting All Flags –

fmtflags flags(fmtflags f)
o Bit pattern found in f is used to set the format flags
associated with the stream.

Using width(), precision() and fill()

There are 3 member functions defined by ios that set these format
parameters, the filed width, the precision and the fill character.

1. width() – to specify a minimum field width.

streamsize width( streamsize w);

w becomes the fieldwidth & previous fieldwidth is returned.

The streamsize type is defined as some form of integer by the


compiler.

2. precision() – To determine the number of digits to be displayed


after the decimal point in floating-point.

streamsize precision( streamsize p);

precision is set to p & old value is returned.

Default precision is 6.

3. fill() - To specify the fill charcter.

char fill(char ch);

ch becomes the newfill character & the old one is returned.

Default fill is space.

UNIT III 21
Eg:

#include <iostream.h>

int main()
{
cout.precision(4) ;

cout.width(10);

cout << 10.12345 << "\n"; // displays 10.12

cout.fill('*');

cout.width(10);

cout << 10.12345 << "\n"; // displays *****10.12

// field width applies to strings, too

cout.width(10);

cout << "Hi!" << "\n"; // displays *******Hi!

cout.width(10);

cout.setf(ios::left); // left justify

cout << 10.12345; // displays 10.12*****

return 0;

UNIT III 22
Using Manipulators to Format I/O
• To access manipulators that take parameters, include <iomanip.h>
in the program.
• The main advantage of using the manipulators instead of the ios
member functions is that they commonly allow more compact code
to be written.
Eg:
#include <iostream.h>
#include <iomanip.h>
int main()
{
cout << hex << 100 << endl;
cout << setfill('?') << setw(10) << 2343.0;

return 0;
}
• The manipulator setiosflags() performs the same function as the
member function setf().
Eg:
#include <iostream.h>
#include <iomanip.h>
int main()
{
cout << setiosflags(ios::showpos);

cout << setiosflags(ios::showbase);

cout << 123 << " " << hex << 123;
return 0;
}
• One of the most interesting manipulator is boolalpha. It allows
true & false values to be input & output using the words true
and false rather than numbers.
Eg:
#include <iostream.h>
int main()
{
bool b;
b = true;
cout << b << " " << boolalpha << b << endl;

cout << "Enter a Boolean value: ";


cin >> boolalpha >> b;
cout << "Here is what you entered: " << b;

return 0;
}

UNIT III 23
C++ FILE INPUT/OUTPUT

• To perform file I/O, we must include the header <fstream.h>

• It defines several classes, including ifstream,ofstream &


fstream.

• These classes are derived from istream,ostream & iostream.

• Another class used by the file system is filebuf, which provides


low level facilities to manage a file stream.

Opening and Closing a File

• In C++ a file is opened by linking it to a stream.

o Before opening a file, a stream is obtained first.

o There are 3 types of streams: input, output and


input/output.

o To create an input stream, declare the stream to be of


class ifstream. Eg: ifstream in;

o To create an output stream, declare the stream to be of


class ofstream. Eg: ofstream out;

o To create an input/output stream, declare the stream to be


of class fstream. Eg: fstream io;

• Once you have created a stream, one way to associate it with a


file is by using open().

void ifstream::open(const char *filename,ios::openmode


mode=ios::in);

void ofstream::open(const char *filename,ios::openmode


mode=ios::out|ios::trunc);

void ifstream::open(const char *filename,ios::openmode


mode=ios::in|ios::out);

UNIT III 24
• Filename is the name of the file.

• Value of mode determines how the file is opened.

• Mode must be one or more of the following values defined by


openmode, which is an enumeration defined by ios –

1. ios::app – append mode

2. ios::ate – A seek to the end of file occurs when file is


opened, but I/O operations can still occur anywhere in
the file.

3. ios::binary – file is opened in binary mode

4. ios::trunc – causes contents of previous file by the same


filename to be destroyed & file is truncated to 0 length.

5. ios::out

6. ios::in

Eg: ofstream out;


Out.open(“test”,ios::out);

Note: The mode parameter provides default values for each type of
stream, as given in the prototype.

• If open() fails, the stream will evaluate to false when used in


a Boolean expression.

• The ifstream, ofstream and fstream classes have constructor


functions that automatically opens the file.

• The constructor functions have the same parameters & defaults as


the open() function.

• Hence a file can be opened just as


ifstream mystream(“filename”);

UNIT III 25
• To check if a file is successfully opened, use the function
bool is_open(); a member function of fstream, ifstream and
ofstream.

• To close a file use the member function close() – takes no


parameters and returns no value.

Reading and Writing Text Files

• Simply use the << and >> operators the same way as when
performing console I/O, except that instead of using cin and
cout, substitute a stream that is linked to a file.

Eg:
#include <iostream.h>
#include <fstream.h>

int main()
{
ofstream out("INVNTRY"); // output, normal file

if(!out)
{
cout << "Cannot open INVENTORY file.\n";
return 1;
}

out << "Item1 " << 39.95 << endl;


out << " Item2" << 19.95 << endl;
out << " Item3 " << 24.80 << endl;

out.close();

return 0;
}

• When inputting, if the end-of-file is encountered, the stream


linked to that file will evaluate as false.

UNIT III 26
Eg:
#include <iostream.h>
#include <fstream.h>
int main()
{
ifstream in("INVNTRY"); // input
if(!in)
{
cout << "Cannot open INVENTORY file.\n";
return 1;
}

char item[20];
float cost;

in >> item >> cost;


cout << item << " " << cost << "\n";
in >> item >> cost;
cout << item << " " << cost << "\n";
in >> item >> cost;
cout << item << " " << cost << "\n";

in.close();
return 0;
}
Unformatted and Binary I/O

put() and get() - To read and write unformatted data.

• get() reads a char

• istream& get(char &ch);

• reads a char from invoking stream & puts its value in ch.

• Returns a reference to the stream.

• put() writes a char

• ostream& put(char ch);

• writes a char ch to the stream and returns a reference to the


stream.

UNIT III 27
Eg1: #include <iostream.h>
#include <fstream.h>
int main(int argc, char *argv[])
{
char ch;

if(argc!=2)
{
cout << "Usage: PR <filename>\n";
return 1;
}

ifstream in(argv[1], ios::in | ios::binary);


if(!in)
{
cout << "Cannot open file.";
return 1;
}

while(in)
{ // in will be false when eof is reached
in.get(ch);
if(in) cout << ch;
}

return 0;
}

Eg2: #include <iostream.h>


#include <fstream.h>
int main()
{
int i;
ofstream out("CHARS", ios::out | ios::binary);
if(!out)
{
cout << "Cannot open output file.\n";
return 1;
}

// write all characters to disk


for(i=0; i<256; i++)
out.put((char) i);

out.close();
return 0;
}

UNIT III 28
More get() functions

1. istream& get(char *buf, streamsize num);

• Reads a char into the array pointed to by buf until either


num-1 characters have been read , a newline is found or the
end of file has been encountered.

• The array pointed to by buf will be null terminated by


get().

2. istream& get(char *buf, streamsize num, char delim);

• Reads a char into the array pointed to by buf until either


num-1 characters have been read , the character specified
by the delim has been found or the end of file has been
encountered.

• The array pointed to by buf will be null terminated by


get().

3. int get();

• Returns the next character from the stream.

• Returns EOF if end of file is encountered.

• This function is similar to getc() function.

getline()

istream& getline(char *buf, streamsize num);

istream& getline(char *buf, streamsize num, char delim);

• The 2 versions of getline() are virtually identical to the


get() versions.

• The difference is that getline() reads and removes the


delimiter from the input stream ; get(0 does not.

UNIT III 29
Eg: #include <iostream.h>
#include <fstream.h>
int main()
{
ifstream in(“test”); // input

if(!in)
{ cout << "Cannot open input file.\n";
return 1;
}
char str[255];

while(in)
{
in.getline(str, 255); // delim defaults to '\n'

if(in)
cout << str << endl;
}

in.close();
return 0;
}

read() and write()

• To read and write blocks of binary data.

istream& read(char *buf, streamsize num);

ostream& write(const char *buf, streamsize num);

• read() function reads ‘num’ characters from the invoking stream


& puts them in the buffer pointed to by ‘buf’.

• write() function writes ‘num’ characters to the invoking stream


from the buffer pointed to by ‘buf’.

Note:
• The typecasts inside the calls to read() & write() are
necessary when operating on a buffer that is not defined as a
char array.

• Because of C++ strong type checking, a pointer of one type


will not be automatically converted into a pointer of another
type.

UNIT III 30
• To find out how many characters have been read use the member
function called gcount().

streamsize gcount();

Eg:
#include <iostream.h>
#include <fstream.h>

int main()
{
double fnum[4] = {99.75, -34.4, 1776.0, 200.1};
int i;

ofstream out("numbers", ios::out | ios::binary);


if(!out)
{
cout << "Cannot open file.";
return 1;
}

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

out.close();

for(i=0; i<4; i++) // clear array


fnum[i] = 0.0;

ifstream in("numbers", ios::in | ios::binary);

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

// see how many bytes have been read

cout << in.gcount() << " bytes read\n";

for(i=0; i<4; i++) // show values read from file


cout << fnum[i] << " ";

in.close();

return 0;
}

Detecting EOF : bool eof();

It returns true when the end of file has been reached.

UNIT III 31
ignore()

• Function used to read & discard characters from input stream.

• istream& ignore(streamsize num=1, int_type delim=EOF);

• It reads & discards characters until either ‘num’ chars have


been ignored or the char specified by the ‘delim’ is
encountered.

• If the delimiting char is encountered, it is not removed from


the input stream.

Eg:
#include <iostream.h>
#include <fstream.h>

int main()
{
ifstream in("test");

if(!in)
{
cout << "Cannot open file.\n";
return 1;
}

/* Ignore up to 10 characters or until first


space is found. */

in.ignore(10, ' ');

char c;

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

in.close();

return 0;
}

UNIT III 32
peek() and putback()

• We can obtain the next char in the input stream without removing
it from that stream by using peek().

• int_type peek();

• It returns the next char in the stream or EOF if the end of file
is encountered.

• We can return the last char read from a stream to that stream by
using putback().

• istream& putback(char c);

• c is the last read character.

flush()

• We can force the information to be physically written to disk


before the buffer is full by calling flush().

• ostream& flush();

• Closing a file or terminating a program also flushes all


buffers.

Random Access

• We can perform random access by using the seekg() and seekp()


functions.

• istream& seekg(off_type offset, seekdir origin);

• ostream& seekp(off_type offset, seekdir origin);

• ‘off_type’ is an integer defined by ios that is capable of


containing the largest valid value that offset can have.

• ‘seekdir’ is an enumeration defined by ios that determines how


the seek will take place.

UNIT III 33
• The C++ I/O system manages 2 pointers associated with a file.

• One is getpointer, which specifies where in the file the next


input operation will occur.

• The other is the putpointer, which specifies where in the file


the next output operation will occur.

• Using the seekg() and seekp() functions allows you to access the
file in a nonsequential fashion.

• The seekg() function moves the associated file’s current get


pointer ‘offset’ number of characters from the specified
‘origin’, which must be one of the 3 values –

o ios::beg

o ios::cur

o ios::end

• The seekp() function moves the associated file’s current ‘put


pointer’, ‘offset’ number of characters from the specified
‘origin’.

• Generally, random-access I/O should be performed only on those


files opened for binary operations.

Obtaining the current File Position

• We can determine the current position of each file pointer by


using functions –

o pos_type tellg();

o pos_type tellp();

o pos_type is a type defined by ios that is capavle of


holding the largest value that either function can return.

UNIT III 34
Eg:
#include <iostream.h>
#include <fstream.h>
#include <cstdlib.h>

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


{
if(argc!=3)
{
cout << "Usage: Reverse <filename> <num>\n";
return 1;
}

fstream inout(argv[1], ios::in | ios::out | ios::binary);

if(!inout)
{
cout << "Cannot open input file.\n";
return 1;
}

long e, i, j;
char c1, c2;

e = atol(argv[2]);

for(i=0, j=e; i<j; i++, j--)


{
inout.seekg(i, ios::beg);
inout.get(c1);

inout.seekg(j, ios::beg);
inout.get(c2);

inout.seekp(i, ios::beg);
inout.put(c2);

inout.seekp(j, ios::beg);
inout.put(c1);
}

inout.close();

return 0;
}

UNIT III 35
I/O Status

o The current state of I/O system is held in an object of type


‘iostate’, which is an enumeration defined by ‘ios’ that
includes the following members –

1. ios::goodbit – No error bits set.

2. ios::eofbit - 1 when end-of-file is encountered.

3. ios::failbit – 1 when a nonfatal I/O error has occurred.

4. ios::badbit - 1 when a fatal I/O error has occurred.

o There are 2 ways in which we can obtain I/O status information

1. We can call the rdstate() function

o iostate rdstate();

o returns the current status of error flags.

2. By using one or more of the following functions –

o bool bad() – returns true if badbit is set.

o bool eof() – returns true if eofbit is set.

o bool fail() – returns true if failbit is set.

o bool good() – returns true if goodbit is set.

o Once an error has occurred, it may need to be cleared before the


program continues. To do this, use the clear() function.

o void clear(iostate flags=ios::goodbit);

o if ‘flags’ is goodbit (as it is by default), all error flags are


cleared.

UNIT III 36
Eg:
#include <iostream.h>
#include <fstream.h>

void checkstatus(ifstream &in);

int main()
{
ifstream in(“test”);

if(!in)
{
cout << "Cannot open input file.\n";
return 1;
}

char c;

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

checkstatus(in); // check final status

in.close();

return 0;
}

void checkstatus(ifstream &in)


{
ios::iostate i;

i = in.rdstate();

if(i & ios::eofbit)


cout << "EOF encountered\n";

else if(i & ios::failbit)


cout << "Non-Fatal I/O error\n";

else if(i & ios::badbit)


cout << "Fatal I/O error\n";
}

UNIT III 37

You might also like