C++学习笔记(四)--数组

前言

文中程序使用C11,使用codeite集成开发环境。

1.数组

定义:将一到多个相同类型的对象串连到一起,所组成的类型。数组可以类比数学中的矩阵。在C++中数组是一种类型
声明数组时,必须让编译器知道数组的大小,如:

int  a[10];                      //[]括号里的数要大于0,括号里可以填常量。这里a的类型是int[10]
int  b[] = {1, 2, 3};      //编译器可以自动推断出数组的大小

 cout << is_same< decltype(a), int[10]>::value << endl;    //结果是1

错误写法:

int b[];      //错误
int c[2]  = {1, 2, 3, 4};   //错误,初始化元素超过数组定义的大小

对于如下语句:

int b[5] = {1, 1, 3};    //b里包含的元素是1 1 3 0 0。系统会自动补全数组。

注:

  1. 不能使用 auto 来声明数组类型。
  2. 数组不能复制。
  3. 元素个数必须是一个常量表达式(编译期可计算的值)。
  4. 读取数组元素是不要超过数组的大小如:
int b[3] = {1, 2, 3};
std::cout << b[13]  << std::endl;   //这个虽然有输出,但这个值是不对的

1.1 数组的复杂声明

注意:数组不存在引用。
看如下程序

#include <iostream>
int main()
{
	int a[3]= {1,2,3};
	std::cout<< a <<' '<< &(a[0])<<' '<<std::begin(a)<<std::endl;
	std::cout<< a+3 <<' '<< &(a[3])<<' '<<std::end(a)<<std::endl;
}

输出结果:

0x7ffdfc342a7c 0x7ffdfc342a7c 0x7ffdfc342a7c
0x7ffdfc342a88 0x7ffdfc342a88 0x7ffdfc342a88
Hit any key to continue...

如上面的程序,数组在使用时通常会转换成相应的指针类型。再看下面的程序:

# include <iostream>
int main()
{
	int a[3]= {1,2,3};
	std::cout<< *(a+2) <<std::endl;  //a这里相当与一个指针,可以直接解引用
	std::cout<< a[2] <<std::endl;
}

输出:

3
3
Hit any key to continue...

1.2 数组与指针

1.2.1 数组到指针的隐式转换

使用数组对象时,通常情况下会产生数组到指针的隐式转换。隐式转换会丢失一部分类型信息,可以通过声明引用来避免隐式转换。
注:不要使用 extern 指针来声明数组。

1.2.2 相关的基本操作

  • 获得指向数组开头与结尾的指针 :
std::(c)begin, std::(c)end
  • 数组可以利用指针的相关算数使用,包括: 增加、减少,比较,求距离,解引用,指针索引。
#include <iostream>

int main()
{
	constexpr size_t num = 5;
	int a[num] = {1, 2, 3, 4, 5};
	
	int* ptr = a;
	int* ptr2 = a + 4;
	
	std::cout << *ptr << std::endl;      //a[0]
	std::cout << *ptr2 << std::endl;   //a[4]
}
  • 求元素的个数
    1.sizeof 方法
#include <iostream>
int main()
{
	int a[3];
	std::cout<< sizeof(a) <<std::endl; 
	std::cout<< sizeof(a)/sizeof(int) <<std::endl;  //最后的元素个数,输出3
}
  1. std::size 方法
    注:c17以上才有c.size()才有这样的方法,c是一个数组。
int a[3];
std::cout<< std::size(a) <<std::endl;   //这个输出12,其输出的是整个数组包含的字节数。使用cobra编译
  1. (c )end - (c )begin 方法
std::cout<< std::end(a) - std::begin(a)<<std::endl; //输出3
std::cout<< std::cend(a) - std::cbegin(a)<<std::endl; //输出3,cend可以理解为只读
  • 遍历数组
    方法一(使用while循环):
#include <iostream>
int main()
{
	int a[4] = {2, 3, 5, 7};
	auto ptr = std::cbegin(a);
	while(ptr != std::cend(a))
	{
		std::cout<< *ptr << std::endl;
		ptr = ptr +1;
	}
}

方法二(range-based for 循环):

#include <iostream>

int main()
{
	int a[4] = {2, 3, 5, 7};
	for(int x : a)    //这里可以遍历整个容器
	{
		std::cout<<x<<std::endl;
	}
}

1.2.3 字符串

对字符串的操作函数一般在cstring库里,如下面的程序。

#include <iostream>
#include <cstring>

int main()
{
	char str1[] = "hello";   //这个程序的末尾默认有结束符'\0'
	char str2[] = {'h','e','l','l','o'};   //这样写一些编译系统可以通过,但不要这个样写,如果这样定义须在末尾加'\0'。这样定义使用cstring的字符串处理函数输出的结果是不对的
	char str3[] = {'h','e','l','l','o', '\0'};
	char str4[] = "word";
	
	std::cout << strlen(str3) << std::endl;
	std::cout << strcmp(str1, str2) << std::endl;   //如果str1=str2就输出0,str1大于str2输出为正,str1小于str2输出为负。这里str1与str2不等价
	std::cout << strcmp(str1, str3) << std::endl;   //str1与str3等价
	std::cout << strcat(str1, str3) << std::endl;   //将str3拼接在srt1后
	std::cout << strcpy(str1, str4) << std::endl;  //用str4替换srt1
}

输出结果:

5
-119
0
hellohello
word
Hit any key to continue...

1.2.4 多维数组

本质:数组的数组,如

int a[3][4];   //大小为3的数组,每个元素包含4个元素。三行四列
  • 多维数组的初始化
//第一种方法
int a[3][4]  = { {1, 2, 3, 4},  {1, 2, 3, 4},  {1, 2, 3, 4}};   //这里不能使用()代替{}
//第二种方法
int a[3][4]  = { 1, 2, 3, 4,  1, 2, 3, 4,  1, 2, 3, 4};   //与第一种方法等价
//  第三种
int a[3][4]  = { {1},  {1},  {1}};      //这个相当于int a[3][4]  = { {1, 0, 0, 0},  {1, 0, 0, 0},  {1, 0, 0, 0}};
//第四种
int a[3][4]  = { 1, 2, 3};   //剩下的位置补0

遍历方法:

#include <iostream>
#include <cstring>   //include strlen
#include <type_traits>
int main()
{
	int x[3][4][5] = {1, 2, 3, 4, 5};
	for (auto& p : x)
	{
		for (auto &q : p)
		{
			for (auto r : q)
			{
				std::cout<< r << std::endl;
			}
		}
	}
}
#include <iostream>
#include <cstring>   //include strlen
#include <type_traits>
int main()
{
	int x[3][4] = {1, 2, 3, 4, 5};
	size_t index0 = 0;
	while (index0 < 3)
	{
		size_t index1 = 0;
		while (index1 < 4)
		{
			std::cout << x[index0][index1] <<std::endl;
			index1 = index1 + 1;
		}
		index0 = index0 + 1;
	}
}
  • 指针与多维数组
  1. 多维数组可以隐式转换为指针,但只有最高维会进行转换,其它维度的信息会被保留。
  2. 使用类型别名来简化多维数组指针的声明。
  3. 使用指针来遍历多维数组。

2. vector

vector是 C++ 标准库中定义的一个类模板,它也被称作容器。一般情况下程序中用vector代替数组的使用。与内建数组相比,更侧重于易用性,它可复制、可在运行期动态改变元素个数。vector类似与堆栈。

  • 定义与初始化
std::vector<std::vector<int>> x;   //基本的定义方式
std::vector<std::vector<int>>  x1(x2);     //x1包含x2的所有元素,xi与x2的类型要i一致
//等价于std::vector<std::vector<int>>  x1 =  x2;
std::vector<std::vector<int>>  x3(n, 1);     //x3包含n个1 
std::vector<std::vector<int>>  x4{1, 2, 3, 4};    //x4包含1 2 3 4
//等价于   std::vector<std::vector<int>>  x4 = {1, 2, 3, 4};  
  • 一些基本操作
std::vector<std::vector<int>> x; 
x.push_back(1);    //增加元素,向x末尾添加1
x.empty();   //判断x是否为空
x.size();  //返回x的大小
x.pop_back():   //删除x中最后一个元素
x.clear():   //清空x中所有元素

3.string

是 C++ 标准库中定义的一个类模板特化别名,用于内建字符串的代替品。与内建字符串相比,更侧重于易用性,其可复制、可在运行期动态改变字符个数。使用时需要添加string头文件。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值