C/C++学习
第三章:特殊变量
0.前导
学习路径:头文件与命名空间------字符串string------向量vector------迭代器------数组
1.头文件与命名空间:
头文件:声明已经定义的变量或函数的文件。 在主文件与源文件中头文件都会被导入,为了确保头文件被多次包含仍能安全工作,使用头文件保护符: ifndef:如果未定义,为真;ifdef:如果定义为真;endif:执行到此为止;define:定义
arduino
#ifndef WAI_BU_H //第一次包含头文件时,未定义,ifndef为真,执行
#define WAI_BU_H //定义,下一次包含头文件时不执行
声明
#endif //执行停止点
命名空间:当使用标准库时需要使用命名空间,如:
c
std::cin //使用命名空间std中的cin
简化使用:
c
using std::cin
cin >> i; //提前声明,可以直接使用
std::cout<< i;
c
using namespace std //声明整个命名空间,可以使用直接全部
cin>>i;
cout<<i;
命名空间与头文件:头文件中一般不使用using声明
2.字符串string:
导入:
string数据类型属于标准库中定义的类也就是自定义数据类型,需要导入。
c
#include <string> //导入对应头文件
using std::string //string属于std命名空间
定义对象:
c
string s1 ; //默认初始化
string s1 = s2; //赋值初始化
string s1(s2); //直接初始化
string s1(c,"10"); //直接初始化,类似于python中类的初始化,传入参数
string s1 = "dwaf" //赋值初始化,可以接受字符串字面值
string s1 = 'a'; //错误,不能将字符作为string的初始化值,但可以在初始化后使用字符进行赋值
操作:
整体操作: 输入输出: 使用cin与cout读取string时,遇到string中的空格或换行符时会停止输入输出。注意输入输出符号的连锁性。
c
cin>>word;
cout<<word; //如果输入 dawf d只会输出dawf
cin>>word1>>word2;
cout<<word1<<word2; //word1输出dawf word输出d
使用getline读取string时,遇到string中的空格则不会停止输入输出,换行符还是会。
scss
getline(cin,line) //getline会读取换行符,但将输入赋值给line时会去掉换行符
cout<<line //如果输入dwaf d 会全部输出
empty与size操作:
empty:判断string对象是否为空:
ini
string s1 = "dawf";
auto flag = s1.empty();
cout<<flag;
size:返回string对象的长度:返回的数据类型是string::size_type
ini
string s1 = "wafda";
string:size_type len = s1.size();
cout<<len;
比较: 使用运算符对string对象进行比较(逐一比较string中的字符,对大小写敏感)。
=:当俩个string对象每个字符都相当且长度相等时,相等。
!=:当每个字符都相等时比较俩个string的长度;当字符不相等时比较俩个string第一对相异的字符的ascii大小
ini
string s1 = "hello";
string s2 = "hello,world";
string s3 = "hekkk";
//s1与s2比较长度;s3与 s1和s2比较第一对相异字符的ascii大小(k与l比)
相加:
对象相加:俩个string对象相加就是将+右侧对象追加到左侧对象后面形成新的string对象
字符串字面值与对象相加:不允许俩个字符串字面值相加
ini
string s1 , s2;
string s3 = s1 + s2; //ture
string s4 = s1 + "wdadf"; //true
string s5 = "wfeg" + "fegr"; //flase
string s6 = "wae" + s1 + "wadfgh"; //true
string s7 = "efgrh" + "feg" + s1; //false
内容操作:
范围for循环:可以遍历甚至改变整个string对象中的字符:
c
string s1 = "dwafewg";
for (auto &c : s1) //通过c可以遍历并且修改整个s1
{
```
}
普通for循环:
ini
for(i = 0;i<s1.size();i++) //初始化即i=0不重复执行,后面的语句重复执行每次执行都读取新的v3对象,因此在循环体中最好不执行向vector对象添加对象的操作
{
s1 = s1 + "r";
cout<<s1[i]<<endl;
}
下标运算符:使用[ ]接受string::size_type参数,可以访问string对象中特定位置的字符
ini
string s1 = "rwqfew";
string::size_type n = 2;
string s2;
s2 = s1[n];
s2 = s1[2]; //下标实际数据类型为size_type,但可以直接传入整形数字
3.向量vector:
向量vector表示的是对象的集合,它是模板,使用时需要确定数据类型。
导入:
vector属于标准库,需要导入
arduino
#include <vector>
using std::vector
定义对象:
向量中的元素不是引用而是对象,向量本身可以引用。
arduino
vector<int> i1; //默认初始化
//拷贝初始化
vector<int> i2 = i1;
vector<int> i3 = {1,2,3};
vector<int> i7 = {a,b,c}; //a,b,c都是变量.只是获取对应变量中的值
//值初始化
vector<int> i4(4);
vector<int> i5(4,5);
vector<int> i6(i4);
//列表初始化
vector<int> i7{3,4,5,6}
vector<string> i8{5,"daewf"} //使用列表初始化时,如果列表中的值无法初始化,编译器会默认初始化对象
操作:
整体操作: 同string类似
内容操作: 添加元素:一般初始化vector对象时使用默认初始化
ini
vector<string> s1 ;
string s2 = "fewf";
s1.push_back(s2); //在尾部添加数据
范围for循环:可以循环遍历并修改vector对象
c
for (auto &c : v3) //在范围循环中,只读取一次v3对象,不会随着循环中的v3的增大而增大
{
v3.push_back(c);
cout << c << endl;
}
普通for循环:
ini
for(i = 0;i<v3.size();i++) //for语句头中初始化语句不重复执行,后俩个语句每次重复执行都读取新的v3对象,因此在循环体中不能执行向vector对象添加对象的操作
{
v3.push_back(1);
cout<<v3[i]<<endl;
}
下标运算符:[ ]接受类型为vector< 具体类型> :: size_type 的参数,可以访问vector中特定的对象
ini
vector<int> v1 = {2,5,7,3};
vector<int>:: size_type n = 2;
cout<< v1[n] <<endl;
cout<<v1[n] <<endl;
4.迭代器
只有部分容器拥有下标运算符,而每个标准库的容器都有迭代器。迭代器与指针类似指向容器中的某个对象,但不支持取址符的使用。
arduino
vector<int> v = {1,3,5,3,7,8};
vector<int>::iterator it = &v; //错误
定义:
每个容器都有迭代器,因此在定义是需要确定具体的容器数据类型。并且迭代器还有常量类型const_iterator,使用该类型的迭代器与常量指针类似只可读不能修改指向对象的值即常量
arduino
vector<int>::iterator it1 ;
string:: iterator it2 ;
vector<int>::const_iterator it1 ;
string:: const_iterator s3;
操作:
begin与end迭代器:使用容器中的成员返回容器的迭代器
begin():使用begin方法的返回作为初始化,it1指向begin方法中的迭代器指向的对象(s1的第一个值)
end():使用end方法的返回作为初始化,end返回的是s2最后一个对象的下一个对象(不存在,仅作为标记)
ini
string s1 = "daf";
auto it1 = s1.begin();
auto it2 = s1.end();
运算符: 适用于所有容器的迭代器,大多数容器的迭代器没定义比较运算符。
ini
string s1 = "daf";
auto it1 = s1.begin();
*s1 = 'f'; //解引用,操作指向对象的值
++s1; //使迭代器指向下一个对象
!= //对比俩个迭代器,如果俩个迭代器属于同一个容器且指向同一对象才相等
it2->empty() | (*it2).empty()
//等价,都是访问指向的对象中的成员
循环: 使用迭代器的循环,不要向迭代器所属的容器添加对象。
特定运算: string与vector有更多的运算符
ini
string s1 = "daf";
auto it1 = s1.begin();
auto it2 = s1.end();
it1 += n; //表示指向移动n个对象后指向的对象
it2 = it1 + n; //同上
auto distance = it1 - it2; //表示俩个所指对象相距多少个对象,必须在同一个容器中,没有加法
< > <= >= //比较同一个容器中所指对象位置的先后
这里的运算符产生的距离的具体数据类型是 difference_type的带符号整型
5.数组
数组是内置数据类型,也是容器。同样数组中的元素是对象不是引用,数组本身可以引用。
定义对象:
ini
//默认初始化
unsigned int n = 5;
constexpr unsigned int m = 5;
int j = 5;
int arr[5];
int arr[n];
int arr[m]; //使用变量初始化数组大小时,要注意变量是无符号的常量表达式
//拷贝初始化
int arr1[1] = {2,5};
int arr2[] = arr1; //不能使用拷贝初始化数组,因为数组名代表的是数组首元素的指针
arr2 = arr1 //赋值也同样不行
//列表初始化
int arr1[] = {2,4,5,7};
int arr2[4] = {2,6,3,2};
//字符串字面值初始化字符数组
char arr1[] = "waf"; //字符串字面值的最后一个空字符 \n 也会被传入
char arr[3] = "wrf" //错误,字符数组大小不够大
//复合类型数组,指针的结合会影响复合类型的变量
int *arr1[5]; //指针数组 这个变量中的对象是指针
int *(&arr2)[5] = arr1; //为数组中的对象指针起别名
int (*arr3)[5]; //数组指针 这个变量是数组类型的指针
int (*&arr4)[5] = arr3; //为这个变量起别名
int &arr5[5] ; //错误,不能引用数组
操作:
内容操作:
循环:遍历数组,同string与vector的介绍相同
下标符:访问数组中的特定对象,同string与cector介绍相同
迭代器:
指针:指针可以指向数组中的对象
ini
int arr1[5] = {2,4,5,6};
int *it1 = arr1; //指针指向数组的首个对象
int *it2 = &arr1[0] //与上句效果相同
decltype(arr1) arr2 = {2,3,5}; //使用decltype的数组名返回的是数组的数据类型
当指针指向数组中的对象时,该指针即可当作迭代器,迭代器能使用的操作指针都可以使用。其中数组不是类没有成员函数,使用标准库函数begin(),与end()代替迭代器中的方法。
scss
int arr1[5] = {2,4,7,3};
auto it1 = arr1; //相当于首部迭代器
auto it2 = &arr1[6] //相当于尾部迭代器(不可递增,解引用)
auto it3 = begin(arr1); //相当于首部迭代器
auto it4 = end(arr1); //相当于尾部迭代器(不可递增,解引用)
运算符:与迭代器操作相同,当指针是空指针或指向不是容器的指针,这些操作都可以使用但会出现奇怪现象。 指针相减获得的距离的数据类型是ptrdiff_t
c
int arr1[5] = {2,4,7,3};
int *it1 = arr1;
cout<<*it1 + 4; //输出数组首个对象的值+4
cout<<*(it1+4) //输出数组移动4个对象的对象
下标与指针:对指针只有下标符相当于对指针解引用。当指针指向数组后,再使用指针下标则以指针当前的位置为0移动
ini
int arr1[5] = {2,4,7,3};
int *it1 = arr1;
cout<< it[2]; //相当于 *(it+2)
int *it2 = &arr1[1];
cout<< it[1] ; //相当于 *(it+1)
int *it3 = &arr1[4];
cout<< it[-1]; //相当于 *(it-1)
字符数组字符串:
c语言定义以下函数:传入的都是字符数组,c语言没有string类型。并且使用这些函数时,传入的字符数组最后一个字符对象必须是空字符 \0
scss
strlen(c) //计算长度,不算空字符
strcmp(c1,c2) //比较是否相等
strcat(c1,c2) //追加
strcpy(c1,c2) //复制c2到c1中
string与字符数组的互相初始化:
ini
char str1[] = {'r','r','y','\0'};
string str2 = str1;
string str3 = str1 + str2;
const char *str4 = str2.c_str(); //该函数返回的是const char *类型