【C++】《C++标准程序库》小结第十三章-stream(2)

本文详细介绍了C++标准输入输出流的功能与用法,包括成员函数、格式标志、文件存取等方面的知识。通过实例展示了如何高效地使用这些功能。

(五)标准输入函数

1、输入函数。cin<<函数只适用于非格式化输入。下面是另外一些输入函数。注意其中有一些是cin的成员函数!!!getline有两种用法cin.getline(s,num)或者getline(cin,s,num);

成员函数

读取直到遇到...

字符数

添加结束符

返回

get(s,num)

EOF,不包括EOF

最多num-1

istream

get(s,num,t)

t或EOF,不包括t和EOF

最多num-1

istream

getline(s,num)

包括EOF

最多num-1

istream

getline(s,num,t)

包括t或EOF

最多num-1

istream

read(s,num)

EOF

num

istream

readsome(s,num)

EOF

最多num

count

gcount

 

 

 

返回上次非格式化读取操作所读入的字符数

ignore()

 

 

 

忽略一个字符

ignore(count)

 

 

 

忽略count个字符

ignore(count, delim(单个字符))

 

 

 

忽略count个字符直到delim,舍弃delim

peek()

 

 

 

获取即将读取的下一个字符,但不会读入缓冲区

unget()

 

 

 

把上一次读取的字符放回stream缓冲区。如果没有错误,下一次可以读取它。

putback(char c)

 

 

 

检查c是否是上一次读取的字符,如果是就执行unget(),不是就设立badbit甚至抛出异常

 

2、get与getline区别不是很大,但一个明显的区别是get遇到 '\n '字符后便返回,这是 '\n '还在缓冲区中,所以下次读出来的将是 '\n ',解决之道是在第一次调用完cin.get()以后再调用一次cin.get()把'\n'符给读取了,可以组合式地写为cin.get(name,SIZE).get();。而getline遇到 '\n '也返回,但它会把 '\n '从缓冲区里移除掉 所以很多时候用getline方便些。

3、read函数,不会自动加结束符号,要手动添加,否则会出问题,例子如下:

char c[5];

c[4] = 0;//必须手动,否则输出末尾会带有乱码!

cin.read(c, 4);//就算强制输入5个字符,也只会放入4个字符。

cout << c <<endl;

 

4、上面的成员函数适用于char字符串,比>>要安全,因为明确指定了范围。

5、以下操作会舍弃当前这一行剩余部分:

cin.ignore(numeric_limits<std::streamsize>::max(), ‘\n’);

以下操作舍弃cin所有剩余部分:

cin.ignore(numeric_limits<std::streamsize>::max());

6、直接用stream buffer性能比成员函数好,因为不需要构造sentry对象。另一种方法是使用迭代器istreambuf_iterator。相关内容将在后面提到。

 

(六)标准输出函数

成员函数

作用

返回。可以获取返回ostream的状态来监视操作是否成功

put(char c)

把c写到stream

ostream&

write(const char* str, count)

将str中的count个字符写入stream,但不会在EOF处停止

ostream&

flush()

刷新stream缓冲区,把缓冲区数据全部强制写入设备

ostream&

直接使用streambuffer或者迭代器ostreambuf_iterator效率更高。但是要注意多线程环境下的上锁机制。

 

对比C函数:int getc(FILE *stream);把数据作为int传回。也可直接转为char。

char ch;

ch = getc(stdin);

int getchar(void);相当于getc(stdin);

返回值可能是EOF,这个需要自己手动判断,C++标准函数已经提供了自动判断,所以用C++的要安全。

char *gets(char*)        // 可以接受一个string,可以接收空格并输出,需包含“#include<string>”

 读入成功,返回与参数buffer相同的指针;读入过程中遇到EOF(End-of-File)或发生错误,返回NULL指针。所以在遇到返回值为NULL的情况,要用ferror或feof函数检查是发生错误还是遇到EOF。本函数可以无限读取,不会判断上限,所以程序员应该确保buffer的空间足够大,以便在执行读操作时不发生溢出。如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值,为了避免这种情况,我们可以用fgets()来替换gets()。这个事实导致gets函数只适用于玩具程序。在V7的手册(1979年)中说明:为了向后兼容,gets删除换行符,gets并不将换行符存入缓冲区。

 

(七)操控器

1、直接跟在<<或者>>后面的。

操控器

类别

作用

flush

basic_ostream

刷新输出缓冲区,强制写入设备

endl

basic_ostream

向缓冲区插入换行符号并刷新

ends

basic_ostream

向缓冲区插入终止符号

ws

basic_istream

读取时忽略空格

2、一般形式:

ostream& ostream::operator<<(ostream& (*op)(ostream&))

{

return(*op)(*this);

}

简单来说就是调用<<后面的函数指针,对自身进行操作。

比如endl:

std::ostream&std::endl(std::ostream& strm)

{

strm.put(‘\n’);

strm.flush();

return strm;

}

 

3、自定义模板操控器例子:

template<classcharT, class traits>

inlinestd::basic_istream<charT, traits>& ignoreLine(std::basic_istream<charT, traits>& strm)

{

strm.ignore(std::numeric_limits<int>::max(), strm.widen(‘\n’));

return strm;

}

用法:省略两行

std::cin>> ignoreLine >> ignoreLine;

 

 

(八)格式标志函数

成员函数

作用

setf(flag)

设置格式标志flag,返回所有原始标志

setf(flag,mask)

配合掩码mask设置flag,返回所有原始标志

unsetf(flag)

清除flag

flags()

返回所有已经设立的标志

flags(flag)

以参数flag为新标志,并返回旧标志

copyfmt(stream)

从stream中复制所有格式定义

std::ios::basefield是数学进制的掩码,例子:

std::cout.setf(std::ios::hex,std::ios::basefield);

清除所有进制标志,并设立hex标志。

 

一个实际应用:

ios::fmtflags oldFlags = cout.flags()

cout.setf(std::ios::showpos | std::ios ::uppercase);

cout << std::hex << x<<std:: endl;

cout.flags(oldFlags);

 

另外也可以使用操控器

操控器

作用

setiosflags(flag)

相当于setf(flag)

resetiosflags(mask)

清除mask标记的一组标志相当于setf(0,mask)

用法:

#include <iomanip>//使用操控器必须添加

 

cout <<resetiosflags(std::ios::adjustfield)

<<setiosflags(std::ios::left);

 

各类操控器和格式化输出函数请查阅P616-626

 

(九)文件存取

1、C++文件流,可以手动关闭,可以不用关闭(自动关闭)。但是如果使用了指针,就需要自己删除。

2、文件标志

标志

意义

in

读取,ifstream的默认模式

out

写入,ofstream的默认模式

app

写入时添加到尾部

ate

读写时,读写位置移动到文件末尾

trunc

将先前的文件内容移除

binary

不替换特殊字符,这样可以保留其他系统文件格式。如果是二进制文件也应该用他

 

与C函数不同,C函数fopen的标志位必须要设置为a或者a+才不会覆盖原始文件。

组合用法

意义

C函数

in

读取

r

out

清空然后改写

w

out|trunc

清空然后改写(和上面意义)

w

out|app

添加

a

in|out

读写,位置在起点

r+

in|out|trunc

先清空再读写

w+

 

成员函数

成员函数

意义

open(name)

缺省模式打开

open(name, flag)

以flag模式打开

close()

关闭

is_open()

判断是否打开

 

2、多次使用流对象

ifstream file;

for(int i = 0; i <argc; ++i) {

file.open(argv[i]);

char c;

while(file.get(c)) {

cout.put(c);

}

 

//另外一种输出方式

std::cout << file.rdbuf();//更快!!

 

file.clear();//这个很重要!!!

file.close();

}

 

3、随机读取,g表示get, p表示put。注意函数不会检查是否越界!!!

成员函数

意义

tellg()

当前读取位置

seekg(pos)

设置绝对读取位置

seekg(offset, pos)

设置相对pos的偏移读取位置

 

 

tellp()

当前写入位置

seekp(pos)

绝对写入位置

seekp(offset, pos)

设置相对pos的偏移写入位置

 

4、位置常数

常数

意义

beg

开头

cur

当前位置

end

结尾

用法:

file.seekg(20,std::ios::cur);

 

5、如果想这样干:执行某个流操作,但想同时自动刷新其他某个流的缓冲区。使用tie函数。

成员函数

意义

tie()

返回当前连接的strm

tie(ostream *strm)

连接strm,自动刷新strm

tie(0), tie(NULL)

取消tie

std::cin.tie(&std::cout);

std::cout << “....”;

std::cin >> x;//自动清空cout缓冲区

std::cin.tie(static_cast<std::ostream*>(0));//取消tie

 

6、缓冲区紧耦合

成员函数

意义

rdbuf()

返回stream缓冲区

rdbuf(streambuf*)

把streambuf缓冲区安装到当前流,并返回当前流的原始缓冲区

注意缓冲区的原来的主人析构的时候会连带析构缓冲区,所有记得把自己的缓冲区还原。

streambuf *oldbuffer = strm.rdbuf();

strm.rdbuf(file.rdbuf);

操作

....

strm.rdbuf(oldbuffer);//还原

太强大了,作为C++程序员,你该懂的!!!!! 内容简介   C++ 标准程序库提供一组通用类别(classes)和接口(interfaces),可大幅扩充 C++ 核心语言。由于程序库本身并不容易,为了完整运用其组件并从其强大的威力中获得帮助,你需要一份完善的资源,而非一份仅仅陈列类和函数的普通文档。   《The C++ Standard Library》(中文版《C++ 标准程序库》)不仅对每一个程序库组件提供范围广泛的说明,也对繁杂的感念提供清楚明亮的解释,并描述高效运用这些组件时需要的实际编程细节,提出一个又一个的范例程序。   这本包含最新资料的完整书籍,反映出被 ANSI/ISO C++ 语言标准规格书纳入的 C++ 标准程序库的结构。更明确地说,本书将焦点放在标准模板库(Standard Template Library)身上,检验其中的容器(containers)、迭代器(iterators)、仿函数(functors)和算法(algorithms)。你还可以找到特殊容器、字符串(strings)、数值类别、国际化议题、IOStream。每一个组件都有深刻的呈现,包括其介绍、设计、运用实例、细部解说、陷阱、意想不到的危险,以及相关类别和函数的确切标记(signature)和定义。一份见解深刻的基础概念介绍和一个程序库综合鸟瞰,会对新手带来快速的提升。   《The C++ Standard Library》范围广泛、详细、可读性高、实用, 是值得你一再查阅的 C++ 宝贵资源。本书网站 http://www.josuttis.com/libbook,其中提供书中源码下载。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值