前言
该系列是《C++Primer第五版》的笔记,包含本人认为值得记录和整理的主要的知识点,并不是全部内容,也不是具体的内容。
该系列文章的作用应该是作为复习或预习的参考,有哪些知识点忘记或想学,可以大致浏览下该文章,然后再去书中寻找详细解答。(本系列文章基本是按书本顺序罗列的知识点,便于大家去书中寻找)
所以看该文章前,需要有一定的C++基础,否则阅读起来可能有困难。
本文大致整理了第十七章的知识点,涉及到C++关于tuple
、bitset
和随机数的知识。
链接目录
- 第二章:变量与基本类型
- 第三章:字符串、向量和数组
- 第四章:表达式
- 第五章:语句
- 第六章:函数
- 第七章:类
- 第八章:IO库
- 第九章:顺序容器
- 第十章:泛型算法
- 第十一章:关联容器
- 第十二章:动态内存
- 第十三章:拷贝控制
- 第十四章:重载运算与类型转换
- 第十五章:面向对象程序设计
- 第十六章:模板与泛型编程
- 第十七章:标准库特殊设施
- 第十八章:用于大型程序的工具
- 第十九章:特殊工具与技术
tuple类型
tuple
定义在头文件tuple
中:将一组数据组合成单一对象,常用于函数返回多个值。
定义和初始化tuple
:
定义tuple
时需要指出每个成员的类型,tuple
的构造函数是explicit
的,需要提供显式初始化。make_tuple
通过参数列表判断类型。
tuple<size_t, size_t, size_t> threeD;//默认初始化为0
tuple<int, double> someVal(1, 3.14);
tuple<int, double> someVal = {1, 3.14};//错误
auto item = make_tuple("xx", 3, 3.14);
访问tuple
成员:
//返回一个引用
auto book = get<0>(item);//返回第一个成员
//如果不知道tuple的准确类型,可以通过辅助类模板来查询
typedef decltype(item) trans;
//获取tuple中的元素数量
size_t sz = tuple_size<trans>::value;
//声明第二个元素类型的变量
tuple_element<1, trans>::type cnt = get<1>(item);
使用tuple返回多个值
typedef tuple<string, int, double> info;
info getInfo(...){
info ret;
...
return ret;
}
使用函数返回的tuple
:
auto val = getInfo(...);
string s = get<0>(val);
int i = get<1>(val);
double d = get<2>(val);
bitset类型
bitset
类定义在头文件bitset
中。
定义和初始化bitset
:
bitset<32> bitvec(0xFFFF);//32位全1
位数大小必须是constexpr
的,初始化方法如下:
当使用一个整型值来初始化bitset
时,会被转换为unsigned long long
如果bitset
长度大于unsigned long long
剩余的高位置0。
当用string
初始化bitset
时,string
中下标最大的字符用来初始化bitset
的最低位。
bitset操作
提取bitset
的值:
unsigned long ulong = bitvec3.to_ulong();
cout << "ulong = " << ulong << endl;
随机数
C++应该使用default_random_engine
类和恰当的分布类对象,而不应该使用rand
库。
随机数引擎和分布
定义在头文件random
中。
default_random_engine e;
//输出十个随机数
for(size_t i = 0; i < 10; ++i)
cout << e() << endl;
分布类型和引擎:
//生成[0, 9]之间均匀分布的随机数
uniform_int_distribution<unsigned> u(0, 9);
default_random_engine e;
for(size_t i = 0; i < 10; ++i)
cout << u(e) << endl;
对于一个给定的发生器,每次运行都会返回相同的数值序列:
//每次调用都是相同的结果
void f(){
default_random_engine e;
uniform_int_distribution<unsigned> u(0, 9);
for(size_t i = 0; i < 10; ++i)
cout << u(e) << endl;
}
//将引擎和分布对象定义为static,则每次调用都会生成不同的序列
//虽然每次调用结果不一样,但是整个程序重复执行的结果仍然是一样的
void f(){
static default_random_engine e;
static uniform_int_distribution<unsigned> u(0, 9);
for(size_t i = 0; i < 10; ++i)
cout << u(e) << endl;
}
设置随机数发生器种子:在调试时,每次运行都产生相同的随机结果,但调试完毕,我们希望每次运行都会有不同的随机结果,此时可以通过种子来达到目的,引擎会利用种子从序列中的一个新位置重新开始生成随机数。
但是需要注意,种子相同,随机结果相同
有两种方式设置种子:
- 创建引擎对象时
- 调用
seed
成员
default_random_engine e(123);//使用给定的种子
e.seed(456);//设置种子值
最常用的随机种子生成:通过系统函数time
(定义在头文件ctime
中),time
返回以秒计的时间。time
返回从一个特定时刻到当前经过了多少秒。
default_random_engine e(time(0));//产生随机种子
其他随机数分布
生成随机实数:
default_random_engine e;
uniform_real_distribution<double> u(0, 1);
生成非均匀分布的随机数:例如正态分布,其中使用头文件cmath
中的lround
将随机数舍入到最接近的整数。
default_random_engine e;
normal_distribution<> n(4, 1.5);//均值为4,标准差为1.5的正态分布,类型为double
vector<unsigned> vals(9);
for(int i = 0; i < 200; ++i){
unsigned v = lround(n(e));
if(v < vals.size())
++vals[v];//统计每个数出现了多少次
}
for(int i = 0; i < vals.size(); ++i)
cout << i << ":" << vals[i] << endl;
bernoulli_distribution
类:返回bool
值,默认返回true
的概率为0.5
bernoulli_distribution b(0.55);//有55%的概率返回true
IO库再探
- 格式控制
- 未格式化IO
- 随机访问
格式化输入与输出
控制布尔值的格式:boolalpha
,默认情况下bool
打印1
或0
,通过boolalpha
输出true
或false
。
cout << "alpha bool values:" << boolalpha << true << " " << false << endl;
//输出 true false
//取消格式控制
cout << noboolalpha;
//输出 1 0
指定整型值的进制:通过showbase
操纵符可以在输出中显示进制
hex
:十六进制oct
:八进制dec
:十进制
cout << showbase;
cout << "八进制:" << oct << 20 << endl;
cout << "十六制:" << hex << 20 << endl;
cout << "十进制:" << dec << 20 << endl;
cout << noshowbase;
//另外十六进制中的字母默认是小写,可以通过uppercase来改为大写
cout << uppercase << showbase;
cout << hex << 1024;
cout << nouppercase << noshowbase << dec << endl;
控制浮点数格式:默认按六位精度打印,没有小数部分则不打印小数
- 以多高精度打印浮点值,即多少位数字,包含整数部分
- 数值打印为十六进制、定点十进制还是科学计数法形式
- 没有小数部分的浮点值是否打印小数点
指定打印精度:会按当前精度进行舍入,而非简单截断,如3.1415
舍入为3.142
通过precision
成员或setprecision
操纵符来改变精度,操纵符setprecision
等定义在头文件iomanip
中。
cout << setprecision(3) << 3.1415 << endl;
//等价
cout.precision(3);
cout << 3.1415 << endl;
指定浮点数记数法:
scientific
:科学计数法fixed
:定点十进制hexfloat
:十六进制计数法
打印小数点:showpoint
强制打印小数点,默认情况小数为0不打印小数点
输出补白:控制输出格式,这部分适合在使用的时候再进行查阅
setw
:指定下一个数字或字符串值的最小空间left
:表示左对齐输出right
:表示右对齐输出,默认internal
:控制负数的符号的位置,左对齐符号,右对齐值,中间用空格填setfill
:指定一个字符代替空格输出空白
控制输入格式:默认情况,输入运算符会忽略空白符(空格、制表、换行、回车、换纸)
cin >> noskipws;//让cin能够读取空白符
未列入知识点
- 未格式化的输入输出操作
- 流随机访问
- 正则表达式:书中只介绍了相关库的使用方法,这部分本身也比较难,本文不引入