命名空间的using声明
- ::位域操作符
- std::cin 意思是就是使用命名空间std的名字cin
- 按照规定,每个using声明引入命名空间中的一个成员。
- 位于头文件的代码一般不应该使用using声明。可能会产生名字冲突。
标准库类型string
- 标准库类型string表示可变长的字符序列。
- 初始化:
string s1 | 默认初始化,s1是一个空串 |
---|
string s2(s1) | s2是s1的副本 |
string s2 = s1 | 等价于s2(s1),s2是s1的副本 |
string s3(“value”) | s3是字面值“value”的副本,除了字面值最后的那个空字符外 |
string s3 = “value” | 等价于s3(“value”),s3是字面值"value"的副本 |
string s4(n, ‘c’) | 把s4初始化为由连续n个字符c组成的串 |
- 使用“=”实际上执行的是拷贝初始化,如果不适用“=”,则是直接初始化
string s1="hello word!";//拷贝初始化
string s2("hiya");//直接初始化
string对象上的操作
os<<s | 将s写到输出流os当中,返回os |
---|
is >> s | 从is中读取字符串赋给s,字符串以空白分割,返回is |
getline(is, s) | 从is中读取一行赋给s,返回is |
s.empty() | s为空返回true,否则返回false |
s.size() | 返回s中字符的个数 |
s[n] | 返回s中第n个字符的引用,位置n从0计起 |
s1+s2 | 返回s1和s2连接后的结果 |
s1=s2 | 用s2的副本代替s1中原来的字符 |
s1==s2、s1!=s2 | 如果s1和s2中所含的字符完全一样,则它们相等;string对象的相等性判断对字母的大小写敏感 |
<, <=, >, >= | 利用字符在字典中的顺序进行比较,且对字母的大小写敏感 |
string加法运算
string s1="hi,",s2="bee";
string s3=s1+s2;//s3="hi,bee"
string s4=s1+"word";//s4="hi,word"
string s5="hi,"+"error";//错误,两个对象都不是string
- 注意当string 对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符(+)的两侧运算对象至少一个是string。
- string s6=“hello”+","+s2;//错误=>string s6=(“hello”+",")+s2;
处理string对象中的字符
isalnum(ch) | 当c是字母或数字时为真 |
---|
isalpha(ch) | 当c是字母时为真 |
iscntrl(ch) | 当c是控制字符时为真 |
isdigit(ch) | 当c是数字时为真 |
isgraph(ch) | 当c不是空格但可以打印时为真 |
islower(ch) | 当c是小写字母时为真 |
isprint(ch) | 当c是可打印字符时为真 |
ispunct(ch) | 当c是标点符号时为真 |
isspace(ch) | 当c是空白时为真(空格、横向制表符、纵向制表符、回车符、换行符、进纸符) |
isupper (ch) | 当c是大写字母时为真 |
isxdigit (ch) | 当c是十六进制数字时为真 |
tolower(ch) | 当c是大写字母,输出对应的小写字母;否则原样输出c |
toupper (ch) | 当c是小写字母,输出对应的大写字母;否则原样输出c |
string s1("some string");
for(auto c:s1)
cout<<c<<endl;
- 如果想要改变string对象中字符的值,必须把循环变量定义成引用类型
string s("hello,word!");
//转化成大写形式
for(auto &c:s)
c=toupper(c);
cout<<s<<endl;
- 如果想要对某个或一部分字符串进行修改,可以使用下标运算
标准库类型vector
- vector 表示对象的集合,其中所有对象的类型都相同。
- vector 也被称为“容器”
- ** vector 是模板而不是类型,由vector生成的类型必须包含vector中的元素类型,例如:vector< int> **
- 定义初始化:
vector< T> v1 | v1是一个空vector,它潜在的元素是T类型的,执行默认初始化 |
---|
vector v2(v1) | v2中包含有v1所有元素的副本 |
vector v2 = v1 | 等价于v2(v1),v2中包含v1所有元素的副本 |
vector v3(n, val) | v3包含了n个重复的元素,每个元素的值都是val |
vector v4(n) | v4包含了n个重复地执行了值初始化的对象 |
vector v5{a, b, c…} | v5包含了初始值个数的元素,每个元素被赋予相应的初始值 |
vector v5={a, b, c…} | 等价于v5{a, b, c…} |
- 列表初始化vector对象:1.拷贝初始化。2.提供类内初始值。3. 花括号vector< string> v{“a”, “an”, “the”};
- 如果使用圆括号(),提供的值使用老构造vector对象的
vector<int >v1(10);//v1有是个元素,每个值都是0
vector<int>v2{10}//v2有一个元素,是10
vector<int>v3(10,1)//v3有10个元素,每个的值都是1
vector<string>v4{"hi"};//列表初始化:v4有一个元素
vector<string>v5("hi");//错误
vector<string>v6{10};//v6有10个默认初始值
v.emtpy() | 如果v不含有任何元素,返回真;否则返回假 |
---|
v.size() | 返回v中元素的个数 |
v.push_back(t) | 向v的尾端添加一个值为t的元素 |
v[n] | 返回v中第n个位置上元素的引用 |
v1 = v2 | 用v2中的元素拷贝替换v1中的元素 |
v1 = {a,b,c…} | 用列表中元素的拷贝替换v1中的元素 |
v1 == v2、v1!=v2 | v1和v2相等当且仅当它们的元素数量相同且对应位置的元素值都相同 |
<,<=,>, >= | 顾名思义 以字典顺序进行比较 |
- 范围for语句内不应该改变其遍历序列的大小。
- vector对象(以及string对象)的下标运算符,只能对确知已存在的元素执行下标操作,不能用于添加元素。
迭代器
- 容器都可支持迭代器
- 类似于指针,迭代器提供了对对象的间接访问。
- ** 和指针不一样的是,获取迭代器不是使用取地址符,有迭代器的类型同时拥有返回迭代器的成员**
迭代器使用
- vector::iterator iter。
- auto b = v.begin();返回指向第一个元素的迭代器。
- auto e = v.end();返回指向最后一个元素的下一个(哨兵,尾后,one past the end)的迭代器(off the end)。
- 如果容器为空, begin()和 end()返回的是同一个迭代器,都是尾后迭代器。
- 使用解引用符*访问迭代器指向的元素。
- 养成使用迭代器和!=的习惯(泛型编程),for循环不用总考虑大于和小于。
- 容器:可以包含其他对象;但所有的对象必须类型相同。
- 迭代器(iterator):每种标准容器都有自己的迭代器。C++倾向于用迭代器而不是下标遍历元素。
- const_iterator:只能读取容器内元素不能改变。
- 箭头运算符: 解引用 + 成员访问,it->mem等价于 (*it).mem
- 注意:但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素
*iter | 返回迭代器iter所指向的元素的引用 |
---|
iter->mem | 等价于(*iter).mem |
++iter | 令iter指示容器中的下一个元素 |
–iter | 令iter指示容器中的上一个元素 |
iter1 == iter2 | 判断两个迭代器是否相等 |
迭代器的运算
iter + n | 迭代器加上一个整数值仍得到一个迭代器,迭代器指示的新位置和原来相比向前移动了若干个元素。结果迭代器或者指示容器内的一个元素,或者指示容器尾元素的下一位置。 |
---|
iter- n | 迭代器减去一个证书仍得到一个迭代器,迭代器指示的新位置比原来向后移动了若干个元素。结果迭代器或者指向容器内的一个元素,或者指示容器尾元素的下一位置。 |
iter1 += n | 迭代器加法的复合赋值语句,将iter1加n的结果赋给iter1 |
iter1 -= n | 迭代器减法的复合赋值语句,将iter2减n的加过赋给iter1 |
iter1 - iter2 | 两个迭代器相减的结果是它们之间的距离,也就是说,将运算符右侧的迭代器向前移动差值个元素后得到左侧的迭代器。参与运算的两个迭代器必须指向的是同一个容器中的元素或者尾元素的下一位置。 |
>、>=、<、<= | 迭代器的关系运算符,如果某迭代器指向的容器位置在另一个迭代器所指位置之前,则说前者小于后者,参与运算的两个迭代器必须指向的是一个同一个容器中的元素或者尾元素的下一个位置 |
数组
- 数组是一种复合类型。(相当于低级版的vector,长度固定)
- 初始化:type name[size];size必须是常量表达式。
- 数组不能赋值给另一个数组。
- 想要理解数组声明的含义,最好的方法就是从数组的名字开始按照由内向外的顺序阅读
数组和指针
- 在大多数表达式中,使用数组的类型的对象其实是一个指向该数组首元素的指针。
string nums[]={"one","two","three"};
string *p=&nums[0];
string *p2=nums//p2=&nums[0]
- 指针也是迭代器
- 数组的内置下标运算所使用的索引值不是无符号类型,这一点与vector和string不一样
int ia[]={0,2,4,6};
int *p=&ia[2];
int j=p[-2]//j=ia[0]
多维数组
- c++语言中没有多维数组,多维数组就是数组的数组
- 多维数组的初始化: int ia[3 ][4 ] = {{0,1,2,3},{1} ,{1}}
//使用范围for循环赋值和遍历输出
#include <iostream>
using namespace std;
int main() {
int num[3][4];
int n=0;
for(auto &row:num){
for(auto &col:row){
col=n;
n++;
}
}
for(auto &row:num){
for (auto col:row)
std::cout << col << std::endl;
}
return 0;
}
- ** 要使用范围语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型。**
参考资料
- c++ primer 第五版
- Github :https://github.com/applenob/Cpp_Primer_Practice/blob/master/notes/ch03.md