我的C++ primer笔记(第II部分,完善中)

最近在忙一些事情,挂科了还要准备开学补考呜呜,过几天更新


前言

本文是完全写自己看的《C++ primer》笔记,内容写的很快,所以可能有较多遗漏,这是第II部分,第一部分请移步我的C++ primer笔记(第I部分)

第II部分 C++标准库

第八章 IO库

C++不直接处理输入输出,而是通过一族定义在标准库中的类型来处理IO。这些类型支持从设备读取数据、向设备写入数据的IO操作,设备可以是文件、控制台窗口等。还有一些类型允许内存IO,即,从string读取数据,向string写入数据。

8.1 IO类

在这里插入图片描述
为了支持使用宽字符的语言,标准库定义了一组类型和对象来操纵wchar_t类型的数据。宽字符版本的类型和函数的名字以一个w开始。例如wcin、wcout、wcerr是分别对应cin、cout、cerr的宽字符版本对象。宽字符版本的类型和对象与其对应普通的char版本的类型定义在同一个头文件中。例如,头文件fstream定义了ifstreamwifstream类型。

IO类型间的关系
标准库使我们能忽略不同类型的流之间的差异,这是通过继承机制实现的。利用模板,我们可以使用具有继承关系的类,而不必了解继承机制如何工作的细节。
简单的说,继承机制使我们可以声明一个特定的类继承自另一个类。我们通常可以将一个派生类(继承类)对象当做其基类(所继承的类)对象来使用。

IO对象无拷贝或赋值
我们不能拷贝或对IO对象赋值。

ofstream out1, out2;
out1 = out2;				//错误,不能对流对象赋值
ofstream print(ofstream);	//错误,不能初始化ofstream参数
out2 = print(out2);			//错误,不能拷贝流对象

由于不能拷贝IO对象,所以我们也不能将形参或返回值设置为流类型。通常使用引用方式传递,读写一个IO对象会改变其状态,因此传递和返回的引用是不能const的

条件状态
在这里插入图片描述
在这里插入图片描述
一个错误的IO例子

int val;
while(cin >> val) cout << 1 << '\n';

一旦我们输入一个字母A,读操作就会失败,代码期望得到一个int,却得到了一个字符A。这样cin会进入错误状态,终止读入。(文件结束标志是一样的效果)

流状态的查询和控制
IO库定义了一个与机器无关的iostate类型,它提供了表达流状态的完整功能。
流状态由eof, bad, fail, good指示,如果eof, bad, fail任何一个为true那么流监测状态为错误状态;相反都为false,则good为true.

其中badbit标志着系统级的故障,是不可恢复的,如果流出现这种情况,流通常就不能继续使用了;failbit标志着是可恢复的,可以修正。eofbit在遇到文件结束符时设置,此时还设置了failbit.

clear()和setstate()用于改变条件成员的状态。clear()将条件重设为有效状态(eof, bad, fail置为false;good置为true),setstate()把某个特定的流设为有效状态。

#include<bits/stdc++.h>

using namespace std;

istream &process_input(istream &cin) {

	int x;
	cin >> x;
	cout << cin.good() << '\n';	//当x不为数字是输出为0
	

}

int main() {

	auto old_state = cin.rdstate();
	cin.clear();	
	cin.ignore();	//clear()只会把cin的状态调整为正确的状态,错误的输入还在缓冲区,
					//cin.ignore()意为舍弃掉缓冲区中第一个字符或回车之前的数据
	process_input(cin);
	cin.setstate(old_state);
	cin.clear();
	cin.ignore();
	cout << cin.good() << '\n';	//clear之后输出为1

	return 0;
}
#include<bits/stdc++.h>

using namespace std;

istream &process_input(istream &cin) {

	int x;
	cin >> x;
	

}

int main() {

	auto old_state = cin.rdstate();			//记录cin当前状态
	cout << "---" << old_state << '\n';		//输出当前状态,因为状态正常结果是0

	process_input(cin);						//在这里输入一个B,因为读入fail
											//所以cin.rdstate()为failbit,也就是4
	auto bad_state = cin.rdstate();
	cout << "---" << bad_state << '\n';		//输出4
	
	cin.clear();							//clear()之后状态正确输出0
	cout << "---" << cin.rdstate() << '\n';

	cin.setstate(bad_state);				//setstate不是覆盖原始状态,而是叠加到原始状态上,所以输出4
	cout << "---" << cin.rdstate() << '\n';
	cin.setstate(old_state);				//setstate不是覆盖原始状态,而是叠加到原始状态上,所以输出4
	cout << "---" << cin.rdstate() << '\n';

	return 0;
}

管理输出缓冲
刷新输入缓冲区的五种情况:

  • 程序正常结束
  • 缓冲区已经满了
  • endl显式刷新
  • 用 unitbuf 操纵符设置流的状态,清空缓冲区
  • 将输入输出流关联起来

主动刷新缓冲区的方式

cout << "1" << endl;	//输出一个换行然后刷新缓冲区
cout << "1" << flush;	//什么都不输出刷新缓冲区
cout << "1" << ends;	//输出一个空字符刷新缓冲区

cout << unitbuf;		//所有输出操作后都会立即刷新缓冲区

cout << nounitbuf;		//回到正常的缓冲方式

关联输入和输出流
当一个输入流被关联到一个输出流时,任何从输入流读取数据的操作都会先刷新关联的输出流。
cin.tie(&cout); ostream *old_tie = cin.tie(); cin.tie(0); cin.tie(&cerr); cin.tie(0);
cin.tie(old_tie);

8.2 文件输入输出

文件操作

C++中对文件操作需要包含头文件<fstream>

文件分为两种:

  • 文本文件:文件以文本的ASCII码形式存储在计算机中
  • 二进制文件:文件以文本的二进制形式存储在计算机中

操作文件三大类:

  1. ofstream:写操作
  2. ifstream:读操作
  3. fstream:读写操作

文本文件

写文件

  1. 头文件include<fstream>
  2. 创建流对象ofstream ofs
  3. 打开文件ofs.open("文件路径",打开方式)
  4. 写数据ofs << "写入的数据"
  5. 关闭文件ofs.close()

文件打开方式:

  • ios::in 为读文件而打开文件
  • ios::out为写文件而打开文件
  • ios::ate初始位置:文件尾
  • ios::app追加方式写文件
  • ios::trunc如果文件存在先删除再创建
  • ios::binary二进制方式

注意:文件打开方式可以配合使用,利用|操作符

例如:用二进制方式写文件:ios::binary | ios::out

读文件

  1. 头文件include<fstream>
  2. 创建流对象ifstream ifs
  3. 打开文件ifs.open("文件路径",打开方式)
  4. 读数据:四种方式
    • ifs >> x每次能读取一行数据,x是字符数组或string类型
    • ifs.getline(x, size) x是字符数组,size是一行最多读入的字符个数
    • getline(ifs, s) s是string类型
    • c = ifs.get() 读入一个字符
  5. 关闭文件ifs.close()

二进制文件

打开方式要指定为ios::binary

写文件

二进制方式写文件主要利用流对象调用成员函数write

函数原型:ostream& write(const char * buffer, int len)

buffer指向内存中一段存储空间,len是读写的字节数

读文件

二进制方式读文件主要利用流对象调用成员函数read

函数原型:istream& read(char * buffer, int len)

buffer指向内存中一段存储空间,len是读写的字节数

8.3 string流

istringstream从string读数据,ostringstream向string写如数据,stringstream可读可写
在这里插入图片描述

使用istringstream

string line, word;
while(getline(cin, line)) {
	istringstream record(line);
	while(record >> word) cout << word << '\n';
}

使用ostringstream

string line, word;
ostringstream s;
while(cin >> word) {
	s << " " << word;
}

cout << s.str() << '\n';

第九章 顺序容器

9.1 顺序容器概述

vector(可变大小数组)、deque(双端队列)、list(双向链表)、forward_list(单向链表)、array(固定大小数组)、string(保存字符串,与vector类似)

9.2 容器库概览

如果我们创建的类型没有默认构造函数,这时我们必须传递给它一个元素初始化器
假定T是一个没有默认构造函数的类型

vector<T> v1(10, init);	//正确,提供了元素初始化器
vector<T> v2(10);		//错误

begin()和end()可以改变元素值,cbegin()和cend()则不可以改变

标准库array具有固定大小

array<int, 42> a;	//42个int

array<int, 42> :: size_type sz;	//正确
arrat<int>:: size_type j;		//错误,array<int>不是一个类型

使用assign(仅顺序容器)
赋值运算符要求左右两遍对象拥有相同的类型,assign允许我们从一个不同但相容的类型赋值。

list<string> names;
vector<const char*> oldstyle;
name = oldstyle;	//错误,类型不匹配
//正确,可以将const char* 转换为string
name.assign(oldstyle.begin(), oldstyle.end());	

list<string> s(1);	//1个元素,空string
s.assign(10, "Hi");	//10个元素,每个都是"Hi"

9.3 顺序容器操作

9.4 vector对象是如何增长的

9.5 额外的string操作

9.6 容器适配器

第十章 泛型算法

第十一章 关联容器

第十二章 动态内存

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值