⚔️1.3 数组
🗡1.3.1 一维数组
数组就是把相同数据类型组合在一起而产生的数据集合。 数组就是从某个地址开始的连续若干位置行程的元素集合。
数据类型 数组名[数组大小]
常见的一维数组举例:
int a[10]; double db[233]; char str[1000000]; bool HashTable[10000000];
访问元素的方法数组名称[下标]
定义了长度为size的数组之后,只能访问下标为0~(size-1)的元素!!
数组的初始赋值
int a[10] = {1, 2 ,3 };
可以只给出部分元素,后面的部分元素会置为0。
如果希望初始化所有元素为0可以int a[10] = {0};或者int a[10] = {};
需要注意的点:
1.括号的意思是取元素a[2]和*(a+2)的作用是等价的。(知道你们看不懂,指针学了回来看0.0)
2.数组首地址是个常量也就是a是个常量 不可更改!!
一个栗子🌰结束吧
#include<stdio.h> int main(){ int a[10]; scanf("%d", & a[0]); for(int i = 1; i < 10; ++i) a[i] = a[i - 1] * 2; for(int i = 1; i < 10; ++i) printf("a[%d] = %d\n",i , a[i]); return 0; }
读入第一个元素 然后从前往后顺推每一个元素的值为前一个两倍,输出就好了。
🛡1.3.2冒泡排序
排序:将一个无序序列按照某种规则进行有序排列
冒泡排序是基于交换的排序方式,是其中最简单的一种排序方式。
首先介绍一下交换的实现方式
int temp = a; a = b; b = temp;
上面这样就完成了两个元素的交换。
冒泡排序的思想是从前往后扫描变量,如果前面的元素比后面的元素大就交换元素,否则不动。
这就像冒泡一样,每次都将最大的元素放在最后面,完成n-1轮就完成了对整个数组的排序。看下图
具体实现代码:
#include<stdio.h> int main(){ int a[10] = { 3, 1, 4, 5, 2}; for(int i = 0; i <= 4; ++i){ //进行n-1躺排序 for(int j = 0; j < 5 - i; ++j){ bool flag = true; if(a[j] > a[j + 1]){ //判断是否交换 int temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; flag = false; } if(flag) break; //没有交换可以直接返回 } } for(int i = 0; i < 5; i++) printf("%d ", a[i]); return 0; }
注意:冒泡排序可以根据交换与否提前跳出,如果基本有序执行很快。
🔧1.3.3 二维数组
二维数组其实是一维数组的延伸和扩展
基本结构:数据类型 数组名[第一维大小][第二维大小]
对数据的访问类似于一维数组:数组名 [下标1][下标2]
二维数组的存储结构如图所示:
特别注意序号是从0开始的,并且达不到size!!!!
初始化的方式:
int a[5][5] = {{1 ,2 , 3, 4, 5}, {1 ,2 , 3, 4, 5}, {1 ,2 , 3, 4, 5}, {1 ,2 , 3, 4, 5}};
人类的本质就是套娃,多维数组也是一样0.0
举个栗子🌰
#include<stdio.h> int a[10000][10000]; int main(){ for(int i = 0;i < 10000;i++) for(int j = 0;j < 10000;j++) scanf("%d",&a[i][j]); for(int i = 0;i < 10000;i++) for(int j = 0;j < 10000;j++) printf("%d\n",a[i][j]); return 0; }
结果就是读入一堆数字然后再把它打印出来。
特别注意,上面的🌰中将数组定义在函数外其实是定义在了堆内存上,放置栈溢出。(又突然听不懂了是不是?没关系,记住数组大于106就定义在函数体外就好了,剩余的回头再学)
⚒1.3.4memset函数
如果需要对一个数组中每个元素进行赋值,可以使用memset函数;
基本格式:memset(数组名, 值, sizeof(数组名));
其中sizeof返回的事对应的数组的大小。单位是字节。
注意:
1.此函数只适用于赋全0或者全1(即0或者-1),因为传入参数字节,这个函数按照字节赋值的,如果int是长度是4,赋值2就会出问题!!!!
2.使用此函数务必包含string.h函数!!!
举个栗子
#include<cstdio> #include<cstring>//cpp里cstring 和 string.h一样 int main(){ int a[5] = { 1, 2, 3, 4, 5}; memset(a, 0, sizeof(a)); for(int i = 0; i < 5; i++) printf("%d ", a[i]); printf("\n"); memset(a, -1, sizeof(a)); for(int i = 0; i < 5; i++) printf("%d ", a[i]); printf("\n"); return 0; }
🔨1.3.5 字符数组
其实字符本质上也是数字0.0,你说你不信?我给你康康!
看法很简单就是从上到下依次增加,一共127个数字。对应1比特的6个1,也就是char的正数部分。
没事可以翻回来看看这个表,需要记住的昨天说了,就是小写比大写大32。
1.字符数组的初始化
字符数组的初始化有两种方式:
char s[6] = {'a', 'e', 'i', 'o', 'u'}; char s[6] = "aeiou";
其中第二种方式只用于初始化,在程序执行过程中如果这么干会直接报错!!
注意字符串末尾有一个'\0‘作为结束标志,所以开数组要大一个位置!
2.字符数组的输入输出
scanf和printf这个昨天说过了,今天不提了 主要就是利用%s
但是注意scanf读取字符串是以空格和回车作为结束的,这两个元素不可能读入到字符串内
getchar 和 putchar昨天也说过了。这里需要注意的是:
getchar不会给字符串加结束符,需要手动加,并且getchar能读到回车
gets()和puts()
gets用于读入一整行的数据。但是这个在C11中弃用了。。。因为安全问题
有些OJ还能使用,用法就是gets(s)。
需要注意的是:
scanf读入数据后会把相应的结束标志留在标准输入输出上,所以使用gets之前如果使用了scanf需要用一个getchar吸收掉回车!!!
puts()相比较而言就简单很多。
作用就是把字符串打印到屏幕上并加上一个换行符。
一个常用的方式是puts("")可以打印一个换行,是不是很方便?
gets_s()
因为刚才说到的原因gets弃用了。。。多说个函数就是gets_s
用法gets_s(str,strlen);
参数就多了一个就是strlen ,这个函数读到长度后就不会再读,防止读爆字符串产生安全问题0.0
但是ges_s()这个东西在c++里没有 所以我们要引入另外一个神器
cin.getline(str,strlen);,用法和gets_s一样 但是别忘了 #include<iostream>和using namespace std;
🔩1.3.6 string.h头文件
之前介绍了memset,我们再来扒一扒这个头文件有什么好用的函数。
最后的sscanf和sprintf是不是有亿点点熟悉?其实我们平常用到的scanf和printf都是这两个的变体!!
知识点到这里就结束了,大家要好好做题巩固呀,有什么问题大家评论区见0.0
让我们相约明天
🐳课后习题
今天的题目难度也不高,就是有点多,我写完会放题解,大家写完了可以在评论区打卡哟!我觉得,题解我放评论区吧,这样不用修改文章。
题解:评论区见,置顶没有就是我没写完0.0,大佬们刷完打个卡呀