【跟学C++】C++数组与字符串(Study8)


 ============================ 【说明】 ===================================================
  大家好,本专栏主要是跟学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,45};

学习注意:此时,我们定义的一般是静态数组,长度是固定的,后面会谈及到动态数组及其优势。

(2) 多维数组
  顾名思义,多维数组一般是大于等于二维的都成为多维数组,例如书架有3排,每排书架可以存放5本书,我们可以定义这个二维数组:

int Num[3][5];

  我们可以对这二维数组进行初始化,**可以理解为:**编号分别为0,1,2的三排书,15本书名称分别为1-15:

int Num[3][5]={{1,23,4,5},{6,7,8,9,10},{11,12,13,14,15}};

  当然也可以这样定义,更加推荐第一种编程习惯

int Num[3][5]={1,23,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

  动态数组另一种方法dequevector类似,都是支持在增加和删除元素但是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菌】,个人已关注,并订阅了相关专栏(对我有帮助的),希望大家觉得不错的可以点赞、关注、收藏

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cqy阳

预祝上岸,感谢打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值