C++ I/O System
I/O System Basics
• supports two complete I/O systems:
– I/O system inherited from C
– object-oriented I/O system defined by C++
• console I/O and disk I/O, are actually just different perspectives on the same mechanism.
• I/O library is supported by the header <iostream>.
Need for new I/O system
• C's I/O system knows nothing about objects.
• C++ I/O system operates on user-defined objects.
• The C I/O is supported by C++ only for compatibility.
C++ Streams
• the C++ I/O system operates through streams.
• A stream is a logical device that either produces or consumes information.
• A stream is linked to a physical device.
• All streams behave in the same way.– (i.e) same function that writes to a file to write to the printer
or to the screen
The C++ Stream Classes
• In <iostream> complicated set of class hierarchies , that supports I/O Operations are defined .
• The I/O classes begin with a system of template classes.
• C++ creates two specializations of the I/O template classes:– one for 8-bit characters and another for wide
characters.
• There are two different template class hierarchies.
• basic_streambuf -> supports basic, low-level input and output operations
• Used widely in advanced I/O programming.
• basic_ios -> Commonly used , it provides formatting, error checking, and status information related to stream I/O.
basic_ios
basic_istream basic_ostream basic_iostream
(input) (output) (input/output)
Template Character Wide-Character
Class basedClassbasedClass
basic_streambuf streambuf wstreambufbasic_ios ios wiosbasic_istream istream wistreambasic_ostream ostream wostreambasic_iostream iostream wiostreambasic_fstream fstream wfstreambasic_ifstream ifstream wifstreambasic_ofstream ofstream wofstream
C++'s Predefined Streams
Stream Meaning Default Devicecin Standard input Keyboardcout Standard output Screencerr Standard error output Screenclog Buffered version of cerr Screen
• four built-in streams are automatically opened, when execution begins
• Streams cin, cout, and cerr correspond to C's stdin, stdout, and stderr.
• By default they communicate with the console
Formatted I/O
• To format the display to the user.
• There are two different ways,– directly access members of the ios class– special functions called manipulators can be
used
Formatting Using the ios Members
• For each stream there are set of format flags that control the way information is formatted.
• ios class declares a bitmask enumeration called fmtflags – it contains the values.
adjustfield basefield boolalpha dec
fixed floatfield hex internal
left oct right scientific
showbase showpoint showpos skipws
unitbuf uppercase
• Skipws -> leading white-space characters are discarded
• Left -> output is left justified (output is right justified by default)
• Oct -> output to be displayed in octal.(default decimal)
• Showbase-> the base of numeric values
• Uppercase-> characters are displayed in uppercase
• Scientific-> floating-point numeric values are displayed using scientific notation.
• Fixed-> floating-point values are displayed using normal notation.
• The oct, dec, and hex => basefield.
• The left, right, and internal => adjustfield.
• The scientific and fixed fields => floatfield.
Setting the Format Flags
• setf() function, member of ios is used to set the flags.
fmtflags setf(fmtflags flags);
• General format:– stream.setf( ios::showpos );
Any predefined stream an enumerated constant defined by the ios class
#include <iostream>using namespace std;int main(){
cout.setf(ios::showpoint);cout.setf(ios::showpos);cout << 100.0; // displays +100.0return 0;
}
// You can OR together two or more flags,cout.setf(ios::showpoint | ios::showpos);
Clearing Format Flags
• unsetf function member of ios is used to clear the flags
• Prototype:void unsetf(fmtflags flags);
#include <iostream>using namespace std;int main(){
cout.setf(ios::uppercase | ios::scientific);cout << 100.12; // displays 1.0012E+02cout.unsetf(ios::uppercase); // clear uppercasecout << " \n" << 100.12; // displays 1.0012e+02return 0;
}
An Overloaded Form of setf( )
• Prototype:fmtflags setf(fmtflags flags1, fmtflags flags2);
• only the flags specified by flags2 are affected
• first cleared and then set according to the flags specified by flags1.
#include <iostream>
using namespace std;
int main( )
{
cout.setf(ios::showpoint | ios::showpos, ios::showpoint);
cout << 100.0; // displays 100.0, not +100.0
return 0;
}
#include <iostream>
using namespace std;
int main()
{
cout.setf(ios::hex, ios::basefield);
cout << 100; // this displays 64
return 0;
}
#include <iostream>using namespace std;int main(){
cout.setf(ios::showpos, ios::hex); // error, showpos not setcout << 100 << '\n'; // displays 100, not +100cout.setf(ios::showpos, ios::showpos); // this is correctcout << 100; // now displays +100return 0;
}
Examining the Formatting Flags
• Prototype:fmtflags flags( );
• Used to know the current format settings.
• Flags cannot be altered.
• Is a member function of base class ios
#include <iostream>using namespace std;void showflags() ;int main(){// show default condition of format flagsshowflags();cout.setf(ios::right | ios::showpoint |
ios::fixed);showflags();return 0;}// This function displays the status of the
format flags.void showflags(){ios::fmtflags f;long i;f = (long) cout.flags(); // get flag settings
// check each flagfor(i=0x4000; i; i = i >> 1)if(i & f) cout << "1 ";else cout << "0 ";cout << " \n";}
Output:
0 0 0 0 0 1 0 0 0 0 0 0 0 0 10 1 0 0 0 1 0 1 0 0 1 0 0 0 1
Setting All Flags
#include <iostream>using namespace std;void showflags();int main(){
// show default condition of format flagsshowflags();// showpos, showbase, oct, right are on, others offlong f = ios::showpos | ios::showbase | ios::oct | ios::right;cout.flags(f); // set all flagsshowflags();return 0;
}
Using width( ), precision( ), and fill( )
• Prototype:streamsize width(streamsize w);streamsize precision(streamsize p);
char fill(char ch);
#include <iostream>using namespace std;int main(){cout.precision(4) ;cout.width(10);cout << 10.12345 << "\n"; // displays 10.12cout.fill('*');cout.width(10);cout << 10.12345 << "\n"; // displays *****10.12
// field width applies to strings, toocout.width(10);cout << "Hi!" << "\n"; // displays *******Hi!cout.width(10);cout.setf(ios::left); // left justifycout << 10.12345; // displays 10.12*****return 0;}
Output:
10.12*****10.12*******Hi!10.12*****
Using Manipulators to Format I/O
• I/O manipulators parallel member functions of the ios class.
• To access manipulators you should include <iomanip>
Some manipulators
//program using manipulators
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
cout << hex << 100 << endl;
cout << setfill('?') << setw(10) <<2343.0;
return 0;
}
Output :
64
??????2343
//program using flags
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
cout.setf(ios::hex, ios::basefield);
cout << 100 << "\n"; // 100 in hex
cout.fill('?');
cout.width(10);
cout << 2343.0;
return 0;
}
Advantage of manipulators : more compact code to be written
• the setiosflags() manipulator can also be used.
#include <iostream>#include <iomanip>using namespace std;int main(){
cout << setiosflags(ios::showpos);cout << setiosflags(ios::showbase);cout << 123 << " " << hex << 123;return 0;
}
Overloading << and >>
• These operators can be overloaded to perform I/O operations.
• << output operator => insertion operator (inserters)
• >> input operator => extraction operator (extractors)
Inserters
• Skeleton :ostream &operator<<(ostream &stream,
class_type obj){
// body of inserterreturn stream;
}• ostream => output stream.• 1st parameter =>reference to ostream .• 2nd parameter => reference to an object• This function should return stream
class phonebook {
public:
char name[80];
int areacode;
int prefix;
int num;
phonebook(char *n, int a, int p, int nm)
{
strcpy(name, n);
areacode = a;
prefix = p;
num = nm;
}
};
// Display name and phone number
ostream &operator<<(ostream &stream, phonebook o)
{
stream << o.name << " ";
stream << "(" << o.areacode << ") ";
stream << o.prefix << "-" << o.num << "\n";
return stream; // must return stream
}
inserter function for objects of type phonebook
#include <iostream>#include <cstring>using namespace std;class phonebook {public:char name[80];int areacode;int prefix;int num;phonebook(char *n, int a, int p, int nm){strcpy(name, n);areacode = a;prefix = p;num = nm;} };// Display name and phone number.ostream &operator<<(ostream &stream, phonebook o){stream << o.name << " ";stream << "(" << o.areacode << ") ";stream << o.prefix << "-" << o.num << "\n";return stream; // must return stream}
int main(){phonebook a("Ted", 111, 555, 1234);phonebook b("Alice", 312, 555, 5768);phonebook c("Tom", 212, 555, 9991);cout << a << b << c;return 0;}
Output:Ted (111) 555-1234Alice (312) 555-5768Tom (212) 555-9991
• Inserter is not a member function (to invoke a member the object should be on the left side)
• when you overload inserters, the left operand is a stream and the right operand is an object of the class
• Inserters are not member functions, hence to access the private data, they can be made as friends of the class.
#include <iostream>#include <cstring>using namespace std;class phonebook {char name[80]; // now privateint areacode;int prefix;int num;public:phonebook(char *n, int a, int p, int nm){strcpy(name, n);areacode = a;prefix = p;num = nm;}friend ostream &operator<<(ostream &stream, phonebook o);};
// Display name and phone number.ostream &operator<<(ostream &stream, phonebook o){stream << o.name << " ";stream << "(" << o.areacode << ") ";stream << o.prefix << "-" << o.num << "\n";return stream; // must return stream}
int main(){phonebook a("Ted", 111, 555, 1234);phonebook b("Alice", 312, 555, 5768);phonebook c("Tom", 212, 555, 9991);cout << a << b << c;return 0;}
} keep the streams as general as possible
Extractors
• Skeleton:istream &operator>>(istream &stream, class_type &obj)
{
// body of extractor
return stream;
}
• istream => input stream.• 1st parameter =>reference to istream.• 2nd parameter => reference to an object
Extractor for phonebook class:
istream &operator>>(istream &stream, phonebook &o){
cout << "Enter name: ";stream >> o.name;cout << "Enter area code: ";stream >> o.areacode;cout << "Enter prefix: ";stream >> o.prefix;cout << "Enter number: ";stream >> o.num;cout << "\n";return stream;
}
/* Cout is used when the program interacts with console else these can be removed */
It can be made safe by defining it like,
If ( stream == cin ) cout << "Enter name: ";