An Application of Operator Overloading: The iostream Library

This library allows you to use the << notation for output, as in C++. The current implementation is just a sketch of what is possible, and allows the basic functionality, but it is NOT 100% compatible with the very complex iostream library of C++. The reasons are many, the principal being that C is not C++, and classes and other C++ constructs are not recognized.[1]

 

This will still allow you to compile C++ code with minimal changes.

 

The iostream library is based on the iostream structure, defined in iostream.h.

Two types of iostreams are defined:

·        File based: The stream uses a FILE structure and when you write into it, you actually write to that file. You should first open a file in the usual way with fopen, or use one of the predefined standard file names (stdout for instance).

·        String based: The stream uses a fixed or a resizable string buffer. When you write to this stream you append characters to the string buffer. If the string buffer is resizable, it will automatically be reallocated when full.

 

Creating a Stream

A stream can be created using two functions:

1.      iostream_new_from_file(FILE *); This function will create a file based iostream using the given file name.

2.      iostream_new_from_string(char *,int); This function will create a string based stream using the given character string buffer and its length.

 

Input arguments

Meaning

Input string is null and length is zero

Create a resizable stream and allocate the initial buffer to it. This is the most common situation.

Input string is null and length is non-zero

Create a non-resizable stream of the given length, allocate the initial buffer.

Input string is non-null and length is zero

Create a resizable stream using a copy of the given string. The current location will be at the end of the given string.

Input string is non-null and length is non-zero

Create a non-resizable string based stream, using the given buffer. When the buffer is full, the write operations will not affect the stream in any way.

 

Examples:

 

     // the stream is string based and resizable.

      // The initial buffer is allocated.

    iostream *ios = iostream_new_from_string(NULL,0);

 

 

     // The stream is string based but not resizable.

     iostream *ios = iostream_new_from_string(NULL,4096);

 

     // Create a resizable, string-based stream and use the

// initial contents of the given string.

     iostream *ios = iostream_new_from_string(“Results:”,0);

 

     // Create a fixed, string-based stream using the given buffer.

     iostream *ios = iostream_new_from_string(buffer,sizeof(buffer));

 

Using iostreams

Below is a very simple example:

 

#include <iostream.h>

int main(void)

{

     iostream *cout = iostream_new_from_file(stdout);

 

     cout << "Hello" ;

     cout << "world" << “\n”;

}

 

This example will produce the well-known words in your screen. Note that “\n” and NOT ‘\n’, is used, since single quotes are not supported. The problem is that in C, single quotes are just integers, which will provoke the numerical value of the character to be added to the stream instead of the character itself.

 

Iostream Modifiers

int iostream_set_width(iostream *i,int w);

This function will restore the previous field width value.

·        You can change the base used for numerical conversions with:

int iostream_set_base(iostream *,int);

This function will restore the previous base in use. To just query the current base use:

int iostream_get_base(iostream *);

This will restore the current base in use.

You can change the current position with:

int iostream_seek(iostream *ios,unsigned long where,int how);

The argument for these functions is identical to the fseek function of the standard library. Note that with string-based streams, the buffer will be extended to have at least the size requested.

You can obtain the current position of a stream with:

int iostream_tell(iostream *);

You can format an integer by grouping the numbers of three characters using the:

int iostream_set_thousands(iostream *,int);

If the given integer is different from zero, the thousands flag will be activated, if it is zero, it will be deactivated. Note that this flag applies only to integers, not to floating point values. The flag can be queried using the function:

int iostream_get_thousands(iostream *);

You can change the precision of the display for floating point data using:

int iostream_set_precision(iostream *,int);

and query the value of the precision with:

int iostream_get_precision(iostream *);

Note that values up to 255 can be stored in this field, but only values up to 15 are useful.

Embedding Modifiers

Some modifiers can be embedded in the stream. For instance:

#include <iostream.h>

int main(void)

{

     iostream *cout = iostream_new_from_file(stdout);

 

cout << "Changing the output base\n";

a = 12345;

cout << "Decimal: " << a << oct << " Octal "

<< a << " Hex: " << hex << a << "\n";

}

 

This will produce the following output:

Changing the output base

Decimal: 12345 Octal 30071 Hex: 3039

 

The modifiers are:

·        flush Flushes the stream. No effect on string- streams.

·        dec Sets the integer base to decimal

·        oct Sets the integer base to octal

·        hex Sets the integer base to hexadecimal.

 



[1] The objective for this first version is just a minimal functionality, and some compatibility with C++, but not 100% compatibility.