数组
1.数组概念:具有一定顺序关系的变量的集合
2.定义格式:存储类型 数据类型 数组名[元素个数]
(可以不填) int a[5];
数组名(上面的a):表示数组的首地址,是一个地址常量,不能被赋值
访问方式/引用方式:数组名[下标],下标从0开始,到n-1
注意:不要数组越界!!!!!
关于数组越界:数组越界后,会自动接着前面那块内存往后写,这样带来的将会是一系列安全问题。因为界外的内存不确定是否已经存放了东西,如果不凑巧存放着比较重要的数据,那么数组越界后将会把这块内存上的重要数据替换掉,后果可想而知。
3.特点:
1)数据元素类型相同,数组类型和数组类型也相同
2)内存连续,地址位置相差一个数据类型字节数,例如:char是1个字节,那么在地址上它 们相差8位
注意:
- 数组名符合标识符命名规则
- 在同一个函数中,数组名不能和变量名相同
- [N(为要设置的元素个数)]下标从0~n-1
一维数组
1.定义格式:存储类型 数据类型 数组名[元素个数]
int a[5];
2.数组名:表示数组的首地址,地址常量,不能被赋值
3.访问方式:数组名【下标】,下标从0开始,到n-1
重要的事情说三遍:注意:不要数组越界!!!!
4.初始化
1)全部初始化
int a[5]={1,2,3,4,5};//a[0]=1;a[1]=2;...a[4]=5;
2)部分初始化 未初始化的部分值为0
int a[5]={1,2,3};// 1 2 3 0 0
3)未初始化 值为随机值,需要单独赋值
先定义:int a[5];
部分赋值 : a[0]=1; a[2]=3;
未赋值部分还是随机值
4)定义一个空数组(两种方式)
a)int a[5]={0,0,0,0,0};
b)int a[5]={0};
c)int a[5]={};
5.如何引用(int a[i])
1)先定义后引用
2)每次只能引用一个数组元素a[i],如果想要引用所有元素要遍历循环
3)引用数组元素防止数组越界
4)打印数组元素地址用%p
6.一维数组内存分配
特点:内存连续,地址相差n个字节数(具体和数据类型有关)
1.在程序中如何使用数组?
使用数组遍历
逻辑:使用for循环实现循环访问数组,从而实现将数组全部输入或者是输出,把下标作为循 环变量,用for循环实现
1)遍历输出:
for(i=0;i<n;i++)
printf("%d\n",a[i]);
2)遍历输入:
for(i=0;i<n;i++)
scanf("%d",&a[i]);
2.如何计算数组大小?
sizeof(数组名)
例如:printf("%d\n",sizeof(a));
数组大小=数据类型*元素个数 //元素个数指的是你要设置这个元素组存储多少元素
例如:
int a[5];//20
double b[2]={1.36};//16
char c[3]={};//3
字符数组
- 定义字符数组的三种形式:
1)char a[]={'a','b','c'};//逐个字符赋值,sizeof(a)=3
2)char a[]={"hello"};//字符串赋值,sizeof(a)=6
3)char a[]="hello";//字符串赋值,sizeof(a)=6
注意:字符串赋值一般省略元素个数,因为要注意数组越界问题!!!
2.字符数组输入输出
char buf[32]={};
输入:
1.用scanf直接输入字符串
1.scanf("%s",buf);//输入字符串不能有空格,否则会认为字符串输入结束
2. scanf("%[^\n]",buf);//这个格式可以输入空格,直到遇到\n才会结束
2.用遍历循环输入字符
for(i=0;i<n;i++)
scanf("%c",&buf[i]);
3.gets
char *gets(char *s);
功能:从终端获取一个字符串
参数:s:目标数组的首地址
返回值:同参数
不过不建议使用,因为不会检查数组越界!!
输出:
1.按格式输出
printf("%s\n",buf);
2.用遍历循环输出
for(i=0;i<n;i++)
printf("%c",buf[i]);
3.puts直接输出字符串
int puts(const char *s);
功能:向终端输出一个字符串
参数:s:目标字符串的首地址
返回值:输出字符的个数
扩充:一般使用字符数组时可能会涉及字符长度问题,下面介绍两种求字符长度的方式
计算字符串的实际长度:
1.for循环遍历到\0
for (n = 0; buf[n] != '\0'; n++); //n实际长度
思路:作为字符串,最后都会有\0,所以我们可以用遍历循环检测字符数组最后一 位'\0'的位置,这样我们在用最后一个a[i]-1就可以得到字符长度。
2.strlen
#include <string.h>
size_t strlen(const char *s);
功能:计算字符串的实际长度,不包括\0
参数:s:要计算的字符串的首地址
返回值:字符串的实际长度
例:
char buf[32]="hello";
int len = strlen(buf);//5
思路:strlen作为函数,可以直接计算字符串长度(不包括'\0'),所以用int len去接受 strlen(buf)计算字符长度的返回值
所以sizeof和strlen的区别?
- sizeof是关键字;strlen是函数
- sizeof是用来计算数据所占空间大小;strlen用来计算字符串的实际长度
- sizeof是包括\0的;strlen不包括\0。当省略字符数3组长度时,sizeof比strlen大1
同时在数组中会遇到有两个很经典点的用法:冒泡排序和选择排序:
冒泡排序:
思路:相邻两个数两两比较,如果前面数大就交换
排序算法:
for(i=0;i<n-1;i++)//比较的轮数
for(j=0;j<n-1-i;j++)//每轮比较的次数
if(buf[j] > buf[j+1])//如果前面数大就交换
{
t = buf[j];
buf[j] = buf[j+1];
buf[j+1]=t;
}
选择排序:
思路:
1)通过n-1次的比较找出最小值,将它放在第一个数的位置
2)通过n-2次的比较找出剩下数种的最小值,放在第二个位置上
3)重复上述过程,重复n-1轮,排序结束
for(i=0;i<N-1;i++)//轮数
{
k=i;
for(j=i+1;j<n;j++)//比较的次数
if(buf[j] < buf[k])//找最小值
k=j;
if(i != k)//需不需要交换
{
t= buf[i];
buf[i]=buf[k];
buf[k]=t;
}
}
二维数组
int arr[2][3]
访问二维数组元素:数组名[行下标][列下标] 下标从0开始一直到行数-1,列数-1;
注意:行列下标都不要越界,行下标可以省略,列下标不能省略!
2.二维数组的元素个数:行数*列数
3.数组名的表示:arr:表示二维数组第一行的首地址,arr+1:第二行的首地址
4.二维数组初始化
1)全部初始化
int arr[2][3]={1,2,3,4,5,6};// 1 2 3 4 5 6
int arr[2][3]={{1,2,3},{4,5,6}};
2)部分初始化 // 未赋初值元素为0
int arr[2][3]={1,2,3,4};// 1 2 3 4 0 0
int arr[2][3]={{1,2},{4,5}};//1 2 0 4 5 0
3)未初始化 // 未赋初值元素为随机值,需要单独赋值
int arr[2][3];
arr[1][0]=5;
5.关于二维数组的内存分配
a[0]:第一行第一列的地址 a:第一行首地址
a[1]:第二行第一列的地址 a+1:第二行首地址
总的来说先存储完第一行后再接着存储第二行的数组
5.二维数组计算大小
sizeof(数组名)
数据类型大小*行数*列数
6.遍历数组,用于输入输出二维数组
for循环嵌套,外层循环行,内存循环列
for(i=0;i<行数;i++)
for(j=0;j<列数;j++)
scanf("%d",&a[i][j]);//printf("%d ",a[i][j]);