Anda di halaman 1dari 19

Programming Language Concepts Using C and C++/Exception Handling ...

1 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

Programming Language Concepts Using C and


C++/Exception Handling in C++
Similar to Java, exceptions in C++ are most oftennot always!objects of a class type. That is, instead of
returning a value of a certain type an exception object may be returned from the function. However, one can
also throw an exception object of a primitive type. The following is an example to this unlikely case.
Example: Throwing an exception of a non-object type.
enum ERESULT { arg_neg = -1,

arg_toobig = -2};

long fact(short n) {
if (n < 0) throw arg_neg;
if (n > MAX_ARG) throw arg_toobig;
if (n == 0 || n == 1) return 1;
else return (n * fact(n 1));
} // end of long fact(short)

Other peculiarities of exceptions in C++ are related to the way they are specified and handled. In addition to
listing the exact list of exceptions thrown from a function by means of an exception specification, one can
optionally remove the specification and get the liberty of throwing any exception.
Example: Exception specifications.
// f1 can throw exceptions of types E1 and E2
void f1(...) throw(E1, E2);
// f2 does not throw any exceptions at all
void f2(...) throw();
// f3 can throw exceptions of any type. This might be a good choice
during the initial phases of a project.
void f3(...);

If we explicitly list the exceptions thrown from a function and it turns out that an unexpected
exceptionthat is, an exception that is not listed in the specificationis thrown and not handled in the
function call chain, a call to unexpected(), defined in the C++ standard library, is made. In other words,
detection of specification violations is carried out at run-time. If the control flow never reaches the point
where the unexpected exception is thrown, program will run without a problem.
In line with its design philosophy C++ does not mandate that statements with a potential of throwing an
exception be issued inside a try block. Similar to Java exceptions deriving from RuntimeException,
C++ exceptions need not be guarded. In case we may be able to figure out that the exception never arises
we can remove the try-catch keywords and get cleaner code.
Example: No mandatory try-catch blocks.
Rational divide_by_five(double x) {
Rational rat1 = Rational(x);

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

2 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

Rational nonzero_rat = Rational(5);


Rational ret_rat = rat1.divide(nonzero_rat);
return ret_rat;
} // end of Rational divide_by_five(double)

Contents
1 Exception Class
2 Module
2.1 Interface
2.2 Implementation
2.3 Test Program
3 Input-Output in C++
3.1 The Base Stream Class: ios
3.2 Input Streams
3.3 Output Streams
3.4 File Input and Output
4 Notes

Exception Class
Queue_Exceptions

1.
#ifndef QUEUE_EXCEPTIONS_HXX
2.
#define QUEUE_EXCEPTIONS_HXX
3.

4.
#include <iostream>
5.
using namespace std;
6.

7.
namespace CSE224 {
8.
namespace DS {
9.
namespace Exceptions {

Note our exception class does not have any member fields. In other words, we have no means to identify
details of the situation. All we know is we have a problem, nothing more! Although in our case we do not

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

3 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

need any details about the nature of the problem, this is not always the case.
Take the factorial example for instance. We may want to pass the value of the argument that gave rise to the
exceptional condition. This is equivalent to saying that we want to tell the difference between exception
objects of the same class. As a matter of fact, we may formulate the problem as that of differentiating
between objects of the same class, be that an exception object class or any other. We can do this simply by
adding fields to the class definition.
Fact_Exceptions

class Negative_Arg {
public:
void error(void) {
cerr << "Negative argument " << _arg_value << endl;
} // end of void error(void)
Negative_Arg(short arg) { _arg_value = arg; }
private:
short _arg_value;
} // end of class Negative_Arg
class TooBig_Arg { ... }

Factorial.cxx

...
long fact(short n) throw(Negative_Arg, TooBig_Arg) {
if (n < 0) throw Negative_Arg(n);
if (n > MAX_ARG) throw TooBig_Arg(n);
if (n == 0 || n == 1) return 1;
else return(n * fact(n 1));
} // end of long fact(short) throw(Negative_Arg, TooBig_Arg)
...

10.
class Queue_Empty {
11.
public:

Note the only function of our class has been declared to be static, which means we can invoke it without
ever creating an instance of the class through the class scope operator. Similarly, one can define static
data fields, which are shared by all instances of the class and there is no obligation to access these fields via
objects of the class.

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

4 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

12.
static void error(void) { cerr << "Queue Empty!!!" << endl; }
13.
}; // end of class Queue_Empty
14.
} // end of namespace Exceptions
15.
} // end of namespace DS
16.
} // end of namespace CSE224
17.

18.
#endif

Module
Interface
Queue

1.
#ifndef QUEUE_HXX
2.
#define QUEUE_HXX
3.

4.
#include <iostream>
5.
using namespace std;
6.

7.
#include "ds/exceptions/Queue_Exceptions"
8.
using namespace CSE224::DS::Exceptions;
9.

10.
namespace CSE224 {
11.
namespace DS {

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

5 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

What follows is a forward class declaration. Its purpose is similar to that of forward declaration ala C: we
declare our intention of using a class named Queue_Node and defer its definition to some other place.
Note we cannot declare an object of this type. This is due to the fact that C++ does not let you declare
variables to be of types whose definitions are not completed. Because compiler cannot figure out the amount
of memory required for the object. However, we can declare variables to be pointers or referencesread it
as "constant pointers"to such a class.

12.
class Queue_Node;
13.
class Queue {

In some cases, it is convenient to allow a certain function/class to access the non-public members of a class
without allowing access to the other functions/classes in the program. The friend mechanism in C++ allows a
class to grant functions/classes free access to its non-public members.
A friend declaration begins with the keyword friend. It may appear only within a class definition. In other
words, it is the class that declares a function/class to be its friend, not the other way around. That is, you
cannot simply declare a class as your friend and access its fields.
Since friends are not members of the class granting friendship, they are not affected by the public,
protected, or private section in which they are declared within the class body. That is, friend
declarations may appear anywhere in the class definition.
According to the following declaration, overloaded shift operator (<<) can freely access the internals of the
Queue object, whose reference is passed as the second argument, as if they were public.
Had we chosen to make the shift operator into an instance function we would not have attained our goal.
Take the following example:
cout << q1 << q2;
This statement will first print q1 and then q2 to the standard output file. We can reach the same effect by
the following statements.
cout << q1;
cout << q2;
As a matter of fact, this is what takes place behind the scene. We can see whats happening by applying the
following transformations.
cout << q1 << q2;

cout.operator<<(q1).operator<<(q2);
x.operator<<(q2);

The shift message is sent twice: once to the object named cout and once to the object returned by the first
invocation of the appropriate function (x). This means we need to have a function signature where the value
returned and the first argument are of the same type: ostream or ostream&. Knowing an instance
function takes a pointer to an instance of the class being defined as its implicit first argument, we reach the
conclusion that the shift operator cannot be an instance function of the Queue class. Way out of this is

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

6 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

providing a friend declaration such as the following.

14.
friend ostream& operator<<(ostream&, const Queue&);
15.
public:
16.
Queue(void) : _front(NULL), _rear(NULL), _size(0) { }
17.
Queue(const Queue&);
18.
~Queue(void);
19.
Queue& operator=(const Queue&);
20.
bool operator==(const Queue&);

Note the types used in the exception specifications. The first function can abnormally return throwing a
Queue_Empty object while the second one will return with a pointer to such an object. This should not
come as a surprise. Unlike Java, which creates objects in the heap only, C++ lets you create your objects in
all three regionsthat is, the heap, the run-time stack, and the static data region. Since an exception object
is basically a C++ object, you can create it in any data region you like.
Provided that you declare your exception handlers accordingly, there is not much of a difference between
the following exception specifications.[1] Handler of the first one will expect an object, while the second one
will expect a pointer that points to some area in the heap.[2]

21.
double peek(void) throw(Queue_Empty);
22.
double remove(void) throw(Queue_Empty*);
23.
void insert(double);
24.
bool empty(void);
25.
private:
26.
Queue_Node *_front, *_rear;
27.
unsigned int _size;
28.
}; // end of class Queue

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

7 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

Note all fields of the following class definition are private. There are no functions to manipulate the
objects, either. So, it looks like we need some magic for creating and manipulating an object of the class.
Answer lies in Queue_Nodes relation to Queue: Queue_Node is tightly coupled to Queue. A
Queue_Node object can exist only within the context of a Queue object. This fact is reflected in the friend
declaration. Thanks to this declaration, we can [indirectly] manipulate a Queue_Node object through
operations on some Queue object.

30.
class Queue_Node {
31.
friend class Queue;

Next statement declares the shift operator to be a friend to the Queue_Node class. A similar declaration
had been made in the Queue class, which means that one single function will have the privilege of peeking
into the innards of two different classes.

32.
friend ostream& operator<<(ostream&, const Queue&);
33.
private:
34.
double _item;
35.
Queue_Node *_next;
36.
Queue_Node(double val = 0) : _item(val), _next(NULL) { }
37.
}; // end of class Queue_Node
38.
} // end of namespace DS
39.
} // end of namespace CSE224
40.

41.
#endif

Implementation
Queue.cxx

1.

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

8 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

#include <iomanip>
2.
#include <iostream>
3.
using namespace std;
4.

5.
#include "ds/Queue"
6.
#include "ds/exceptions/Queue_Exceptions"
7.
using namespace CSE224::DS::Exceptions;
8.

9.
namespace CSE224 {
10.
namespace DS {
11.
Queue::
12.
Queue(const Queue& rhs) : _front(NULL), _rear(NULL), _size(0) {
13.
Queue_Node *ptr = rhs._front;
14.
for(unsigned int i = 0; i < rhs._size; i++) {
15.
this->insert(ptr->_item);
16.
ptr = ptr->_next;
17.
} // end of for(unsigned int i = 0; i < rhs._size; i++)
18.
} // end of copy constructor

Our destructor, implicitly invoked by the programmer (through delete in deallocating heap objects) or by
the compiler-synthesized code (in the process of deallocating static and run-time stack objects), deletes all
nodes in the queue and then proceeds with cleaning the room reserved for the fields. Had we forgotten to
remove the items we would have ended up with the picture given below, which is actually the same picture
we would have got without the destructor.

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

9 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

Note the shaded region denotes the memory returned to the allocator by the delete operator itself, not the
destructor.[3] All queue nodes reachable only through the fields in the shaded region have now become
garbage. So, we must remove all queue items when the queue is deleted, which is what we do in the
destructor body.
Note also we do not write the code within a try-catch block. Unlike Java, thats OK with C++; you can
choose to omit the try-catch block if you think they will never happen. In this case, the number of
removals is guaranteed to be as many as the number of items in the queue and this cannot give rise to any
exceptional condition.

20.
Queue::
21.
~Queue(void) {
22.
unsigned int size = _size;
23.
for(unsigned int i = 0; i < size; i++) remove();
24.
} // end of destructor
25.

26.
Queue& Queue::
27.
operator=(const Queue& rhs) {
28.
if (this == &rhs) return (*this);
29.

30.
for(unsigned int i = _size; i > 0; i--) remove();
31.

32.
Queue_Node *ptr = rhs._front;

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

10 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

33.
for(unsigned int i = 0; i < rhs._size; i++) {
34.
this->insert(ptr->_item);
35.
ptr = ptr->_next;
36.
} // end of for(unsigned int i = 0; i < rhs._size; i++)
37.

38.
if (rhs._size == 0) {
39.
_front = _rear = NULL;
40.
_size = 0;
41.
return(*this);
42.
} // end of if(rhs._size == 0)
43.

44.
return (*this);
45.
} // end of assignment operator
46.

47.
bool Queue::
48.
operator==(const Queue& rhs) {
49.
if (_size != rhs._size) return false;
50.
if (_size == 0 || this == &rhs) return true;
51.

52.
Queue_Node *ptr = _front;
53.
Queue_Node *ptr_rhs = rhs._front;
54.

55.
for (unsigned int i = 0; i < _size; i++) {
56.
if (ptr->_item != ptr_rhs->_item)
57.
return false;
58.
ptr = ptr->_next;
59.
ptr_rhs = ptr_rhs->_next;
60.
} // end of for(unsigned int i = 0; i < _size; i++)

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

11 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

61.

62.
return true;
63.
} // end of equality-test operator
64.

65.
double Queue::
66.
peek(void) throw(Queue_Empty) {
67.
if (empty()) throw Queue_Empty();
68.

69.
return(_front->_item);
70.
} // end of double Queue::peek(void)
71.

72.
double Queue::
73.
remove(void) throw(Queue_Empty*) {
74.
if (empty()) throw new Queue_Empty();
75.

76.
double ret_val = _front->_item;
77.
Queue_Node *temp_node = _front;
78.

79.
if (_front == _rear) _front = _rear = NULL;
80.
else _front = _front->_next;
81.

82.
delete temp_node;
83.
_size--;
84.

85.
return ret_val;
86.
} // end of double Queue::remove(void)
87.

88.

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

12 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

void Queue::
89.
insert(double value) {
90.
Queue_Node *new_node = new Queue_Node(value);
91.

92.
if (empty()) {
93.
_front = _rear = new_node;
94.
_size = 1;
95.
return;
96.
} // end of if (empty())
97.

98.
_rear->_next = new_node;
99.
_rear = _rear->_next;
100.
_size++;
101.
} // end of void Queue::insert(double)
102.

103.
bool Queue::
104.
empty(void) { return (_size == 0); }

The following output operator definition makes use of both the Queue and the Queue_Node classes. It first
prints the length of the queue by using a private field of the Queue class and then outputs the contents of
the corresponding queue by traversing each and every node, which are of Queue_Node type. For this
reason we had to make this function a friend to both classes.

106.
ostream& operator<<(ostream& os, const Queue& rhs) {
107.
os << "( " << rhs._size << " )";
108.

109.
if (rhs._size == 0) {
110.
os << endl;
111.

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

13 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

return(os);
112.
} // end of if (rhs._size == 0)
113.

114.
os << "(front: ";
115.
Queue_Node *iter = rhs._front;
116.
while(iter != NULL) {
117.
os << iter->_item << " ";
118.
iter = iter->_next;
119.
} // end of while(*iter != NULL)
120.
os << " :rear )\n";
121.

122.
return(os);
123.
} // end of ostream& operator<<(ostream&, const Queue&)
124.
} // end of namespace DS
125.
} // end of namespace CSE224

Test Program
Queue_Test.cxx

1.
#include <fstream>
2.
#include <string>
3.
using namespace std;
4.

5.
#include "ds/Queue"
6.
using namespace CSE224::DS;
7.

8.
#include "ds/exceptions/Queue_Exceptions"

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

14 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

9.
using namespace CSE224::DS::Exceptions;
10.

11.
int main(void) {
12.
Queue q1;
13.
string fname("Queue_Test.input");
14.
ifstream infile(fname.c_str());
15.

16.
if (!infile) {
17.
cout << "Unable to open file: " << fname << endl;
18.
return 1;
19.
} // end of if(!infile)

Now that the argument to the handler (q) points to some heap memory, we must destroy the region as soon
as we are done with handling the exception. Thats what we do with the delete operator inside the handler.
If we had preferred to pass an object instead of a pointer to an object, as we do in peek, there wouldnt
have been any need for such a clean-up activity; thanks to the code synthesized by the compiler, it would
have been carried out automatically upon exit from the handler.
Observe we could have written the first statement of the handler as Queue_Empty::error(); This is
OK because the sole function in our exception class is static, which means we can call it through the class
name.

21.
try { q1.remove(); }
22.
catch(Queue_Empty* q) { q->error(); delete q; }
23.

24.
for (int i = 0; i < 10; i++) {
25.
double val;
26.
infile >> val;
27.
q1.insert(val);
28.
} // end of for(int i = 0; i < 10; i++)

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

15 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

29.
infile.close();
30.

31.
cout << q1;
32.
Queue q2 = q1;
33.

34.
cout << "Queue 1: " << q1;
35.
cout << "Queue 2: " << q2;
36.

37.
if (q1 == q2) cout << "OK" << endl;
38.
else cout << "Something wrong with equality testing!" << endl;
39.

40.
q2.remove(); q2.remove();
41.
cout << "Queue 2: " << q2;
42.
if (q1 == q2) cout << "Something wrong with equality testing!" << endl;
43.
else cout << "OK" << endl;
44.

45.
return(0);
46.
} // end of int main(void)

Input-Output in C++
Input-output facilities in C++, a component of the standard library, are provided by means of the iostream
library, which is implemented as a class hierarchy that makes use of both multiple and virtual inheritance.
This hierarchy includes classes dealing with input from and/or output to user's terminal, disk files, and
memory buffers.

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

16 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

The attributes of a particular stream type is somehow mangled in its name. For example, ifstream stands
for a file stream that we us as a source of input. Similarly, ostringstream is an in-memory buffera
string objectstream that is used as a sink of output.

The Base Stream Class: ios


Whatever the name of the class being used might be it eventually derives from ios, the base class of the
iostream library. This class contains the functionality common to all streams, such as accessor-mutator
functions for manipulating state and format. In the former group are included the following functions:
iostate rdstate() const: Returns the state of the current stream object, which can be any
combination of the following: good, eof, fail, and bad.
void setstate(iostate new_state):In addition to the already set flags, sets the state of the
stream to new_state. Note this function cannot be used to unset the flag values.
void clear(iostate new_state = ios::goodbit): Sets the state to the value passed in
new_state.
int good(void): Returns true if the last operation on the stream was successful.
int eof(void): Returns true if the last operation on the stream found the end of file.
int fail(void): Returns true if the last operation on the stream was not successful and no data
was lost due to the operation.
int bad(void): Returns true if the last operation on the stream was not successful and data was
lost as a result of the operation.
For manipulating the format, we have
char fill(void) const: Returns the padding character currently in use. The default character
is space.
char fill(char new_pad_char): Sets the padding character to new_pad_char and returns
the previous value.
int precision(void) const: Returns the number of significant digits to be used for output of
floating point numbers. The default value is 6.
int precision(int new_pre): Sets precision to new_pre and returns the previous value.
int width(void) const: Returns the output field width. Default value is 0, which means as
many characters as necessary are used.
int width(int new_width): Sets width to new_width and returns the previous value.
fmtflags setf(fmtflags flag): Sets one of the flags, which are used to control the way
output is produced. flag can have one of the following: (for base value used in output of integral
values) ios::dec, ios::oct, ios::hex, (for displaying floating point values)
ios::scientific, ios::fixed, (for justifying text) ios::left, ios::right,
ios::internal, (for displaying extra information) ios::showbase, ios::showpoint,
ios::showpos, ios::uppercase. As in the next four functions, this function returns the state
that was in effect prior to the call.

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

17 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

fmtflags setf(fmtflags flag, fmtflags mask): Clears the combination of flags passed
in mask and then sets the flags passed in flag.
fmtflags unsetf(fmtflags flag): Reverse of setf, this function makes sure the
combination of flags passed in flag is not set.
fmtflags flags(void) const: Returns the current format state.
fmtflags flags(fmtflags new_flags): Sets the format state to new_flags.

Input Streams
On top of the functionality listed in the previous section, all input streams in C++ provide support for the
following functions.
istream& operator>>(type data): Overloaded versions of the shift-in (or extraction)
operator are used to read in values of various types and can further be overloaded by the programmer.
It can be used in a cascaded manner and in case the input operation is unsuccessful it returns false,
which means it can also be used in the context of a boolean expression.
int get(void): Returns the character under the read head and advances it by one.
int peek(void): Like the previous function, peek returns the character under the read head but
doesn't move it. That is, peek does not alter the stream contents.
istream& get(char& c): Cascaded version of get(void), this function is equivalent to
operator>>(char&). That is
in_str.get(c1).get(c2).get(c3); in_str >> c1 >> c2 >> c3;
istream& get(char* str, streamsize len, char delim = '\n'): Reads a
null-terminated string into str. Length of this string depends on the second and third arguments,
which hold the size of the buffer and the sentinel character, respectively. If len - 1 is scanned
without reading the sentinel character, '\0' is appended to the buffer and returned in the first
argument. If the sentinel character is reached before filling in the buffer, the read head is left on the
sentinel character and all that has been read up to that point with the terminating '\0' is returned in
the buffer.
istream& getline(ctype* str, streamsize len, char delim = '\n'): Similar to
the previous function, getline is used to read a null-terminated string into its first argument.
However, in case the sentinel character is reached before the buffer is filled, the sentinel character is
not left in the stream but read and discarded. Note the type of the first argument is a pointer to one of
char, unsigned char, or signed char.
istream& read(void* buf, streamsize len): Reads len bytes into buf, unless the
input ends first. If input ends before len bytes are read this function sets the ios::fail flag and
returns the incomplete result.
istream& putback(char c): Corresponding to ungetc(char) of C, this function attempts to
back up one character and replace the character that has been backed up with c. Note this operation is
guaranteed to work only once. Consecutive uses of it may or may not work.
istream& unget(void): Attempts to back up one character.
istream& ignore(streamsize len, char delim = traits::eof): This function
reads and discards as many as len characters or all characters up to and including the delim.

Output Streams
Complementing the operations listed in the previous section are the operations applied on an output stream.
Before we give a listing of these operations, we should mention one crucial point: in order for the output
operations to take effect one of the following conditions must be met:
1. An endl manipulator or '\n' is inserted into the stream.
2. A flush manipulator is inserted into or a flush() message is sent to the stream.

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

18 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

3. The buffer attached to the stream is full.


4. An istream object tied to the stream performs an input operation. Tying two streams means their
operations will be synchronized. A popular example is the cin-cout pair: before a message is sent to
cin cout is flushed. That is,

cout << "Your name:";

cout << "Your name:"; cout.flush();


cout << "Your name" << flush;
cin >> name;
cin >> name;
cin >> name;
ostream& operator<<(type data): Overloaded versions of the shift-out (or insertion)
operator are used to write data of various types and can further be overloaded by the programmer.
Like the extraction operator, it can be cascaded.
ostream& put(char c): Inserts c into the current stream.
ostream& write(string str, streamsize len): Inserts len characters of str into the
current stream. Since a string object can be constructed from a [const] char*, the first
argument can also be a C-style character string.

Before moving on to file-oriented streams, we should mention that functionalities of istream and
ostream are combined in the iostream class, which derives from these two classes. That is, one can use
the same stream for input and output at the same time.

File Input and Output


Using ifstream and ofstream one can read from and write to files. Since these classes inherit from the
relevant stream classesistream and ostream, respectivelytheir instances can receive the messages
given in the previous sections. In addition to these one can also use the following list.
ifstream(const char* fn, int mde = ios::in, int prt = 644),
ofstream(const char* fn, int mde = ios::out, int prt = 644): Connects the
stream being constructed to the disk file named fn. The second and third arguments, which are
optional, are used to specify the way the stream can be used. The third argument is specific to
Unix-based operating systems and indicate the file protection bits. The second argument specifies how
to open the disk file and can be a [reasonable] combination of the following:
ios::in: Opens the file for input and locates the read head at the beginning.
ios::out: Opens the file for output. While doing so, the file is truncated.
ios::app: Opens the file for output. File contents are not destroyed and each output operation
inserts data to the end of the file.
ios::bin: Treats the file content as raw data. In environments where '\n' is mapped to a
single byte this is not needed.
ifstream(void)& ofstream(void): Creates a stream object without connecting it to a disk
file.
void open(const char* fn, int mde = def_mde, int prt = 644): Connects a
previously constructed [disconnected] stream object to a disk file.
ios::pos_type tellg/tellp(void): Return the position of the file marker. The last letters, g
for get and p for put, of these functions serve as a reminder of whether the file marker is a read head
or a write head.
void seekg/seekp(pos_type n_p): These functions move the file markerthat is, the read
or write head-to the absolute byte number specified by n_p. seekgread it as "seek to a new location
for the next get"affects the read head while seekpread it as "seek to a new location for the next
put"affects the write head.
void seekg/seekp(off_type offset, ios::seekdir dir): Move by as many as
offset bytes relative to the location specified by dir, which can take one of the following values:
[the beginning of the file] ios::beg, [the current file marker position] ios::cur, and [the end of

20-11-2014 13:07

Programming Language Concepts Using C and C++/Exception Handling ...

19 of 19

http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

the file] ios::end.


As a closing remark of this handout we should mention the possibility of simultaneously reading from and
writing to the same file. In such a case, we can construct a fstream object and use it to achieve our goal.

Notes
1. Actually, there is a difference. Be that a plain object or an exception object, an object created in the
heap is managed by the programmer and must be freed by her
2. As a matter of fact, you can pass a pointer to some area in other parts of the address space such as
the static data or run-time stack regions. But then how are you going to decide whether to free the
region or not? If it points to some place in the heap, it is the programmers responsibility and she must
free the object; if the pointed object is not in the heap its lifetime will be managed by the compiler.
Wed better be more deterministic and create all such objects in the heap or have the handler accept
an extra argument. Or yet better, choose to pass objects, not pointers to object.
3. Observe this is basically the same region that would have been returned with free in the case of a
malloced heap object: the region pointed to by the pointer. This semblance leads us to an informal
definition: delete operator is implicit invocation of the destructor plus free.
Retrieved from "http://en.wikibooks.org
/w/index.php?title=Programming_Language_Concepts_Using_C_and_C%2B%2B
/Exception_Handling_in_C%2B%2B&oldid=2718705"

This page was last modified on 27 October 2014, at 21:14.


Text is available under the Creative Commons Attribution-ShareAlike License.; additional terms may
apply. By using this site, you agree to the Terms of Use and Privacy Policy.

20-11-2014 13:07