IO Streams
- I/O
- Same libraries as C
- iostream classes
Added to allow extensibility to I/O functions and efficiency.
Only the parts you use are loaded.
Only printing strings?
The float printing code isn't needed.
Better compile time error checking. << is called
the inserter and >> called the extractor overloaded
for all C++ types.
You can extend it for your types.
Cout << string
writes string to standard out.
Cerr uses standard error. << operators
can be concatenated.
So
cout << "the data value is " << foo << "\n";
Manipulators act on the iostream.
So
cout << flush;
flushes the output from the stream.
Others include:
Endl |
operator outputs newlines. and flushes the output. |
hex,dec,oct |
change base of output. |
ws |
eat incoming whitespace. |
To print a number in decimal and then hex:
cout << "in decimal " << num << hex << "in hex " << num < endl;
Cout and cerr by themselves don't output newlines.
Cin >> variable reads
from standard in and puts it in var.
It does formatting.
Cin >> string;
cin >> int;
Be wary of reading multiple inputs from a line.
Example,
1 3.0 this is a string.
would be read as an int, a float and the string 'this' as the spaces are
delimiters.
Better to read in a line at a time as characters and then do
conversion.
line input
Two main routines, get() and getline().
Each takes 3 args, pointer
to space to put the input, size of input and delimiter.
Stops reading at delimiter.
get doesn't remove the delimiter from the input, getline does.
Neither puts it in the buffer.
get with no args returns the next single
char or EOF as an int.
get with one reference character parameter put a
char in the variable.
There is also a read() member function.
First arg is the destination memory and the second is the number of bytes.
There is a write() function that goes the other way.
All iostreams have member functions to check status.
These are good(), bad(), eof() and fail().
The clear() function can be used to clear an error state indicated
by the functions above.
For example, an EOF will indicate both eof and fail.
But if you are seeking around in it, just clear the errors and go on.
To read until
EOF, do
while(cin)
{
} //while
file input
Include fstream.h to use this. Files can be safely opened using file
streams. Closing these is handled by the destructor. Open an input file
with
{
ifstream in("myfile"); // input
assert(in);
ofstream out("myotherfile"); // output
assert(out);
To read a file and print it
while(in.getline(buf,SIZE)) {
cout << buf << endl // standard out
out << buf << endl //file output
} // while
}
Note that at this point, the file opens go out of scope and are closed
by the destructors.
So we can do
{
ifstream in("myotherfile"); // input
ofstream out("mffile"); // output
while(in.getline(buf,SIZE)) {
cout << buf << endl // standard out
out << buf << endl //file output
} // while
}
to copy it back. There is an internal method on streams that allows the
entire contents of the buffer to be dumped. The above code could be replaced
by:
{
ifstream in("myotherfile"); // input
ofstream out("mffile"); // output
out << in.rdbuf();
}
You could also explicitly call the close() member function.
open flags
Just like fopen() in C, you can specify how to open the files using flags.
This table is from page 217 of the text.
ios::in |
open for input. if used in ofstream, doesn't truncate file |
ios::out |
open for output. Truncates file. |
ios::app |
open for appending. |
ios::ate |
open existing file and seek to end. |
ios::nocreate |
open only if already exists. |
ios::noreplace |
open only if it doesn't exist. |
ios::trunc |
open and delete if it already exists. |
ios::binary |
opens in binary mode, default is text. |
file positioning
There are two ways to put the file pointer at a particular position
in the file.
The Standard C function seek() has an analogue here.
There is also a new technique called streampos a stream pos
is a typedef for a long.
A streampos is like a bookmark placed in the stream.
the member function tellp() for ostreams and tellg() for istreams
returns a streampos.
These are rather like the tell() function in standard C.
streampos inp = n.tellg()
will return the current byte position within the file.
ifstream in("myfile");
in.seekg(0,ios::end); // seek 0 bytes from the end
streampos sp = in.tellg(); // contains the size of the file
in.seek(-sp/2,ios::end); // seek half way from end
streampos sp2 = in.tellg(); // points to half way mark
// do some other stuff
in.seekg(sp2); // seek back to middle
ios::beg |
from beginning |
ios::cur |
from here |
ios::end |
from end |
string streams
This allows you to use the same I/O techniques on internal memory.
In some ways this is like using sprintf().
istrstream str("hello 2 c");
int i; char b;
char greeting[15];
str >> greeting;
str >> i >> b;
strstream constructors can either take a single argument which is assumed
to be a 0 terminated string or two args, where the second is the size of
the array pointed to by the first.
Output strstreams have one constructor
that takes three args.
They are the pointer to the array to be written
into, the length of that array and the mode.
If the mode is missing, the
writing starts at the front of the array.
If the mode is either ios::ate
or ios::app, the array is assumed to be a 0 terminated array, and the new
characters are added to the end.
char buffer[32];
ostrstream str(buffer,32,ios::app);
int i=7; char b='c';
char greeting[] = "hello";
str << endl; // initialize
str << i << endl; // add a newline
str << b << endl;
str << greeting << endl;
str << ends; // puts a 0 in the end
automatic storage allocation
If you create an ostrstream without arguments, you get an object where
you don't have to specify the amount of storage.
ostrstream A;
So you can add data to it all day, without worrying about running out of
memory.
A << "hello there" << endl;
A << i << endl;
// more stuff
To print this, you use a trick called streambuffs to access the internal
buffers.
cout << A.rdbuff();
You can get at the actual string by doing
char * strptr = A.str();
However, this closes the strstream and you can't add more characters to it.
This is to prevent the memory pointed to by strptr from becoming invalid,
should the strstream reallocate.
There is a way to reopen a strstream, but we will cover it later.
There probably isn't much need to do that.
Compare all this to sprintf() and such.
output formatting
There are member functions on ostreams to do all the things printf()
can do and some others.
There are also manipulators to do some of this.
The ios class contains the data to handle the formatting for an ostream.
The member function setf() changes the state of formatting flags.
Many are simple on/off flags but some are more complicated.
See page 234 for details.
ios::skipws |
skip white space |
ios::showbase |
indicate the base when printing an integer |
ios::showpoint |
show decimal point and trailing 0 for floats |
ios::uppercase |
uppercase hex digits |
ios::showpos |
show plus for positive integers |
ios::unitbuf |
flush stream after each insertion |
ios::stdio |
synchronizes with stdio system |
so
cout.setf(ios::showpos);
turns on the display of + for integers.
Turn it off with
cout.unsetf(ios::showpos);
use the ios::stdio flag is your program is doing both iostream and stdio
I/O. and the outputs are appearing in the wrong order.
There are groups of flags that work like radio buttons.
Only one can be set.
To help this,
since setf(flag) would allow you to set multiple, there are named groups
and a 2 arg version of setf().
See page 243 for details.
ios:basefield |
|
ios::dec |
format ints in base 10 |
ios::hex |
format in hex |
ios::oct |
format in octal |
ios::floatfield |
|
ios::scientific |
use scientific notation on floats |
ios::fixed |
fixed format for floats |
neither |
automatic choice |
ios::adjustfield |
|
ios::left |
left justify |
ios::right |
right justify |
ios::internal |
add fill after sign but before value |
These are set by
cout.setf(ios::hex,ios::basefield);
There are set of functions to set and read the width of fields, the precision
and the fill character.
int ios::width(),width(int) |
read or set the width of the field |
int ios::fill(),fill(int) |
read or set the fill character |
int ios::precision(),precision(int) |
read or set the float precision |
They all return the previous value when set.
The width field functions
like the width in the %s format.
It specifies the minimum width.
making manipulators
It is easy to make manipulators of your own.
A manipulator like endl
is just a function that takes a ostream as an argument.
ostream& endl(ostream&);
So to make one that outputs a newline but doesn't flush the output,
ostream&
nl(ostream& os)
{
return os << '\\n';
} // nl
this can be used just like endl.
count << "here is a string with a newline" << nl;