42、C++ Primer 4th笔记,IO库,未格式化IO操作

1、标准库还提供了丰富的支持未格式化IO的低级操作,这些操作使我们能够将流作为未解释的字节序列处理,而不是作为数据类型(如char,int,string等)的序列处理。

2、单字节操作

几个未格式化的操作一次一个字节地处理流,它们不忽略空白地读。

示例代码

#include <iostream>
#include "string"
#include "cmath"
#include "iomanip"
using namespace std;

int main()
{	
	//默认情况下,输入操作符忽略空白
	while(cin >> ch)
		cout << ch;
	//可以通过操纵符来强制不忽略空白
	cin >> noskipws;
	while(cin >> ch)
		cout << ch;
	cin >> skipws; //reset cin to default state so that it discards whitespace
	//通过未格式化的IO操作,我们一次一个字节处理流,不忽略空白
	while(cin.get(ch))
		cout.put(ch);
	return 1;
}

1 单字节低级 IO 操作

is.get(ch)

istream is 的下一个字节放入 ch,返回 is

os.put(ch)

将字符 ch 放入 ostream,返回 os

is.get()

返回 is 的下一字节作为一个 int

is.putback(ch)

将字符 ch 放回 is,返回 is

is.unget()

is 退回一个字节,返回 is

is.peek()

将下一字节作为 int 值返回但不移出它

1)在流上倒退

    一般而言,保证能够在下一次读之前放回最多一个值。也就是说,不保证能够连续调用 putback unget 而没有介于其间的读操作。

标准库提供了三种方法来将字符放回流上:

peek,返回输入流上下一字符的副本但不改变流。peek 返回的值留在流上,且将是下一个被检索的。

unget,使输入流倒退,以便最后返回的值仍在流上。即使不知道最近从流获得的是什么值,也可以调用 unget

putbackunget 的更复杂的版本。它返回从流中读到的最后一个值,但接受最后一次读的同一实参。很少有程序使用 putback,因为更简单的unget 也可以完成相同工作而约束更少。

2)输入操作的int返回值

   表1中函数返回int值是为了允许它们返回一个文件结束标记。这些函数将字符转换为unsigned char,然后将那个值提升为int,因此,即使字符集有映射到负值的字符,从这些操作返回的值也将是一个正值。通过将文件结束符作为负值返回,标准库保证文件结束符区别于任意合法字符值。

头文件iostream定义了名为EOFconst,可以使用它来测试函数的返回值是否为文件结束符。

示例代码

#include <iostream>
#include "string"
#include "cmath"
#include "iomanip"
using namespace std;

int main()
{	
	int ch;
	while((ch = cin.get()) != EOF)
		cout.put(ch);
	return 1;
}

3、多字节操作

这些操作要求我们分配和管理用于存储和检索数据的字符数组。注意,get是重载的。

2 多字节低级 IO 操作

is.get(sink, size, delim)

is 中读 size 个字节并将它们存储到 sink 所指向的字符数组中。读操作直到遇到 delim 字符,或已经读入了 size 个字节,或遇到文件结束符才结束。如果出现了 delim,就将它留在输入流上,不读入到 sink 中。

is.getline(sink, size, delim)

与三个实参的 get 行为类似,但读并丢弃 delim

is.read(sink, size)

size 个字节到数组 sink。返回 is

is.gcount()

返回最后一个未格式化读操作从流 is 中读到的字节数

os.write(source, size)

size 个字从数组 source 写至 os。返回 os

is.ignore(size, delim)

读并忽略至多 size 个字符,直到遇到 delim,但不包括 delim默认情况下,size 1 delim 是文件结束符

    将get或其他返回int值的函数的返回值赋给char对象而不是int对象,是常见的错误,但编译器不检测这样的错误。

1getgetline进行读,起到遇到如下条件之一:

① 读到了size - 1个字符。

② 遇到文件结束符。

③ 遇到分隔符。

    Following any of these conditions, a null character is put in the next open position in the array. The difference between these functions is the treatment of the delimiter. get leaves the delimiter as the next character of the istream . getline reads and discards the delimiter. In either case, the delimiter is not stored in sink .

2)有必要在任意插入的未格式化输入操作之前调用gcount。尤其是,将字符放回流上的单字符操作也是未格式化输入操作,如果在调用gcount之前调用peekunget putback,则返回值将是 0

4、流的随机访问

IO类维持一个标记(位置指针),改标记决定下一个读或写发生在那里。

3 seektell函数

seekg

重新定位输入流中的标记

tellg

返回输入流中标记的当前位置

seekp

重新定位输出流中的标记,seekp函数将位置置于下一个写将发生的地方

tellp

返回输出流中标记的当前位置

其中,p(ut)g(et)

因为只有一个标记,所以,在读和写之间切换时必须进行seek来重新定位标记。同样,C语言也有这样的规定,读操作和写操作进行切换时,中间必须用fseek函数:

int fwrite(void *buf, int size, int count, FILE *fp)

int fseek(FILE *fp, LONG offset, int origin)

int fread(void *buf, int size, int count, FILE *fp)

1)普通iostream对象一般不允许随机访问。因为istreamostream类型一般不支持随机访问,所以我们的seek,tell一般针对于fstream,sstream

2seek的函数原形

原形定义

// set the indicated marker a fixed position within a file or string
seekg(new_position); // set read marker
seekp(new_position); // set write marker
// offset some distance from the indicated position
seekg(offset, dir); // set read marker
seekp(offset, dir); // set write marker

beg

The beginning of the stream

cur

The current position of the stream

end

The end of the stream

    名为pos_typeoff_type的类型分别表示位置和从该位置的偏移量。off_type类型的值可正可负,在文件中可以进行前向或后向seek

示例代码

#include <iostream>
#include "string"
#include "cmath"
#include "iomanip"
using namespace std;

int main()
{	
	ostringstream writerStr;
	ostringstream::pos_type mark = writerStr.tellp();
	//...
	if (cancelEntry)
		//return to marked position
		writerStr.seekp(mark);
	return 1;
}

3)在进行seek等函数前,应当调用流的clear()函数来清理流中的错误。这样防止流处于错误状态,而对文件流的操作都将失败。

示例代码

#include <iostream>
#include "string"
#include "cmath"
#include "iomanip"
#include "fstream"
using namespace std;

int main()
{	
	//open for input and output and pre-position file pointers to end of file
	fstream inOut("C:\\httpdownload.txt", fstream::ate | fstream::in | fstream::out);
	if (!inOut)
	{
		cerr << "Open file error" << endl;
		return EXIT_FAILURE;
	}
	//inOut is opened in ate mode, so it starts out positioned at the end,
	//which we must remember as it is the original end-of-file position
	ifstream::pos_type ptEndMark = inOut.tellg();
	inOut.seekg(0, fstream::beg);
	int cnt = 0;
	string line;
	// while we haven't hit an error and are still reading the original data
	// and successfully read another line from the file
	while(inOut && inOut.tellg() != ptEndMark && getline(inOut, line))
	{
		cnt += line.size() + 1;
		ifstream::pos_type ptCurrMark = inOut.tellg();
		inOut.seekp(0, fstream::end);
		inOut << cnt;
		if (ptCurrMark != ptEndMark)
			inOut << " ";
		inOut.seekg(ptCurrMark);
	}
	inOut.clear(); //clear flags in case we hit an error
	inOut.seekp(0, fstream::end); // seek to end
	inOut << "\n"; //write a newline at end of file
	return 0;
	return 1;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值