东阳的学习记录
IOStream定义了数个型别为 istream 和 ostream的全局对象,它们对应于标准的 I/O 通道(channels):
将 正常输出
和错误信息的输出
加以分离,可以让程序员以不同的方式对待两种输出,例如将正常输出重定向到某个文件,同时令错误输出依旧打印到控制台。
即operator <<
和 operator >>
操纵器是专门用来操纵 stream 的对象,常常只会改变输入或格式化输出的解释方式。用于 ostreams的操作器不会凭空创造数据, 用于istreams 的操纵符也不会吃掉任何输入
std::cout << std::endl
:输出’\n’,并刷新output缓冲区std::cout << std::ends
:输出’\0’std::cout << std::flush
:刷新output缓冲区std::cin >> std::ws >> strTemp
: 读入并忽略空格与字符型别及其相应字符特性(traits)无关
的属性,主要包括状态和格式标志等组件和函数。basic_ios<>
, 定义出与字符型别及其相应字符特性(traits)相关
的 stream class共同属性,其中包括 stream 所用的缓冲器。缓冲器所属类别派生自 template class basic_streambuf<>,其具现参数和 basic_ios一样。basic_streambuf<> 负责实际的读写操作.
basic_istream<>
和 basic_ostream<>
两者都虚继承自 basic_ostream
,分别定义出读/写的对象。和basic_ios<>
一样 ,他们以字符型别及其特性(traits
)作为参数就行了,iostream / ostream都是以 char 实现的basic_iostream<>
派生自 (多重继承) basic_istream<>
和 basic_ostream<>
,用来定义即可以读,又可以写的对象。basic_streambuf<>
是IOStream程序库的核心,定义出所有可改写的stream
或 可读取的 stream
的接口。其他的stream class 均利用它进行实际的字符读写操作程序中为处理某些外部表达
,必须从 basic_streambuf<>
派生一些类别。各个 stream class的定义分散于以下数个头文件中:
:内含 stream classes
的前置声明。这个文件是必要
的,因为前置声明不能只是简单地写一句诸如 class ostream
这样的声明就行
:内含 stream buffer
基类(basic_streambuf<>
)的定义。
: 内含仅支持输入的类别(basic_istream
)和同时支持输入输出的类别(basic_iostream<>
)的定义
:内含 basic_ostream<>
的类别定义
:内含全局性的 stream
对象(例如cin, cout)的定义操作符 <<
和 >>
可以直接用于读取或改写 stream buffer
,这恐怕是运用 C++ I/O streams 来拷贝文件的最快方法
Stream 维护着一种状态,标志 I/O 是否成功,并且能够指出不成功的原因。
其它位均被清为0
。读入格式错误
。stream
因不明原因而损坏或丢失数据
,那就设立这个位。注意:eofbit 常常和 failbit同时被设立
在C++中,如果设立了 failbit
,除非显示予以清除
,否则无法进行下一个操作。请注意:被设立的位只是反映过去曾发生的事。
如果某次操作后发现某个位被设立了,我们无法确定到底是这一次还是先前动作导致了这个结果。因此如果想要通过标志了解错误,操作前应先设立goodbit
(如果尚未设立的话)。此外,清除标志之后各项操作可能得到不同的结果
。
streams 定义了两个可用于布尔表达式的函数。
while (std::cin) { /.../ }
if (std::cin >> x) {
// reading x was successful
}
标准化之后的 stream 允许我们对任何一种状态标志进行定义:此一状态标志被设立时是否引发异常
会引发异常
的标志// throw exceptions for all "errors"
strm.exceptions(std::ios::eofbit | std::ios::failbit |
std::ios::badbit);
stream 可用来存取文件。C++标准程序库提供了四个 template class
,并定义了四个标准特化版本:
为了准确控制文件处理模式,class ios_base
定义了一组标志,其型别是 openmode,这是类似 fmtflags 的一种位掩码型别
(bit mask type)
文件必须存在
注意:清空而后改写
请注意:若要打开一个写文件而不清除文件内容的话, 必须以 out | app 的模式打开
绝对读取位置
相对读取位置
绝对写入位置
相对写入位置
松耦合
你可以把一个 stream 连接到一个 output stream 身上。这意味着两者的缓冲区是同步
的。
output stream
的指针// predefined connections
std::cin.tie(&std::cout);
std::wcin.tie(&std::wcout);
// 程序在真正请求输入之前,一定会先清空 output 缓冲区
std::cout << "please enter x:" ;
std::cin >> x;
// 删除上面的连接
std::cin.tie(static_cast<std::ostream*>(0))
你也可以将一个output stream 连接到另一个 output stream 上。下面语句就保证在对着 error stream 写东西之前,先清空正常的 output 缓冲区
// tie cout to cerr
std::cerr.tie(&std::cout);
紧耦合
透过函数 rdbuf()
,可以使不同的streams共享同一个缓冲区
,从而实现紧耦合
/*
* rdbuf1.cpp
*
* Created on: 2021年1月12日
* Author: san
*/
#include
#include
using namespace std;
int main()
{
// stream for hexadecimal standard output
ostream hexout(cout.rdbuf());
hexout.setf(ios::hex, ios::basefield);
hexout.setf(ios::showbase);
// switch between decimal and hexadecimal output
hexout << "hexout: " << 177 << " "; // 输出 hexout: 0xb1
cout << "cout: " << 177 << " ";
hexout << endl;
}
独立于直接I/O以外的方式来处理I/O
利用函数str()
,字符序列可以和其调用者一起共同管理内存,除非 stream 被初始化为定长缓冲区
,否则,必须遵守下面三个原则:
delete[]
来释放字符序列并不安全。最安全的做法是调用成员函数 freeze()
并给予参数 false
,将内存传会stream\0
。我们只有直接在 stream
内加上该特殊符号,才能结束字符序列。这可以通过操纵器 ends
完成。float x;
...
std::ostrstream buffer; //dynamic char* stream
// fill char* stream
buffer << "float x: << x << std::ends;
/* pass resulting C-string to foo()
- freezes the char* stream
*/
foo(buffer.str());
// unfreeze the char* stream
// 将内存传回 stream
buffer,freeze(false);
自定义一个读取分数的 >>
// io/fraclin.hpp
#include
inline std::istream &operator >> (std::istream &strm, Fraction &f)
{
int n, d;
strm >> n;
strm.ignore();
strm >> d;
f = Frantion(n, d);
return strm;
}
就是传递一个函数指针作为 I/O 操作符的参数
还有缓存区 Classes等内容下一篇再讲