数组:
概念:具有一定顺序的若干变量的集合
定义:存储类型 数据类型 数组名字[元素个数];
例:int arr[7];// 定义一个存放7个数据的整型数组
数组名 arr:代表的是数组的首地址,是一个常量,不能赋值(不能为左值)
数组中每一个数据称为元素 每个元素都是一个变量
赋值:
- 全部初始化:
int arr[3]={1,2,3};//表示定义三个字符的arr数组并赋值1,2,3
- 部分赋值:(没有被赋值的地方值为0)
int arr[3]={1,2};//表示定义三个字符的arr数组并赋值1,2,0
int arr[3]={1,2};//表示定义三个字符的arr数组并赋值1,0,0
- 未初始化 (数组中元素为随机值)
int arr[3];//表示定义三个字符的arr数组不赋值
后期在赋值时要用下标(0--数组长度-1)
语法:数组名[下标]=值;
例:arr[0]=2; //给arr数组第一个值赋值为2,其余位置仍为随机值
- 定义空数组://数组元素全为0
int arr[3]={0,0,0};
int arr[3]={0};
int arr[3]={};
访问:
语法:数组名[下标];
例:int arr[3]={1,2,3};
访问第一个元素:arr[0]
访问最后一个元素:arr[2]
越界:
访问时下标超过数组范围,访问下标最大值等于数组长度-1
例:
int arr[3]={1,2,3};
访问arr[3]; //数组越界!!!
注意:
- 一个数组内数据类型要相同
- 内存是连续的
例:int型数组 每个字符占4个字节
3.数组名是首地址,定义数组时名称符合标识符的命名规范
4.同一个函数中,数组名不能和变量重名
int a[3];
int a=10; 错误
5.数组的下标是从0开始,到n-1结束 注意数组越界
数组分类:
一维数组 二维数组
一维数组:
只有一个下标
引用:
- 先定义后引用
- 每次引用元素时只能引用一个 a[0]√ a[0,1,2]× 如果想要所有元素需要遍历
- 防止数组越界!!
- 引用数组地址,打印格式使用%p
- 内存分配
int arr[4];
数组的遍历
int arr[3];
arr[0] arr[1] arr[2]
for循环完成
#include <stdio.h>
#include <unistd.h>
int main()
{
int arr[5];
for (int i = 0; i < 5; i++)
{
scanf("%d", &arr[i]);//输入遍历
}
for (int i = 0; i < 5; i++)
{
printf("%d ", arr[i]); // 输出遍历
}
return 0;
}
数组大小:
方法:
1.sizeof
2.数组中元素个数*数据类型大小
元素个数:
int arr[5];
- 直接观察
- sizeof(arr)/sizeof(int) //sizeof(数组名)/sizeof(数据类型)
注意:数组名后面的[]可以不写个数,不写的话必须赋值
清零函数
对数组进行清零:
- bzero
#include <strings.h>
void bzero(void *s, size_t n);
功能:将内存空间中的数据设置为0
参数:参数1:要清空的空间首地址
参数2:字节大小
返回值:无
例:
#include <stdio.h>
#include <strings.h>
int main()
{
int arr[15] = {1, 1, 12, 24, 6, 8, 3467, 0}; // 开辟5个元素的空间
bzero(arr, sizeof(arr));
for (int i = 0; i < 15; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
- memset
#include <string.h>
void *memset(void *s, int c, size_t n);
功能:将内存空间中的数据设置为0
参数:参数1:要清空的空间首地址
参数2:要设置的值 设置为0或-1 //因为此函数针对char类型数据进行设置只修改1字节所以其他整型值无法实现。
参数3:字节大小
返回值:要清空的空间首地址
字符数组
概念:数组中保存的都是字符型数据
形式:
1.逐个字符赋值:
char str[]={'a','b','c'};//定义了一个char类型的数组开辟三个字节空间
- 赋值字符串
char str[7]={"hello"};//开辟了7个字节的空间,赋值5个字符,但作为字符串系统会自动添加‘\0',实际存放6个字符
char str[]="hello";//开辟了6个字符的空间
注意!:定义字符数组时往往不填写元素个数,小心越界问题
字符数组的遍历:
1.for循环遍历
2.printf scanf %s
3. 函数:gets (使用时会报警告,因为此函数不关系数组越界问题,所以用时要自己注意 不要担心)
输入字符串
char *gets(char *s);
功能:从终端输入一个字符串
参数:字符数组的首地址(要保存数据的位置)
返回值:字符数组的首地址
puts
int puts(const char *s);
功能:向终端输出字符串
参数:要输出的字符串的首地址
返回值:输出的字符的个数
计算字符数组实际长度:(不包含\0)
1.for 循环
2.strlen
#include <string.h>
size_t strlen(const char *s);
功能:计算字符数组实际长度(不包含\0)
参数:字符串的首地址
返回值:计算字符数组实际长度(字符的个数)
sizeof 和 strlen的区别:
- 功能不同:sizeof:计算字节大小 strlen:字符串的实际长度
- sizeof:关键字 strlen:函数
- sizeof:计算结果包含‘\0’,strlen不包含‘\0’
当定义时,[]中不写元素个数时,用sizeof会比strlen多一个
数组的排序:
int a[5]={5,4,3,2,1};
冒泡排序:
思想:数组中相邻两个数进行比较(两两比较)前者比后者大,交换位置
特点:
1.第一轮结束后,最大值在最后面
int j=0第一轮: int i=0 比较了4次 5-1-j
5和4进行比较:5>4--->4 5 3 2 1
5和3进行比较:5>3--->4 3 5 2 1
5和2进行比较:5>2--->4 3 2 5 1
5和1进行比较:5>1--->4 3 2 1 5
int j=1第二轮: 比较了3次 5-1-j
4和3进行比较:4>3--->3 4 2 1 5
4和2进行比较:4>2--->3 2 4 1 5
4和1进行比较:4>1--->3 2 1 4 5
int j=2第三轮: 比较了2次 5-1-j
3和2进行比较:3>2--->2 3 1 4 5
3和1进行比较:3>1--->2 1 3 4 5
int j=3第四轮: 比较了1次 5-4=5-1-j
2和1进行比较:2>1--->1 2 3 4 5
#include <stdio.h>
int main()
{
int a[5] = {5, 4, 3, 2, 1};
int temp;
/
for (int j = 0; j <5-1; j++)
{
for (int i = 0; i < 5-1-j; i++)
{
if (a[i] > a[i + 1])
{
temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
}
}
for (int i = 0; i < 5; i++)
printf("%d ",a[i]);
return 0;
}
选择排序:
int a[5]={5,4,3,2,1}; // 2 3 1 4 5
思想:在数组中找最小值,标记最小值的下标,和第一个数进行交换,最小值在最前面
#include <stdio.h>
int main()
{
int a[5] = {0, 4, 3, 2, 1}; // 1 4 3 2 5
int temp;
int k; // 用于标记最小值下标
for (int i = 0; i < 5-1; i++)
{
k = i; // 0 k=1 k=2 3
for (int j = i + 1; j < 5; j++)
{
if (a[k] > a[j])
{
k = j;
}
}
if (k != i)
{
temp = a[k];
a[k] = a[i]; // a[1] 2
a[i] = temp; // a[1] 2
}
}
for (int i = 0; i < 5; i++)
printf("%d ", a[i]);
return 0;
}
排序过程:
(1)首先通过n-1次比较,从n个数中找出最小的, 将它与第一个数交换—第一趟
选择排序,结果最小的数被安置在第一个元素位置上
(2)再通过n-2次比较,从剩余的n-1个数中找出关键字次小的记录,将它与第二
个数交换—第二趟选择排序
(3)重复上述过程,共经过n-1趟排序后,排序结束
例:int a[5]={5,4,3,2,1};
首先定义一个k用来保存最小值的下标
第一轮:
将0赋值给k,判断5>4-------> 将1赋值给k;
判断4>3-------> 将2赋值给k;
判断3>2-------> 将3赋值给k;
判断2>1-------> 将4赋值给k;
将a[0]的值与a[k]的值进行交换得到:1,4,3,2,5
第二轮:
将1赋值给k,判断4>3-------> 将2赋值给k;
判断3>2-------> 将3赋值给k;
判断5>2-------> k不变;
将a[1]的值与a[k]的值进行交换得到:1,2,3,4,5
第三轮:
将2赋值给k,判断4>3-------> k不变;
判断5>3-------> k不变;
k值保持不变,故第三轮不做交换得:1,2,3,4,5
第四轮:
将3赋值给k,判断5>4-------> k不变;
k值保持不变,故第三轮不做交换得:1,2,3,4,5
二维数组
有两个[]
格式:存储类型 数据类型 数组名{行数}{列数};
int arr[2][3];//定义了一个两行三列的数组
访问元素:数组名[行下标][列下标];
arr[0][0]:访问第一行第一列下标
行下标和列下标都是从0开始
访问第2行第3个元素:arr[行数-1][列数-1]
数组的元素的个数:行数*列数
数组的大小:sizeof 大小=行数*列数*数据类型的大小
数组名:arr:数组第一行的首地址 arr+1:数组第二行的首地址
arr[0]:第一行第一列的地址
初始化:
- 全部初始化
int arr[2][3]={1,2,3,4,5,6};//按照顺序赋值
int arr[2][3]={{1,2,3},{4,5,6}}; //按行赋值
- 部分初始化
int arr[2][3]={1,2};//按照顺序赋值 1,2,0,0,0,0
int arr[2][3]={{1},{4,5}}; //按行赋值1,0,0,4,5,0
- 不初始化
int arr[2][3];//值是随机值,后续需要赋值只能按下标一个一个赋值
注意:
- 定义二维数组,可以省略行数但是不能省略列数
int a[][3]={1,2,3,4,5,6};//两三列的数组
int a[2][3]错误
- 内存分配
int a[2][3];
获取第一行第二个元素地址:&a[0][1]
- 注意数组越界(行下标和列下标都不能越界)
遍历
双重for循环
……未完待续