
本文共 6035 字,大约阅读时间需要 20 分钟。
命名空间的using声明
std::cin
表示从标准输入中读取内容。此处使用作用域操作符(: : )的含义是:
**编译器应从操作符左侧名字所示的作用域中寻找右侧那个名字。**因此,std::cin的意思就是要使用命名空间std中的名字cin。
using声明,有了using声明就无需专门的前缀(形如命名空间::)
using namespcae::name
每个名字都需要独立的using声明
头文件不应包含using声明
标准库类型string
定义和初始化string对象
string s1;//默认初始化string s2=s1;//s2是s1的副本string s3="hiya";//s3是该字符串字面值的副本string s4(10,'c');//s4的内容是cccccccccc
直接初始化和拷贝初始化
- 如果使用等号(=)初始化一个变量,实际上执行的是拷贝初始化。
- 如果不适用等号,则执行的是直接初始化。
string对象上的操作
读写string对象
int main(){ string s; cin>>s; cout<<s<<endl; return 0;}
使用getline读取一整行
int main(){ string line; while(getline(cin,line)) cout<<line<<endl; return 0;}
string的empty和size操作
empty函数根据string对象是否为空返回一个布尔值
size函数返回string对象的长度(即string对象中的字符个数),可以使用size函数只输出长度超过80个字符的行。
string::size_type类型
size函数返回的是一个string::size_type类型
切记:不可让int类型的变量与size函数的返回值比较
比较string对象
按照字典序比较大小:
- 如果两个string类型的长度不同,而且较短string对象的每个字符都与较长的string对象相应位置上的字符相同,就说较短的string对象小于较长string对象。
- 如果两个string对象在某些对应的位置上不一致,则string对象比较的结果其实就是string对象第一对相异字符的比较结果。
为string类型赋值
string st1(10,'c'),st2;//st1的内容是cccccccccc;st2是一个空字符串st1=st2;//赋值:用st2的副本替换st1的内容//此时st1和st2都是空字符串
两个string对象相加
string s1="hello, ",s2="world\n";string s3=s1+s2;s1+=s2;
两个string对象相加得到一个新的string对象,其内容是把左侧运算对象与右侧的运算对象串接而成。
字面值和string对象相加
标准库允许把字符字面值和字符串字面值转换成string对象,所以在需要string对象的地方就可以使用这两种字面值来替代。
string s1 = "hello",s2="world";string s3 = s1 + ","+ s2 + '\n';
必须保证+两侧的运算对象至少有一个是string
处理string对象中的字符。
如果想对string对象中的每个字符做点什么操作,目前最好的办法是使用C++11新标准提供的一种语句:范围for语句这种语句遍历给定序列中每个元素并对序列中的每个值执行某种操作,其语法形式是:
for (declaration: expression) statement
其中,expression是一个对象,用于表示一个序列。
declaration部分负责定义一个变量,该变量用于访问序列中的基础元素。
每次迭代,declarationbufen的变量会被初始化为expression部分的下一个元素值。
使用范围for语句和ispunct函数来统计string对象中标点符号个数。
#include<iostream>#include<cctype>using namespace std;int main(){ string s("Hello World!!!"); decltype(s.size()) punct_cnt=0; for(auto c:s) if(ispunct(c)) ++punct_cnt; cout<<punct_cnt<<" punctuation characters in "<<s<<endl;}
使用范围for语句改变字符串中的字符
要改变string对象中字符的值,必须把循环变量定义成引用类型。
假设我们想要把字符串改写大写字母的形式。
#include<iostream>#include<cctype>using namespace std;int main(){ string s("Hello World!!!"); for(auto &c:s) c=toupper(c); cout<<s<<endl;}
只处理一部分字符
想要访问string对象中的单个字符有两种方式:
一种是使用下标,另一种是使用迭代器。
使用下标执行迭代
#include<iostream>#include<cctype>using namespace std;int main(){ string s("hello"); for(decltype(s.size())index =0 ; index!=s.size()&&!isspace(s[index]);++index) { s[index]=toupper(s[index]); } cout<<s;}
使用下标执行随机访问
例如我们想要编写一个程序把0到15之间的十进制数转换成对应的十六进制数形式,只需初始化一个字符串令其存放16个十六进制“数字”:
#include<iostream>#include<cctype>using namespace std;int main(){ const string hexdigits = "0123456789ABCDEF"; cout<<"Enter a series of numbers between 0 and 15" <<" separated by spaces. Hit ENTER when finished: " <<endl; string result; string::size_type n; while(cin>>n) { if(n<hexdigits.size()) result +=hexdigits[n]; } cout<<"Your hex number is: "<<result<<endl;}
标准库类型vector
标准库类型vector表示对象的集合,其中所有对象的类型都相同。集合中每个对象的类型都相同,索引用于访问对象。因为vector“容纳着”其他对象,所以它也常被称作容器.
需要指出的是,在早期C++标准中如果vector的元素还是vector(或者其他模板类型),必须在外层vector对象的右尖括号和其他元素类型之间添加一个空格
vector<vector<int> >//旧标准vector<vector<int>>//C++11标准
定义和初始化vector对象
vector<T> v1 //v1是一个空vector,它的潜在元素是T类型的,执行默认初始化。vector<T> v2(v1) //v2是包含有v1所有元素的副本vector<T> v2=v1 //等价于v2(v1),v2中包含了v1中所有元素的副本vector<T> v3(n,val) //v3包含了n个重复的元素,每个元素的值都是valvector<T> v4(n) //v4包含了n个重复执行值初始化的对象vector<T> v5{ a,b,c…} //v5包含了初始值个数的元素,每个元素被赋予响应的初始值vector<T> v5={ a,b,c…} //等价于v5{a,b,c}
列表初始值还是元素数量
vector<int> v1(10);//v1有10个元素,每个元素的值是0vector<int> v2{ 10};//v2有1个元素,该元素的值是10vector<int> v3(10,1);//v3有10个元素,每个值都是1vector<int> v4{ 10,1};//v4有2个元素,值分别是10和1
向vector对象添加元素
push_back将一个值push到vector的队尾。
如果在循环体内部包含有向vector对象添加元素的语句,则不能使用范围for循环。
#include<iostream>#include<vector>using namespace std;int main(){ string word; vector<string> text; while(cin>>word) { text.push_back(word); } for(auto i:text) cout<<i<<" ";}
其他vector操作
v.empty() //如果v不含有任何元素,返回真,否则返回假v.size() //返回v中元素个数v.push_back(t) //向v的尾端添加一个值为t的元素v[n] //返回v中第n个位置上的引用v1 = v2 //用v2中的元素拷贝替换v1v1={ a,b,c…} //用列表中的元素拷贝替换v1v1 == v2 //v1和v2相等当且仅当它们的元素数量相同且对应位置的元素值都相同
可以使用范围for语句处理vector对象中的所有元素。
#include<iostream>#include<vector>using namespace std;int main(){ vector<int> v{ 1,2,3,4,5,6,7,8,9}; for(auto &i:v) i *= i; for(auto i:v) cout<<i<<" "; cout<<endl;}
计算vector内对象的索引
假设有一组成绩集合,其中成绩的取值从0到100。以10分为一个分数段,要求统计各个分数段有多少个成绩。
#include<iostream>#include<vector>using namespace std;int main(){ vector<unsigned> scores(11,0); unsigned grade; while(cin >> grade) { if(grade <= 100) { ++scores[grade/10]; } } for(auto i:scores) { cout<<i<<" "; }}
不能用下标形式添加元素
迭代器介绍
使用迭代器
和指针不一样的是,获取迭代器不是取地址符,有迭代器类型同时返回迭代器的成员。比如,这些类型都拥有名为begin和end的成员。
其中begin成员负责返回第一个元素(或第一个字符)。
end成员返回容器尾元素的下一个位置。
迭代器运算符
*iter | 返回迭代器iter所指元素的引用 |
---|---|
iter->mem | 解引用iter并获取该元素名为mem的成员 |
++iter | 令iter指向容器的下一个元素 |
–iter | 令iter指向容器的上一个元素 |
iter1 == iter2 | 判断两个迭代器是否相等 |
iter1 != iter2 | 判断两个迭代器是否不相等 |
将string对象的第一个字母改为大写形式
#include<iostream>#include<vector>#include<cctype>using namespace std;int main(){ string s("some string"); if(s.begin() != s.end()) { auto it=s.begin(); *it=toupper(*it); } cout<<s;}
将迭代器从一个元素移动到另一个元素
迭代器使用递增(++)运算符来从一个元素移动到下一个元素。从逻辑上来说,迭代器的递增和整数递增类似,整数递增是在整数值上“加1”,迭代器递增则是迭代器“向前移动一个位置”。
迭代器类型
迭代器的标准库使用iterator和const_iterator来表示迭代器类型。
begin和end运算符
为了便于得到const_iterator类型的返回值,C++11标准中引入了两个新函数
cbegin和cend。
结合解引用和成员访问操作
解引用迭代器可获得迭代器所指的对象,如果该对象恰好是类,就有可能希望进一步访问它的成员。
(*it).empty()
谨记,但凡使用了迭代器的循环体都不要向迭代器所属容器添加元素。
迭代器运算
#include<iostream>#include<vector>using namespace std;int main(){ int sought; cin>>sought; vector<int> text{ 1,2,3,4,5}; auto beg = text.begin(); auto end = text.end(); auto mid = text.begin()+(end - beg)/2; while(mid!=end) { if(sought<*mid) { end=mid; } else beg=mid+1; mid=beg+(end-beg)/2; }}
发表评论
最新留言
关于作者
