个人觉得C++的iostream用起来是非常方便的,只需要使用简单的<<和>>运算符就可以方便的进行各种类型的数据的格式化输入输出。而且C++中的iostream在编译阶段完成输入输出的格式化解析的,比C中的printf()和scanf()在运行时格式化解析要更加安全和强大。在这个系列中我就来详细的介绍一下C++中各种输入输出流的用法。
首先来大致了解一下C++中的iostreams,我们用到的所有的相关的内容都会定义在下面的这些头文件里:
<fstream> <iomanip>
<ios> <iosfwd>
<iostream> <istream>
<ostream> <sstream>
<streambuf> <strstream>
这其中我们用到最多的可能就是<iostream>,毕竟几乎任何C++的教程都会以这个基础。当然这个头文件里面还有一些我们可能没有用到过的全局对象,在这里也全部列出来:
cerr Specifies the cerr global stream.
cin Specifies the cin global stream.
clog Specifies the clog global stream.
cout Specifies the cout global stream.
wcerr Specifies the wcerr global stream.
wcin Specifies the wcin global stream.
wclog Specifies the wclog global stream.
wcout Specifies the wcout global stream.
这些都是全局的对象,在包含了<iostream>之后我们就可以直接使用这些对象。至于怎么使用这些对象就不说了。
因为我们在头文件中常常只写一些声明,而不喜欢在头文件中去引用全局对象,因为这样会涉及到对象的初始化问题,这是个比较复杂的问题,幸运的是,C++的iostreams的设计者以一套非常完善的方法来解决了这个问题,基本上我们可以在需要的时候(例如在头文件中声明重载<<运算符的函数)在头文件中任意的去include这些库头文件而不会出现问题。但是其实C++标准库已经为我们提供了一个更为规范的头文件,向前引用声明(Declare forward references)头文件<iosfwd>。在这个头文件中只有一些声明,并不包含定义,当我们需要在头文件中向前引用申明的时候,就可以包含这个头文件。查看这个头文件的内容也可以让我们清楚的了解到各种类的原型,这个头文件中的部分内容如下:
类型声明:
typedef T1 streamoff;
typedef T2 streamsize;
typedef fpos streampos;
// wchar_t TYPE DEFINITIONS
typedef basic_ios<char, char_traits<char> > ios;
typedef basic_streambuf<char, char_traits<char> > streambuf;
typedef basic_istream<char, char_traits<char> > istream;
typedef basic_ostream<char, char_traits<char> > ostream;
typedef basic_iostream<char, char_traits<char> > iostream;
typedef basic_stringbuf<char, char_traits<char> > stringbuf;
typedef basic_istringstream<char, char_traits<char> > istringstream;
typedef basic_ostringstream<char, char_traits<char> > ostringstream;
typedef basic_stringstream<char, char_traits<char> > stringstream;
typedef basic_filebuf<char, char_traits<char> > filebuf;
typedef basic_ifstream<char, char_traits<char> > ifstream;
typedef basic_ofstream<char, char_traits<char> > ofstream;
typedef basic_fstream<char, char_traits<char> > fstream;
// wchar_t TYPE DEFINITIONS
typedef basic_ios<wchar_t, char_traits<wchar_t> > wios;
typedef basic_streambuf<wchar_t, char_traits<wchar_t> > wstreambuf;
typedef basic_istream<wchar_t, char_traits<wchar_t> > wistream;
typedef basic_ostream<wchar_t, char_traits<wchar_t> > wostream;
typedef basic_iostream<wchar_t, char_traits<wchar_t> > wiostream;
typedef basic_stringbuf<wchar_t, char_traits<wchar_t> > wstringbuf;
typedef basic_istringstream<wchar_t, char_traits<wchar_t> > wistringstream;
typedef basic_ostringstream<wchar_t, char_traits<wchar_t> > wostringstream;
typedef basic_stringstream<wchar_t, char_traits<wchar_t> > wstringstream;
typedef basic_filebuf<wchar_t, char_traits<wchar_t> > wfilebuf;
typedef basic_ifstream<wchar_t, char_traits<wchar_t> > wifstream;
typedef basic_ofstream<wchar_t, char_traits<wchar_t> > wofstream;
typedef basic_fstream<wchar_t, char_traits<wchar_t> > wfstream;
模板类的向前申明:
template<class _Statetype>
class fpos;
template<class Elem>;
class char_traits;
class char_traits<char>;
class char_traits<wchar_t>;
template<class _Ty>
class allocator;
class ios_base;
template<class Elem, class Tr = char_traits<Elem> >
class basic_ios;
template<class Elem, class Tr = char_traits<Elem> >
class istreambuf_iterator;
template<class Elem, class Tr = char_traits<Elem> >
class ostreambuf_iterator;
template<class Elem, class Tr = char_traits<Elem> >
class basic_streambuf;
template<class Elem, class Tr = char_traits<Elem> >
class basic_istream;
template<class Elem, class Tr = char_traits<Elem> >
class basic_ostream;
template<class Elem, class Tr = char_traits<Elem> >
class basic_iostream;
template<class Elem, class Tr = char_traits<Elem> >
class basic_stringbuf;
template<class Elem, class Tr = char_traits<Elem> >
class basic_istringstream;
template<class Elem, class Tr = char_traits<Elem> >
class basic_ostringstream;
template<class Elem, class Tr = char_traits<Elem> >
class basic_stringstream;
template<class Elem, class Tr = char_traits<Elem> >
class basic_filebuf;
template<class Elem, class Tr = char_traits<Elem> >
class basic_ifstream;
template<class Elem, class Tr = char_traits<Elem> >
class basic_ofstream;
template<class Elem, class Tr = char_traits<Elem> >
class basic_fstream;
这样我们就知道了原来我们一直在使用的这些类型都是一些模板类啊,是的,正是使用的C++的模板类这一机制才使得了iostreams能很好的支持wchar_t类型(Unicode),是需要在我们使用的时候在类型的前面加上一个w就ok了,就像支持宽字符的字符串类型wstring。这样的设计思路是值得我们学习的,C++中还有很多类似的东西,只有用这样类似的设计方法你才能说你C++还不错了。
我在这里并不对这里的一些我们没见过的类型做详细的分析了,因为有些东西我们基本是用不到的,而在这个系列我也只讲一些比较常用的C++ Iostreams的用法,所以大家也不用太详细的去看上面的东西了。
可以看到我们常用的类型有:istream, ostream, ifstream, ofstream, istringstream, ostringstream, streambuf.(当然前面加w的,由于是模板类,所以其用啊都相同啦)
本系列将从以上这些类型来详细讲解C++ 标准库中iostreams的用法,本人也是新手,大部分内容会参考MSDN,有什么错的地方或者不完善的地方希望大家帮忙指出。