C++ Stream类

输入输出语义是将程序与文件和设备进行关联,并使用缓存区(一款共享的内存)在程序与文件/设备之间传输数据。

标准输入关联的是键盘设备,标准输出关联的是显示器设备。标准的意思是规定了0、1、2这三个文件描述符用来关联基本输入输出设备。

Stream特点

C++的IO称为stream,流,流的特点如下:

  1. 提供buffer(缓冲区,共享的内存),在程序和文件之间传输数据;
  2. 字节流,以队列形式先入先出,每次一个字节;
  3. 格式化,将文本类型格式化为其他数据类型,或反之。

和流对应的概念是消息,流的边界是字符,消息的边界是消息结构体。因为消息结构体中存有消息类型,所以消息适合于多对多传输,而流适合于1对1传输。

C++内置了cin、cout、cerr、clog以及4个宽字符共8个流对象。
cin关联了键盘;
cout关联了屏幕;
cerr和clog也关联了屏幕。

常用的stream头文件有:

#include <istream>
#include <ostream>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iominip>

随机访问:

istream::tellg()    返回读取位置
istream::seekg()    设置读取位置

ostream::tellp()    返回写入位置
ostream::seekp()    设置写入位置

beg、cur、end        相对位置

标准IO成员函数

char a;
char buffer[100];

// 输入
cin.get(&a);
cin.getline(buffer,100,';');
cin.ignore();//丢弃一行

// 输出
cout.put(char c);
cout.flush();

格式化

#include <iominip>

// 标志位
setiosflags		        设置flags
resetiosflags		        清除flags

// 刷新和换行
endl				换行并刷新缓冲区
ends				追加’\0’
flush				刷新缓冲区
ws			        忽略开始的空白
skipws			        同ws一样
noskipws			不忽略开始的空白
unitbuf			        每次写操作都刷新缓存
nounitbuf			每次写操作后不刷新缓存

// 显示宽度
setw				设置输出宽度
left				左对齐
right				右对齐
internal			正负号左对齐,数值右对齐
setfill				多余的输出宽度用指定字符填充

// 显示类型
boolalpha		        用文本表示布尔值
noboolalpha		        用数值表示布尔值
showpos			        写出正号
noshowpos		        不写出正号
showuppers		        用符号表示的数值,符号大写
noshowuppers	                用符号表示的数值,符号不需要大写

// 显示进制
oct				八进制
dec				十进制
hex				十六进制
showbase		        显示进制前缀

// 显示浮点数
showpoint		        浮点类型必须显示小数
noshowpoint		        浮点类型不必须显示小数
setprecision		        显示的小数个数
fixed				使用十进制显示
scientific			使用科学计数法显示

// 国际化
put_time			输出日期
get_time			读入日期
put_money		        输出金额
get_money		        读入金额
cin.imbue                       获取locale
cout.getloc                     获取locale

文件读写

C++中的文件操作头文件:

#include <ifstream>
#include <ofstream>
#include <fstream>
#include <filebuf>

文件标志位:

in	打开并读取,ifstream的默认模式
out	打开并写入,ostream的默认模式
app	追加
ate	定位光标到结尾
trunc	覆写文件
binary	二进制模式

C++中有两种打开文件的方式,一种是使用对象的构造函数,另一种是显示使用open函数。

使用构造函数打开文件,并在离开作用域后由析构函数关闭文件:

#include <fstream>

// 写入文件
ofstream file("file_name");
ofstream file("file_name", std::ios::out|std::ios::app);
file << "hello" << endl;

// 读取文件
char c;
ifstream file("file_name");
file.get(c);

使用open()打开文件:

ifstream file;
file.open("file_name");
...
file.clear();
file.close();

显然,还是面向对象的方法好用。

文本模式和二进制:
使用二进制文件模式时,程序将数据从内存传输给文件(反之亦然)时,将不会发生任何隐藏的转换,而默认的文本模式并非如此。例如,对于Windows文本文件,它们使用两个字符的组合(回车和换行)表示换行符;Macintosh文本文件使用回车来表示换行符;而UNIX和Linux文件使用换行(linefeed)来表示换行符。C++是从UNIX系统上发展而来的,因此也使用换行(linefeed)来表示换行符。为增加可移植性,Windows C++程序在写文本模式文件时,自动将C++换行符转换为回车和换行;Macintosh C++程序在写文件时,将换行符转换为回车。在读取文本文件时,这些程序将本地换行符转换为C++格式。对于二进制数据,文本格式会引起问题,因此double值中间的字节可能与换行符的ASCII码有相同的位模式。另外,在文件尾的检测方式也有区别。因此以二进制格式保存数据时,应使用二进制文件模式(UNIX系统只有一种文件模式,因此对于它来说,二进制模式和文本模式是一样的)。

string stream

#include <iostream>
#include <sstream>

ostringstream os;
os.str()        返回string
os.str(a)       设置stringstream

重定向流

通过关联/设置缓冲区,可以不必借助操作系统就完成IO重定向。

// 获取缓冲区
cout.rdbuf()

// 设置缓冲区
cout.rdbuf(file.rdbuf())

将流重定向到标准输出,并格式化:

#include <iostream>
#include <iomanip>
using namespace std;

int main(){
    ostream hexout(cout.rdbuf());
    hexout << hex << showbase;
    //hexout.setf(ios::hex, ios::basefield);
    //hexout.setf(ios::showbase);
    int a = 1234;
    cout << a << endl;
    hexout << a << endl;
    
    return 0;
}
1234
0x4d2

将标准输入和标准输出重定向并不安全,因为被重定向的对象在离开作用域后缓冲区会被析构,导致cout没有缓冲区可用,所以如果需要使用智能指针进行包装,使其在析构时还原rdbuf。

void redirect(ostream& strm){
	auto del = [&](streambuf* p){
		strm.rdbuf(p);
	}
	unique_ptr<streambuf,delctype(del)> origBuffer(strm.rdbuf(),del);
	ofstream file(“file_name”);
	strm.fdbuf(file.rdbuf());
}

redirect(out);

缓冲区

stream并不执行读写操作,而是交给stream buffer来完成。

缓冲区对象有以下成员函数:

sputc(c)			将字符c写入缓冲区
sputn(s,n)		将子串写入缓冲区
in_avail()			返回有效字符下标
sgetc()			查看当前字符
sbumpc()			获取当前字符
snextc()			跳过当前字符
sgetn()			读取n个字符
sputbackc(c)	将字符c返回缓冲区
sungetc()			返回当前字符
pubimbue()		设置区域
getloc()			获取区域
pubseekpos		设置当前位置

缓冲区迭代器可用来迭代缓冲区的字符。

所以stream负责格式化,buffer负责读写。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多弗朗强哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值