文章目录
============================ 【说明】 ===================================================
大家好,本专栏主要是跟学C++内容,自己学习了这位博主【 AI菌】的【C++21天养成计划】,讲的十分清晰,适合小白,希望给这位博主多点关注、收藏、点赞。
主要针对所学内容,通过自己的理解进行整理,希望大家积极交流、探讨,多给意见。后面也会给大家更新,其他一些知识。若有侵权,联系删除!共同维护网络知识权利!
=======================================================================================
1、数组
1.1、概念
学过数据结构的应该知道,对于数组的定义是这样的:数组是一系列具有相同类型的数据元素构成的有限序列。在C++中,数组按照顺序将一系列相同类型的数据存储到内存中。因此,数组又具有(1) 是一系列元素;(2) 所有元素类型相同 ;(3)这些元素组成一个完整集合等特点。
1.2、存储方式
那么,数组在C++中如何去存储?存储方式又是什么呢?我们可以用一个生活中常见的案例。
其实,图书馆对图书的存放方式和数组存储方式很相似。书架上一排书等同于一维数组。同样,整个书架有类似于二维数组(图书包括横向与纵向),对于一个图书室又像是一个三维数组,而整个图书馆又像是四维数组,以此类推。
而数组的存储大小有类似于书架存放书本数量。有所不同的是,数组中,每个元素占的空间大小是相同的。(原因:数组中所有元素的类型都相同。)
1.3、数组定义与初始化
(1) 一维数组
对于一维数组而言,我们定义数组的格式如下:
type ArrayName[length];
//type:表示数据类型,如int等。
//ArrayName:数组名称
//length:数组长度,即严肃个数
示例:
//定义一个名为Num、长度为6的整型数组
int Num[6];
定义完数组后,我们可以对数组进行初始化:
int Num[6]={1,2,3,4,5};
学习注意:此时,我们定义的一般是静态数组,长度是固定的,后面会谈及到动态数组及其优势。
(2) 多维数组
顾名思义,多维数组一般是大于等于二维的都成为多维数组,例如书架有3排,每排书架可以存放5本书,我们可以定义这个二维数组:
int Num[3][5];
我们可以对这二维数组进行初始化,**可以理解为:**编号分别为0,1,2的三排书,15本书名称分别为1-15:
int Num[3][5]={{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};
当然也可以这样定义,更加推荐第一种编程习惯:
int Num[3][5]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
1.4、访问数组
如何去访问数组,其实很简单,利用索引的方式,习惯从0开始计算,0即代表第一个元素,以此类推。
我们在访问数组时,不能超越其边界,否则结果是无法预料。在很多情况下,这将导致程序崩溃。比如你可以在只包含5个元素的数组中取回索引为10的元素,但这样会给程序带来安全和稳定性方面的风险。
我们通过两个案例分别展示如何访问一维数组和二维数组(多维数组以此类推):
(1) 一维数组
#include<iostream>
using namespace std;
//一维数组
int main() {
int Num[5] = { 1,2,3,4,5 };
for (int i = 0; i < sizeof(Num)/sizeof(Num[0]) ; i++)
{
cout << Num[i] << endl;
}
return 0;
}
(2) 二维数组
#include<iostream>
using namespace std;
//二维数组
int main() {
int Num1[3][5] = {{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
cout << Num1[i][j]<<' ';
}
cout << endl;
}
return 0;
}
1.5、动态数组–vector
前面所述的一维数组和多维数组都是静态数组。在数组声明或定义时,数组的长度(元素的个数)都是固定好的,后期是无法修改的。
但是,在实际应用过程中,我们的数组长度都不一定知道其上限,设置过小,容量不够,溢出;设置过大,降低了系统的性能。
为了减少内存,充分利用数组,可以不再使用静态数组,可以使用动态数组,依据具体需求来调整数组大小。
在C++中,提供了vector
动态数组类,我们来详细学习这个数组。
(1) vector特点
动态数组不仅节省存储内存,还能使程序更加灵活,vector数组具有如下几个特点:
1) 在数组尾部添加或删除元素的吧时间是固定的;
2) 在数组中间添加或删除元素与该元素后面的元素个数成正比。
3) 存储的元素是动态的,vector
负责管理内存。
(2) 初始化vector
vector
有多种初始化方法:注: vector <类型> array,类型不仅是int,也可以是float类等。
1)初始化一个动态数组array1:
vector <int> array1;
2)初始化一个动态数组array2,初始长度(元素个数)为10:
vector <int> array2(10);
3)初始化一个动态数组array3,长度(元素个数)为10,且元素均为1:
vector <int> array3(10,1);
4)初始化一个动态数组array4,将数组array3复制到array4:
vector <int> array4(array3);
5)利用迭代器,将数组array4的前3个元素复制到数组array5,并打印出。
vector <int> array5(array4.begin(),array4.begin()+3);
for(int i;i<array5.size();i++){
cout<<array5[i]<<' ';
}
(3) vector常用的操作函数
1)push_back()
在数组array1尾部增加一个元素10:
array1.push_back(10);
2)insert()
push_back()
是在数组末尾增加元素,若在数组中间插入元素,则可以用insert()
函数。
int main() {
//定义一个动态数组array1,长度为5,元素均为10
//定义一个动态数组array2,长度为2,元素均为66
vector <int> array1(5, 10);
vector <int> array2(2, 66);
//显示array1内容
cout << "array1初始内容为:" << endl;
for (int i = 0; i < array1.size(); i++)
{
cout << array1[i] << ' ';
}
cout << endl;
cout << "==========";
cout << endl;
//在数组array1前插入元素15
array1.insert(array1.begin(), 15);
//显示array1内容
cout << "插入15后,array1为:" << endl;
for (int i = 0; i < array1.size(); i++)
{
cout << array1[i] << ' ';
}
cout << endl;
cout << "==========";
cout << endl;
//在数组array1尾部插入2个30
array1.insert(array1.end(), 2, 30);
//显示array1内容
cout << "插入2个30后,array1为:" << endl;
for (int i = 0; i < array1.size(); i++)
{
cout << array1[i] << ' ';
}
cout << endl;
cout << "==========";
cout << endl;
//将数组array2插入到数组array1第一个元素之后
array1.insert(array1.begin() + 1, array2.begin(), array2.end());
//此时显示array1数组内容
cout << "最终array1为:" << endl;
for (int i = 0; i < array1.size(); i++)
{
cout << array1[i] << ' ';
}
cout << endl;
cout << "==========" ;
}
3)pop_back()
前面讲了push_back()
是在数组后面增加元素,二这边的pop_back()
则相反,在数组末尾删除一个元素,而且删除时间也是固定的。
array1.pop_back();
(4) 访问vector数组元素
前面在访问一维数组时,利用索引方式,其实动态数组也是可以的。对于vector
而言,还有其他比较常见的几种方法:
1)常见的索引方式
vector <int> array1(5,10); //初始化数组5个元素都是10
//1.用下标运算符[]以数组方式访问
for(int i=0;i<array1.size();i++)
cout<<array1[i]<<" ";
cout<<endl;
2)成员函数at
vector <int> array1(5,10); //初始化数组5个元素都是10
//1.用下标运算符[]以数组方式访问
for(int i=0;i<array1.size();i++)
cout<<dyarr1.at(i)<<" ";
cout<<endl;
3)迭代器(类似指针)
vector <int>::iterator Locator=array1.begin();
while(Locator!=array1.end())
{
cout<<*Locator<<" ";
++Locator;
}
1.6、动态数组–deque
动态数组另一种方法deque
和vector
类似,都是支持在增加和删除元素。但是,vector
仅支持结尾插入和删除,而deque
在开头和结尾都支持。
需要加入头文件#include <deque>
(1)在结尾插入删除元素
deque <int> array1(5,10); //初始化数组5个元素都是10
array1.push_back(100);
array1.pop_back();
(2)在开头插入删除元素
array1.push_front(100);//在数组开头插入100
array1.pop_front();//删除数组开头的元素
2、字符串
2.1、C语言字符串
C++中的字符串起源于C语言,算是一种特殊的字符数组。字符串也就是以‘\0’
为终止符的字符数组。
不管是哪种语言,我们都学过字符串,在C语言中,我定义一个最熟悉的字符串:
char Hello[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '\0'};
需要注意的是,这个数组的最后一个字符为\0'
,称为字符串结束字符。目的是告诉编译器字符串到此结束。这种C风格字符串是特殊的字符数组,因为总是在最后一个字符后加上空字符\0'
。
如果没有加上终止符,打印数组时会出现一些多余字符。
#include<iostream>
using namespace std;
int main()
{
char SayHello[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '\0'};
cout<<"加空字符输出:"<<SayHello<<endl;
char SayHello1[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'};
cout<<"不加空字符输出:"<<SayHello1<<endl;
char SayHello2[] = "Hello World";
//C++在初始化数组时,自动把'\0'放在字符串末尾。
cout<<"字符串形式输出:"<<SayHello2;
return 0;
}
2.2、常用字符串函数
C++中cstring类中提供了很多实用的字符串函数(头文件为:#include <cstring>
):
strcpy(s1,s2)
:复制字符串s2到字符串s1;
strcat(s1,s2)
:连接字符串s2到字符串s1末尾;
strlen(s1)
:返回字符串s1长度;
strcmp(s1,s2)
:比较s1和s2,若s1=s2,返回0;若s1>s2,返回1;若s1<s2,返回-1;
strchr(s1,ch)
:返回一个指针,指向字符串s1中字符ch第一次出现的位置;
strstr(s1,s2)
:返回一个指针,指向字符串s1中字符s2第一次出现的位置;
对上面的函数,进行简单示例:
(1) strcpy()
这里注意实际代码中为strcpy_c()
,原因可以看这个strcpy_c()。
int main() {
char str1[] = { 'H','E','L','L','O',' ','\0' };
char str2[] = { 'W','O','R','L','D','\0' };
char str3[10];
strcpy_s(str3, str1);
cout << "str1复制到str3:" << str3;
return 0;
}
(2) strcat()
、strlen()
,这里注意实际代码中为strcat_s()
,原因可以看这个strcat_s()。
int main() {
char str1[20] = { 'H','E','L','L','O',' ','\0' };
char str2[] = { 'W','O','R','L','D','\0' };
strcat_s(str1, str2);
cout << "连接后:" << str1;
cout << "长度为:" << strlen(str1);
return 0;
}
(3) strcmp()
int main() {
char str1[] = { 'H','E','L','L','O',' ','\0' };
char str2[] = { 'W','O','R','L','D','\0' };
cout<<strcmp(str1, str2);
return 0;
}
(4) strchr()
、strstr()
int main() {
char str1[] = "HELLO";
char str2[] = "WIRLD";
char str3[] = "R";
cout << strchr(str1, 'L')<<endl;
cout << strstr(str2, str3) << endl;
return 0;
}
注意:C风格字符串作为输入的函数非常危险,因为它们会寻找终止空字符10’,如果程序员没有在字符数组末尾添加空字符,这些函数将跨越字符数组边界。
2.2、C++字符串–String类
C++为了解决上述问题,提供了string类,这种方式是安全且强大的操作。这里对于C++的String类,会通过另一篇博客进行解释,敬请等待!
更新:【跟学C++】C++的String类用法详解【番外1】
3、总结
最后,长话短说,大家看完就好好动手实践一下,切记不能三分钟热度、三天打鱼,两天晒网。大家也可以自己尝试写写博客,来记录大家平时学习的进度,可以和网上众多学者一起交流、探讨,我也会及时更新,来督促自己学习进度。一开始提及的博主【AI菌】,个人已关注,并订阅了相关专栏(对我有帮助的),希望大家觉得不错的可以点赞、关注、收藏