第五章:数组


数组是一组相同类型元素的集合

  • 数组中存放的是1个或者多个数据,但是数组元素个数不能为0
  • 数组中存放的多个数据,类型是相同的

1. 一维数组

1.1 一维数组的创建和初始化

  • 数组类型 数组名[数组大小]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

//第五章:数组
//数组创建和初始化

int main()
{
	//创建数组
	int arr1[5];//不初始化,存储的是随机值

	//初始化数组
	int arr2[5] = { 1,2,3,4,5 };//完全初始化:数组的元素个数和数组长度一致
	int arr3[10] = { 1,2,3,4,5 };//不完全初始化:数组的元素个数少于数组长度,则剩余的元素将会初始化为 0
	int arr4[] = { 1,2,3,4,5 }; //当不指定数组长度时,会根据初始化内容来确定数组长度

	//字符数组初始化
    //当字符数组不完全初始化时,剩余的元素初始化为 '\0'
	//字符数组可以直接使用字符串初始化
	char str1[10] = "hello";
	//也可以通过字符初始化
	char str2[10] = { 'h','e','l','l','o' };
	
	//当字符数组不指定长度时
    char str3[] = "hello";//此时会自动在末尾添加 '\0',所以 str4 的长度是 6
    char str4[] = { 'h','e','l','l','o' };//不会带\0,长度是5


	return 0;
}

数组在初始化时,如果是不完全初始化,剩余元素会根据数组类型进行初始化

1.2 数组的类型

在数组中,去掉变量名就是数组类型。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

//数组类型
//在数组中,去掉变量名就是数组类型 例如 int arr[10];数组类型是 int [10]

int main()
{
	int arr[10];

	//前文学习过 sizeof(),计算在内存中的字节长度。参数支持变量,表达式,和类型
	printf("%zd\n",sizeof (arr));//此时输出的是 40,因为 int arr[10],存放十个元素,每个元素都是四个字节
	printf("%zd\n",sizeof(int [10]));
 
 //所以我们可以利用 sizeof 来计算数组的长度
	int sz = sizeof(arr) / sizeof(arr[0]);//数组总共的长度 / 一个元素的长度
	printf("%d", sz);


	return;
}

1.3 一维数组的输入与输出

数组在内存中是连续存放的。数组的下标从 0 开始,最后一个元素的下标是 n-1,下标相当于数组元素的编号。通过下标引用操作符 [] 来访问数组的元素。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

//一维数组的使用
int main()
{
	//数组输入和输出
	char str1[11];
	//字符数组可以直接输入,不用通过下标。
	//在底层,输入的字符串(不能有空白字符)会被读取,根据顺序存放到对应的下标中
	//在此处也不需要元素地址值 & str[i]
	scanf("%10s", str1);

	//字符数组可以直接打印,printf 函数根据变量自动找到相对应的地址
	//字符数组在底层中直接存储的就是完整的字符串
	//而其他数组存储的是列表,所以需要 for 循环打印
	printf("%s\n", str1);

	//字符数组输入第二种写法测试
	char str2[10];
	//输入数据
	for (int i = 0; i < 9; i++) // 此时需要 < 9,只输入 9 个元素,最后一个留给 \0
	{
		scanf("%s", &str2[i]);
	}

	//输出数据

	printf("%s", str2);

	
	int arr[3];
	//输入数据
	for (int i = 0; i < 3; i++)
	{
		//将输入的元素,放在 arr[i] 中,数组本身就是地址
		//但是在此处不是数组, arr[i] 是元素,所以需要 &arr[i] 取元素的地址
		scanf("%d", &arr[i]);
	}

	for (int i = 0; i < 3; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

2. 二维数组

  • 数据类型 数组名 [一维数组个数][一维数组大小]

将一维数组做为元素的数组称为二维数组。二维数组中的每个元素在内存中也是连续存放的。

2.1 二维数组初始化

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

//二维数组初始化
int main()
{
	//定义数组两行三列,
  //建议 arr1[2][3] 理解为,此时二维数组存放两个一维数组,每个一维数组存放三个元素
  //因为在内存中,二维数组也是连续存放的,靠指针进行读取
	int arr1[2][3] = { 1,2 };//不完全初始化
	int arr2[2][3] = { 1,2,3,2,3,4 };//完全初始化
	int arr3[2][3] = { {1},{2,3} };//按行初始化,第一行读取1,第二行读取2和3

	//初始化可以省略行,不能省略列(根据元素个数来推断几行)
	int arr4[][3] = { 1,2 };//3列可以存储两个元素,所以只会有一行
	int arr5[][3] = { 1,2,3,4,5 };//两行
	int arr6[][3] = { {1},{2,3},{4,5} };//三行,此时将不会根据元素个数来推断行

	return 0;
}

2.2 二维数组输入与输出

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

//二维数组输入输出
int main()
{
	int arr[2][3];//定义数组
	
	//输入
	//第一层循环是遍历行
	//行数 = 二维数组的总大小 / 一行元素的大小 
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)// arr[0]代表一行的元素
	{
		//第二层循环是遍历列
		//列数 = 二维数组的总大小 / (一列元素的大小 (行数 * 二维数组的一个元素) )
		for (int j = 0; j < sizeof(arr) / ((sizeof(arr) / sizeof(arr[0]) * sizeof(arr[0][0]))); j++)
		{

			scanf("%d", &arr[i][j]);//此时 arr[i][j]是元素本身,不是地址,需要取地址
		}
	}

	//输出
	//第一层循环是遍历行
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)// 
	{
		//第二层循环是遍历列
		for (int j = 0; j < sizeof(arr) / ((sizeof(arr) / sizeof(arr[0]) * sizeof(arr[0][0]))); j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");//一行输出结束换行
	}

	return 0;
}

3. 数组练习

3.1 多个字符从两端移动,向中间汇聚

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <windows.h>

//数组练习
//多个字符从两端移动,向中间汇聚
int main()
{
	//定义字符数组
	char arr1[] = "welcome to bit!!!!!!";
	char arr2[] = "********************";

	int left = 0;//左指针

	//计算元素个数:sizeof(arr) / sizeof(arr[0]),但是字符数组末尾还有一个 \0
	//所以字符数组元素个数:sizeof(arr) / sizeof(arr[0]) -1
	//或者 strlen 统计字符串长度,忽略 \0
	int right = strlen(arr1) -1;//右指针


	while (left <= right)
	{
		//当两个指针指向的下标相等,赋值一个即可
		if (left == right)
		{
			arr2[left] = arr1[left];
		}

		//利用左指针替换arr2的内容
		arr2[left] = arr1[left];
		//利用右指针替换arr2的内容
		arr2[right] = arr1[right];

		left++;//移动左指针
		right--;//移动右指针

		system("cls");//清理屏幕
		Sleep(500);//打印完睡眠观察效果,单位一千毫秒
		printf("%s\n", arr2);
	}

	return 0;
}

3.2 二分查找

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdbool.h>

//二分查找(折半查找),每次处理一半的数据提高效率
//前提条件有序
int main()
{
	//定义数组
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10};
	//定义变量接受用户输入的值
	int num = 0;

	printf("请输入数字:");
	scanf("%d", &num);

	int left = 0;//左指针
	int right = sizeof(arr) / sizeof(arr[0]) - 1;//右指针
	int mid = 0;//中间变量下标,用于移动左指针或右指针

	bool flag = false;//定义变量用于判断是否找到

	while (left <= right)
	{
		//移动中间变量
		mid = (left + right) / 2;

		if (num == arr[mid])
		{
			printf("数字下标为:%d", mid);
			flag = true;
			break;
		}
		else if (num > arr[mid])
		{
			left = mid + 1;//左指针移动到中间变量后一位
		}
		else
		{
			right = mid - 1;//右指针移动到中间变量前一位
		}
	}

	if (!flag) //如果 flag 为假则没找到
	{
		printf("输入的数字不在数组内");
	}

	return 0;
}

第六章:函数

声明

本文是在鹏哥 C 语言集训营学习过程中所记录的学习笔记,梳理了核心知识点,同时也记录了本人实操验证的代码案例,供后续学习复盘使用。

更多推荐