C/C++ I/O输入输出流

before|正文之前:

c++实验代码及学习笔记(十一)

你好! 这是一个高程实验课的代码记录及学习笔记。我将记录一些重要的知识点、易错点。但是作为大学生,水平很低,敬请指点教导、优化代码。

1问题

C/C++ I/O输入输出流_第1张图片
本次课我们学习了I/O流。同c语言一样,c++也没有输入输出语句。但是,有个面向对象的软件包,就是I/O流类库。那么,什么是流呢?

c++把数据从一个对象向另一个对象流动抽象为“流”。流是一种抽象,它负责在数据的生产者和消费者之间建立联系,并管理着数据的流动。

一般情况下,把读操作称为“提取”,把写操作称为“插入”。
I/O流类库的基础是一组类模板,提供了大量功能。下面我将对I/O流类库进行精讲。

2精讲

下面是修改过的I/O流层次图
C/C++ I/O输入输出流_第2张图片C/C++ I/O输入输出流_第3张图片
这是I/O流的基本层次,其中,i代表input,o代表output,f代表file,s代表string。stream当然就是流的意思了。
下面是我针对本章制作的思维导图。
C/C++ I/O输入输出流_第4张图片

3代码测试

3.1格式控制

#include 
#include 
#include 

using namespace std;

int main()
{
	char c = '#';

	//setw
	double values[] = { 1.00,12.34,123.4,12345 };
	for (int i = 0; i < 4; i++)
	{
		cout << setw(10) << values[i] << endl;
	}
	//setprecision setfill
	for (int i = 0; i < 4; i++)
	{
		cout << setw(10) << setfill(c) << setprecision(1)<< values[i] << endl;
	}

3.2二进制输入

默认的文件读写方式是文本模式。但是,与Linux系统相比,Windows系统会有多一个回车符的问题,如果读写二进制会出现问题。使用二进制模式打开,会提高效率、解决问题。

	//文件读写 二进制
	ofstream file;
	int data[2] = { 10,99 };

	//正常打开(末尾追加
	//0D 0A 00 00 00 63 00 00 00
	file.open("test1.dat", ios_base::app);
	file.write(reinterpret_cast<char*>(data), sizeof(data));
	file.close();
	
	//二进制打开
	//0A 00 00 00 63 00 00 00
	file.open("test2.dat",ios_base::out|ios_base::binary);
	file.write(reinterpret_cast<char*>(data),sizeof(data));
	file.close();
	

当然在测试二进制模式时存在一些问题,那就是dat文件的打开方式。我用记事本打开,结果只显示一个字母c。问题出在哪里呢?
通过查阅网络资料,我们发现原来二进制文件要用二进制编辑器打开。
参考文章:使用ios_base::binary的问题

所谓的文本文件,本质上还是二进制文件,只不过它保存是数据都是ASCII字符(或者GB2312,big5 unicode等编码) 而已 ,文本查看器(比如windows的记事本)也只能正常显示这些特定的编码对应的字符
用::binary的目的是不要任何可能自动产生的格式符号,比如常见的"\n",用二进制方式写入文件就只会写入0x0a,而用文本方式则可能会写入0x0a 0x0d两个字节,多了一个回车

	//文件指针
	ifstream ifs;
	ifs.open("a.txt", ios_base::in);
	ifs.seekg(0,ios::end);
	streampos size = ifs.tellg();
	cout << "文件大小:" << size << endl;
	ifs.close();

3.3文件指针

参考文章:c++文件的读写
seekg()/seekp()与tellg()/tellp()的用法详解
用seekg函数设置指针,用tellg函数读指针位置。

tellg() ——返回一个int型数值,它表示“内置指针”的当前位置。此函数仅当你在读取一个文件时有效。
tellp() —— 与tellg()有同样的功能,但它用于写文件时。总而言之:当我们读取一个文件,并要知道内置指针的当前位置时,应该使用tellg();当我们写入一个文件,并要知道内置指针的当前位置时,应该使用tellp()
seekp() —— 还记得seekg()么?当我在读取一个文件,并想到达文件中某个特定位置时,就曾使用过它。seekp()亦如此,只不过它用于写入一个文件的时候。例如,假如我在进行文件读写,而要定位到当前位置的三个字符之前,则需调用FileHandle.seekg(-3). 但如果我是在写入一个文件,并且比如我要重写后5个字符的内容,我就必须往回跳转5个字符,因而,我应该使用FileHandle.seekp(-5) .

简单来说,p代表put,g代表get
对输入流操作:seekp tellp
对输出流操作:seekg tellg

seekg()是对输入文件定位,它有两个参数:第一个参数是偏移量,第二个参数是基地址。
对于第一个参数,可以是正负数值,正的表示向后偏移,负的表示向前偏移。而第二个参数可以是:
ios::beg:表示输入流的开始位置
ios::cur:表示输入流的当前位置
ios::end:表示输入流的结束位置
tellg()函数不需要带参数,它返回当前定位指针的位置,也代表着输入流的大小。

具体应用请参考原文。
我们测试一下获取文件大小即可(seekg定位结束位置,tellg返回字节数)

3.4字符串输入输出流

上一节课遗留的问题,实际上很重要的内容
首先我们来看几个函数。
get 读可以带空字符,cin读不出空字符,getline则可以读出带空格的字符串
参考文章:C++中cin、cin.get()、cin.getline()、getline()、gets()等函数的用法
注意他们的参数。如加掌握灵活使用,将非常有帮助。
其次是istringstream的用法
参考文章:C++中的 istringstream 的用法

istringstream::istringstream(string str);
它的作用是从string对象str中读取字符。

上节课我们举了I am your father的例子
通过getline(cin,str)输入一段包含空格的字符串,在is流中,可以以空格为分隔输出一小段一小段字符串。

#include 
...
//字符串输入输出流
	string str, s;
	cout << "可输入含空格的字符串" << endl;
	getline(cin, str);

	istringstream is(str);
	while(is>>s)
	{ 
	cout<<s<<endl;
	}
	
	ostringstream os;
	os << str;
	cout << os.str() << endl;

4最终效果

C/C++ I/O输入输出流_第5张图片
感谢大家阅读~

你可能感兴趣的:(学习笔记,c/c++)