5、标准库
约 7429 字大约 25 分钟
2025-06-22
stabdard template liberary标准模板库 广义上分为容器container、算法algorithm、迭代器iterator 容器和算法之间 通过迭代器进行无缝连接 STL中几乎所有代码都采用函数模板或类模板
六大组件
容器
各种数据结构vector、list、deque、set、map等用来存放数据
序列式容器
强调值的排序,序列式容器中的每个元素均有固定位置
关联式容器
树、图等结构,各元素之间没有严格的顺序关系
算法
各种常用算法sort、find、copy、for_search等
质变算法
运算过程中会更改区间中元素的内容,如拷贝、替换、删除等
非质变算法
运算过程中不会更改区间的元素内容,如查找、计数、遍历、寻找极值等
迭代器
扮演容器与算法之间的胶合剂 提供一种方法,使之能够依序访问某个容器中的各个元素,又无需暴露该容器内部表示方式 每个容器都有自己专属的迭代器 类似指针
算法通过迭代器才能访问容器中的元素 大多数迭代器都是双向迭代器或随机访问迭代器
种类
输入迭代器
对数据只读访问 支持++、==、!=
输出迭代器
对数据只写访问 支持++
前向迭代器
读写操作,能向前推进迭代器 支持++、==、!=
双向迭代器
读写操作,能向前向后操作 支持++、--
随机访问迭代器
读写操作,可以跳跃方式访问任意数据,功能最强迭代器 支持++、--、[n]、-n、<、<=、>、>=
仿函数
行为类似函数,可作为算法的某种策略
适配器(配接器)
一种用来修饰容器或者仿函数或迭代器接口的东西
空间配置器
负责空间配置和管理
内建函数对象
functional STL内建了一些函数对象:
谓词
返回bool类型的仿函数称为谓词
如果仿函数接收一个参数则称为一元谓词 接收两个参数称为二元谓词
一些算法的形参名为_Pred这样的参数就需要传入一个谓词或者返回值为bool的函数
算数仿函数
实现四则运算
template<class T> T plus<T>//加法仿函数
template<class T> T minus<T>//减法仿函数
template<class T> T multiplies<T>//乘法仿函数
template<class T> T divides<T>//除法仿函数
template<class T> T modulus<T>//取模仿函数
template<class T> T negate<T>//取反仿函数除了nagate是一元运算,其他都是二元运算
使用
nagate<int>n;
n(50);//-50
plus<int>p;
p(1,2);//3关系仿函数
实现关系对比
template<class T> bool equal_to<T>//等于
template<class T> bool not_equal_to<T>//不等于
template<class T> bool greater<T>//大于
template<class T> bool greater_equal<T>//大于等于
template<class T> bool less<T>//小于
template<class T> bool less_equal<T>//小于等于逻辑仿函数
实现逻辑运算
template<class T> bool logical_and<T>//逻辑与
template<class T> bool logical_or<T>//逻辑或
template<class T> bool logical_not<T>//逻辑非容器
string字符串
构造
string str=string();//等于string str=string();无参构造,创造一个空字符串
string str2=string((const string& str);//通过一个字符串初始化
string str3=string(const char* s);//通过字符数组构造字符串
string str4=string(int n,char c);//通过指定数量的指定字符构造字符串,用n个c填充字符串赋值
string& operator=(const char* s);//char*类型字符串 赋值给当前的字符串
string& operator=(const string &s);//把字符串s赋给当前的字符串
string& operator=(char c);//字符赋值给当前的字符串
string& assign(const char *s);//把字符串s赋给当前的字符串
string& assign(const char *s[int n);//把字符串s的前n个字符赋给当前的字符串
string& assign(const string &s);//把字符串s赋给当前字符串
string& assign(int n,char c);//用n个字符c赋给当前字符串
string& assign(const string &s,int start,int n);//将s前n个字符赋值给字符串存取
char& operator[]](int n);//通过[]方式取索引为n的字符
char& at(int n)://通过at方法获取索引为n的字符拼接
string& operator+=(const string& str);//重载+=操作符
string& operator+=(const char* str);//重载+=操作符
string& operator+=(const char c);//重载+=操作符
string& append(const char *s);//把字符串s连接到当前字符串结尾
string& append(const char*s,int n);//把字符串s的前n个字符连接到当前字符串结尾
string& append(const string &s);//同operator+=()
string& append(const string &s,int pos,int n);//把字符中从pos开始的n个字符连接到当前字符串结尾
string& append(int n,char c);//在当前字符串结尾添加n个字符c查找
查找一个字符串或一个字符,返回在指定的字符串中出现的下标,如果找不到返回-1
int find(const string& str,int pos = 0) const; //查找str第一次出现位置,从pos开始查找
int find(const char* s,int pos = 0) const; //查找s第一次出现位置,从pos开始查找
int find(const char* s,int pos,int n) const; //从pos位置查找s的前n个字符第一次位置
int find(const char c,int pos = 0) const; //查找字符c第一次出现位置
int rfind(const string& str,int pos = npos) const;//查找str最后一次位置,从pos开始查找
int rfind(const char* s,int pos = npos) const;//查找s最后一次出现位置,从pos开始查找
int rfind(const char* s,int pos,int n) const;//从pos查找s的前n个字符最后一次位置
int rfind(const char c,int pos = 0) const; //查找字符c最后一次出现位置替换
将一个字符串中指定下标范围的部分替换成新的字符串
string& replace(int pos,int n,const string& str); //替换从pos开始n个字符的字符串
strstring& replace(int pos,int n,const char* s); //替换从pos开始的n个字符的字符串比较
使用比较运算符 顺序:按asciss码大小依次比较字符串的每一位字符,如果字符相同继续比较后面的一位,直到某一位能分出大小
返回结果是bool类型,但比较通常有三种结果(<>=),bool类型无法表现出所有结果。因此string提供了一个compare函数,返回值是int类型 -1表示str1< str2 1表示str1>str2 0表示str1=str2
str1.compare(str2);子串的获取
string substr(int pos=0,int n=npos)const;//返回pos开始的n个字符插入
string& insert(int pos,const char* s); //插入字符串
string& insert(int pos,const string& str); //插入字符串
string& insert(int pos,int n,char c);//在指定位置插入n个字符c删除
string& erase(int pos,int n = npos);//删除从Pos开始的n个字符vector向量
vector与数组相似,差别是空间运用的灵活性
底层是顺序表
数组是静态空间,一旦配置了就不能改变,要增删就要换空间,需要自己配置新空间再释放原来的空间 vector是动态空间,随着元素的加入,它的内部机制会自动扩充空间以容纳新元素 vector是使用类模板实现的
构造
vector<T> v; //采用模板实现类实现,默认构造函数
vector(v.begin(),v.end());//将v[begin(),end())区间中的元素拷贝给本身
vector(n,elem);//构造函数将n个elem指贝给本身。
vector(const vector &vec);//拷贝构造函数
//例子 使用第二个构造函数
int arr[] = {2,3,4,1,9};
vector<int> vl(arr,arr + sizeof(arr) / sizeof(int));赋值
assign(beg,end);//将[beg,end)区间中的数据拷贝赋值给本身
assign(n,elem);//将n个elem拷贝赋值给本身。
vector& operator=(const vector &vec);//重载等号操作符
swap(vec);// 将vec与本身的元素互换。大小操作
v.size();//返回容器中有多少个元素
v.empty();//判断容器是否为空
v.capacity;//返回容器的容量
//重新指定容器的长度
v.resize(n);//如果新的长度比原来的小,会保留容器中前n个元素,如果新的长度比原来的大,会在后面填充默认值。
v.resize(n,c)//当新的长度比原来的大可以指定在后面填充的元素(c)
v2.swap(v1);//互换两个容器的元素vector开辟空间是预开辟机制,提前开辟一定大小的空间添加新元素时就往里面存存满后再开辟一定大小的空间,所以vector的size和capacity是不同的,size返回的是存储有效元素的个数,capacity返回的是容器当前能存储的元素个数
数据存取
at(int idx); //返回索引idx所指的数据,如果idx越界抛出out_of_range异常
operator[];//返回索引idx所指的数据,越界时,运行直接报错
front();//返回容器中第一个数据元素
back();//返回容器中最后一个数据元素插入和删除
insert(const_iterator pos,int count,ele);//迭代器指向位置pos插入count个元素ele
push_back(ele); //尾部插入元素ele
pop_back();//删除最后一个元素
erase(const_iterator start,const_iterator end);//删除选代器从start到end之间的元素
erase(const_iterator pos);//删除迭代器指向的元素
clear();//删除容器中所有元素迭代器
使用普通指针依次指向vector中的所有元素 可以通过指针修改元素
begin()获取vector中的首元素的地址 end()获取vector中的最后一位元素的下一位的指针(不存在的)
vector<int>::iterator it=v.begin();//获取vector中的首个元素的地址
it++;//使迭代器指针向后挪动一位获取第二个元素的地址循环使用迭代器获取元素
for (vector<int>::iterator it=v.begin();it!=v.end();it++){
cout<<*it<<endl;
}
//逆序遍历
for (vector<int>::iterator it=a.end();it!=a.begin();){
it--;
cout<<*it<<endl;
}
//可以缩写
for (int ele:v){
cout<<ele<<endl;
}依次将容器中的每一个元素给ele赋值(不能通过ele修改元素)在int后加&引用可以修改
deque双端队列
底层是分段数组 deque也是一个可变长数组,所有适用于vector的操作都适用于deque deque随机存储任何元素时间复杂度都是O(1)(但慢于vector) 与vector的区别:vector在头部删除或添加元素的速度很慢,在尾部删除或添加元素性能较好,deque在头尾增删元素都具有较好的性能
底层是索引表 因此迭代器不是普通的指针,不能进行++或--操作获取元素
插入和删除
它有两种vector没有的成员函数
void push_front(const T& val);//将val插入到首位
void pop_front();//删除首位元素stack栈
先进后出 stack没有迭代器 也不能遍历
构造
stack<T> stkT;//默认构造
stack(const stack& stk);//拷贝构造赋值
stack& operator=(const stack &stk);//重载赋值运算符存取
s.push(elem);//向栈顶添加元素(压栈、入栈)
s.pop();//从栈顶移除一个元素(弹栈、出栈)
s.top();//返回栈顶元素大小操作
s.empty();//判断是否为空
s.size();//返回栈中有几个元素queue队列
先进先出 没有迭代器 不能遍历 queue的成员函数和stack类似,只不过push和pop是在队尾添加或队首删除元素
que.front()//返回队首元素
que.back()//返回队尾元素list列表
底层是双链表
list不能使用普通的指针做迭代器因为它的节点不一定在同一块连续的内存上 list的迭代器是Bidirectional iterators vector在插入和删除操作时可能造成空间重分配导致原有的迭代器失效,但list的迭代器不会出现这样的问题
构造
list<T> lstT;//默认构造
list(begin,end);//构造函数,将[begin,end)区间的元素拷贝给本身
list(n,elem);//将n个elem拷贝给本身
list(const list &lst);//拷贝构造插入和删除
push_back(elem);//在容器尾部加入一个元素
pop_back(;//删除容器中最后一个元素
push_front(elem);//在器开头插入一个元素
pop_front();//从容器开头移除第一个元素
insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除pos位置的数据,返回下一个数据的位置。
remove(elem);//删除容器中所有与elem值匹配的元素。大小操作
size();//返回容器中元素的个数
empty();//判断容器是否为空
resize(num);//重新指定容器的长度为num.
// 若容器变长,则以默认值填充新位置。
// 如果容器变短,则末尾超出容器长度的元素被删除。
resize(num,elem);//重新指定容器的长度为num,如果容器变长使用指定的elem填充新位置赋值
assign(beg,end);//将[beg,end)区间中的数据拷贝赋值给本身
assign(n,elem);//将n个elem拷贝赋值给本身
list& operator=(const list &lst);//重载等号操作符
swap(lst);//将lst与本身的元素互换。数据存取
front();//返回第一个元素
back();//返回最后一个元素反转、排序
reverse();//反转链表,比如lst包含1,3,5元素,运行此方法后,lst就包含5,3,1元素
sort(); //list排序set/multiset集合/多集
底层实现是红黑树
set中所有元素都会根据值自动排序,不允许有重复的元素 multiset和set相同但允许有重复的元素
set的迭代器是只读的迭代器,不能通过迭代器改变set中的值 对set中的元素进行增删操作后迭代器依旧有效
set中没有下标
插入
s.insert(c);//插入c删除
s.erase(it);//删除当前迭代器指向的元素,返回下一个元素的指针
s.clear();//清空set查找
s.find(a);//查找元素c是否存在,如果存在返回这个元素的迭代器,如果不存在返回set.end()指向最后一个元素的后一个地址
s.count();//查找元素的个数
s.lower_bound(a);//返回第一个元素小于等于指定元素的迭代器
s.upper_bound(a);//返回第一个大于指定元素的迭代器pair对
相当于python中的字典的一个元素
将两个数据整合到一起称为一个整体 两个数据的数据类型可以不同 这两个数据组合到一个称为键值对
构造
pair<T1,T2>p(n,c);
pair<T1,T2>p=make_pair(n,c);取值
p.first;//获取第一个元素(键)
p.second;//获取第二个元素(值)map/multimap图
相当于python中的字典
map中存储的元素是一个个的pair 存储的所有键值对会按照key进行排序 map中不允许出现重复的key,但multimap中可以出现重复的key 可以通过迭代器修改值,但不能修改键
构造
map<T1,T2>m;//无参构造
//拷贝构造添加
如果添加的元素键已经存在则是修改操作
m.insert(pair<T1,T2>(n,c))
m.insert(make_pair(n,c))
m.insert(pair<T1,T2>::value_type(n,c)));
m[key]=value;遍历
for (map<T1,T2>::iterator it=m.begin();it!=m.end();it++) {
cout<<(*it).first<<endl;
cout<<(*it).second<<endl;
}
for(pair<T1,T2>p:m){
cout<<p.first<<endl;
cout<<p.seconf<<endl;
}删除
m.erase(p);//删除p指向的元素
m.erase(key);//删除指定key的键值对查找
m.find(key);//查找指定键的键值对,返回其地址(迭代器的对象)
m.count(key);//查找有多少个对应键的元素
m.lower_bound(a);//返回第一个元素小于等于指定元素的迭代器
m.upper_bound(a);//返回第一个大于指定元素的迭代器大小操作
m.size();
m.empty();自定义排序规则
map使用的底层数据结构为一颗红黑树(红黑树是一颗高度平衡二叉排序树),因为map的各种操作接口,RB-Tree也都提供了,所以几乎所有的map操作行为,都只是转调用了RB-Tree的操作行为而已。TB-Tree中的key是按弱序排序的,因此map中的key也是按弱序排列的,所以任意更改map的key会严重破坏map组织的,也就是key不能修改(key也就不能使用sort排序。) map模板的定义
template <class _Key, class _Tp,
class _Compare __STL_DEPENDENT_DEFAULT_TMPL(less<_Key>),
class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >class map;一般情况下,我们定义一个map是直接使用前两个参数的,也就是说我们一般都指定key和value的类型,没有指定Compare类的类型。所以默认情况下,key的类型必须能够进行<运算,且唯一,也就说关键字类型key必须严格弱序。 当我们使用Compare类来自定义排序关键字类型key的时候,必须要保证“行为正常”的<运算符或>运算符。
算法
算法主要是由头文件< algorithm> < functional> < numeric>组成 < algorithm>是所有STL头文件中最大的一个,范围涉及到比较、交换、查找、遍历操作、复制、修改等等 < numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数 < functional>定义了一些模板类,用以声明函数对象。
遍历
for_each(iterator begin,iterator end, _func);class func1{//仿函数
public:
void operator()(){};
}
func2(){};//普通函数
for_each(v.begin(),v.end(),func1());//仿函数需要调用小括号
for_each(v.begin(),v.end(),func2;//普通函数不需要小括号,只需把函数指针传入即可搬运
使用搬运算法时目标容器必须要有容量,且容量必须大于要搬运的数据的长度 可以使用reset函数设置容量,直接创建容器是没有容量的
transform(iterator begin1,iterator end1,iterator begin2,_func)//搬运容器到另一个容器中//beg1 源容器开始迭代器 //end1 源容器结束迭代器 //beg2 目标容器开始迭代器 // _ func函数或者函数对象
查找
在查找自定义数据类型的时候需要重载== 让函数知道怎么对比
find(iterator begin,iterator end,value);//在begin到end的范围内查找元素value
//找到的话返回value地址,没有找到返回end的下一位,都是迭代器对象
find_if(iterator begin,iterator end,_Pred);//按条件查找元素
//_Pred函数或谓词
//找到返回指定位置迭代器,找不到返回结束迭代器
adjacent_find(iterator begin,iterator end);//查找相邻重复元素
binary_search(iterator begin,iterator end,value);//二分查找法
//必须在有序的序列中才能用
//查到返回true,没有查到返回false
count(iterator begin,iterator end,value);//统计元素出现次数
count_if(iterator begin,iterator end,_Pred)//按条件统计元素个数排序
random_shuffle如果不使用srand函数设置一个随机数种子那么它会使用默认的种子进行打乱,可能运行几次打乱的结果一样
sort(iterator begin,iterator end,_Pred);//对容器内元素进行排序
//如果不填谓词就默认升序
random_shuffle(iterator begin,iterator end);//洗牌,指定范围内的元素随机调整次序
merge(iterator begin1,iterator end1,iterator begin2,iterator end2,iterator dest);//容器元素合并,并存储到另一容器中,两个容器必须是有序的,合并后的数据也是有序的,也需要提前分配空间
//begin1,end1是容器1的开始和结束迭代器
//begin2,end2是容器2的开始和结束迭代器
//dest是目标容器的开始迭代器
reverse(iterator begin,iterator end);//反转指定范围的元素拷贝和替换
copy(iterator begin,iterator end,iterator dest);//容器内指定范围的元素拷贝到另一容器中
replace(iterator begin,iterator end,oldvalue,newvalue);// 将容器内指定范围的旧元素修改为新元素
replace_if(iterator begin,iterator end,_Pred,newvalue);//容器内指定范围满足条件的元素替换为新元素
swap(container c1,container c2);// 互换两个容器的元素
//c1是容器1,c2是容器2算数生成算法
算数生成算法属于小型算法,属于头文件< numeric>
accumulate(iterator begin,iterator end,value)//计算区间内容器元素累计总和
//value起始值
fill(iterator begin,iterator end,value)//向容器中添加元素
//value填充的值常用的集合算法
set_intersection(iterator begin1,iterator end1,iterator begin2,iterator end2,iterator dest);// 求两个容器的交集
//dest目标迭代器的起始位置
set_union(iterator begin1,iterator end1,iterator begin2,iterator end2,iterator dest);// 求两个容器的并集
set_difference(iterator begin1,iterator end1,iterator begin2,iterator end2,iterator dest);// 求两个容器的差集文件操作
需要包含头文件< fstream>
分类
文本文件
文件以文本的ASCII码形式存储在计算机中
二进制文件
文本以二进制形式存储在计算机中,用户不能直接读懂它们
操作步骤
打开方式
iosout只写方式打开 iosapp追加方式写文件 iosbinary二进制方式打开
打开方式可以用|操作符配合使用
如
ios::binary|ios::out操作方式
输入输出是相对内存而言的 从控制台输出到文件(output),从文件输入到控制台(input) 内存为内,文件为外;向内输入,向外输出;读为入,写为出;
ofstream写操作 ifstream读操作 fstream读写操作
打开后可以使用is_open()函数判断是否打开成功,返回值为布尔类型
以写文件为例
//包含头文件
#include <fstream>
//创建流对象
ofstream ofs;
//也可以直接初始化流对象
ofstream ofs("文件路径",打开方式);
//打开文件
ofs.open("文件路径",打开方式);
//写数据
ofs<<"写入的数据";
//关闭文件
ofs.close();读取文件的四种方式
ifs的getline一行一行获取,两个参数的含义是存放的空间以及目标空间的大小 全局函数getline()
char buf1[1024];
while (ifs>>buf1){//while运行到数组末尾会有NULL
cout<<buf1<<endl;
}
//getline一行一行获取,两个参数的含义是存放的空间以及目标空间的大小
char buf2[1024];
while(ifs.getline(buf2, sizeof(buf2))){//一行一行地获取
cout<<buf2<<endl;
}
string buf3;
//全局函数getline()
while (getline(ifs,buf3)){
cout<<buf3<<endl;
}
char c;
//~(c=ifs.get())
//!(ifs.eof())
//(c=ifs.get())!=EOF//end of file
while ((c=ifs.get())!=EOF){
cout<<c;
}二进制方式
打开方式指定ios::binary
写文件主要利用流对象调用成员函数write
ofstream& write(const char*buffer,int len);字符指针buffer指向内存中一段存储空间,len是读写的字节数
class Person{
public:
char name[10];
int age;
};
int main(){
ofstream ofs("person.txt",ios::binary|ios::out);
Person p{"tom",18};
//强制转换字符指针,否则返回的是p的类指针
ofs.write((const char *)&p,sizeof(Person));
ofs.close();
return 0;
}写文件主要利用流对象调用成员函数read
ifstream& read(char*buffer,int len);之所以用char* 指针是因为需要字节的替换,常量指针用于不对引用参数做改变 字符指针buffer指向内存中一段存储空间,len是读写的字节数
class Person{
public:
char name[10];
int age;
};
int main(){
ifstream ifs("D:\\垃圾\\person.txt",ios::binary|ios::in);
if (!ifs.is_open()){
cout<<"cnm"<<endl;
return -1;
}
Person p;
ifs.read((char*)&p, sizeof(Person));
cout<<p.name<<p.age<<endl;
ifs.close();
return 0;
}输入输出流
定义了四个标准流对象 重定向:将输入的源或输出的目的地改变、
cin标准输入流
用于从键盘读取数据,也可以重定向为从文件中读取数据
在Windows中在单独一行按ctrl+z和回车键就代表输出结束 IUNIX/Linux中ctrl+d代表输出结束
get函数
不会跳过空格、制表符、回车等特殊字符
c=cin.get();cout标准输出流
用于向屏幕输出出错信息,不能重定向
endl
endl和换行符并不同,它用于结束当前行的输出并刷新缓冲区
流操控算子控制输出格式
流操纵算子(格式控制符) 常用
*dec//以十进制形式输出整数
hex//以十六进制形式输出整数
oct//以八进制形式输出整数
fixed//以普通小数形式输出浮点数
scientific//以科学计数法形式输出浮点数
left//左对齐,即在宽度不足时将填充字符添加到右边
*right//右对齐,即在宽度不足时将填充字符添加到左边
setbase(b)设置输出整数时的进制,b=8、10或16
setw(w)//指定输出宽度为w个字符,或输人字符串时读入W个字符
setfill(c)//在指定输出宽度的情况下,输出的宽度不足时用字符c填充(默认情况是用空格填充)
setprecision(n)//设置输出浮点数的精度为n。在使用非 fixed且非scientific方式输出的情况下,n即为有效数字最多的位数,如果有效数字位数超过n,则小数部分四舍五人,或自动变为科学计数法输出并保留一共n位有效数字;在使用fxed 方式和 sci-entific方式输出的情况下,n是小数点后面应保留的位数
setiosflags(标志)//将某个输出格式标志置为1
resetiosflags(标志)//将某个输出格式标志置为0不常用
boolapha//把true和false输出为字符串
*noboolalpha//把true和false输出为0、1
showbase//输出表示数值的进制的前缀
*noshowbase//不输出表示数值的进制的前缀
showpoint//总是输出小数点
*noshowpoint//只有当小数部分存在时才显示小数点
showpos//在非负数值中显示+
*noshowpos//在非负数值中不显示+
*skipws//输入时跳过空白字符
noskipws//输人时不跳过空白字符
uppercase//十六进制数中使用'A~'E。若输出前缀,则前缀输出“0X”,科学计数法中输出E
*nouppercase//十六进制数中使用'a ~'e。若输出前缀,则前缀输出“0x”,科学计数法中输出'e'
internal//数值的符号(正负号)在指定宽度内左对齐,数值右对齐,中间由填充字符填充其中的“ * ”不是算子的一部分,* 表示默认使用该算子 这些算子的使用方法是用"<<"和cout连用
算子的标志:
ios::left
ios::right
ios::internal
ios::showbase
ios::showpos
ios::showpoint
ios::uppercase
ios::fixed
ios;:scientific标志的含义和同名算子一样 这些标志实际上是某比特位为1,其他比特位为0的整数 多个标志可以用“|”运算符连接,表示同时设置
cout<<setiosflags(ios::scientific|ios::showpos)<<12.34;如果两个相互矛盾的标志被同时设置(如fixed、scientific)那么结果可能是两个标志都不起作用
setw算子起的作用是一次性的只影响下一次输出每次需要指定输出宽度时都要使用setw setw还可以控制cin
string s1,s2;
cin>>setw(4)>>s1,setw(3)>>s2;s1只读入4个字符,s2只读入3个字符
ostrea类的成员函数
成员函数//相同作用的操纵流算子
precision(n)//setprecision(n)
width(w)//setw(w)
fill(c)//setfill(c)
setf(标志)//setiosflags(标志)
unsetf(标志)//resetiosflags(标志)其中用到的标志与其相同作用的流算子用到的标志相同
put成员函数
可以用来输出一个字符,其参数类型为int,的表示要输出字符的ascii码,返回值时cout的引用
cerr标准错误输出流
用于向屏幕输出出错信息,不能被重定向 常用于打印错误日志 cerr不使用缓冲区,直接向显示器输出信息
cerr对应c语言的stderr,和cout不同的是它每次输出都要刷新缓冲区无论是否使用endl,所以在打印关键信息的时候应该使用cerr,以免cout缓存输出的信息导致错误信息在不适合的地方输出
clog
输出到clog中的信息会先被存放到缓冲区,缓冲区满或者刷新时才输出到屏幕 常用于打印正常的日志
贡献者
版权所有
版权归属:wynnsimon
