news 2026/4/16 8:47:40

嵌入式Linux学习(day07)C语言(day04)【C语言入门】数组基础详解(含排序+实战练习,新手必看)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
嵌入式Linux学习(day07)C语言(day04)【C语言入门】数组基础详解(含排序+实战练习,新手必看)

数组是C语言入门的第一个“数据结构”,很多新手会觉得它简单,但其实里面藏着不少细节,比如初始化的坑、数组下标的注意事项,还有排序算法的应用,今天一次性讲透!

一、什么是数组?(新手必懂核心)

1.1 数组的本质

数组是数据结构的一种,也是最基础、最简单的数据结构,属于线性结构中的“顺序存储结构”。

简单来说:数组就是相同类型变量的集合——当我们需要使用多个同类型的变量时,不用一个个定义(比如int a1, a2, a3...),用一个数组就能统一管理,既简洁又高效。

1.2 为什么需要数组?(解决什么问题)

很多新手会问:一个变量直接用就好,为什么需要“结构”?

答案很简单:当我们需要处理一定量的同类型数据时,单个变量会显得非常繁琐。

比如:统计一个班级50个学生的成绩、存储100个随机数、处理一串字符,这时用数组就能批量管理这些数据,后续的遍历、修改、计算都会更方便。

二、数组的定义(语法+细节)

数组的定义有固定语法,核心是“指定类型、数组名、元素个数”,缺一不可,语法格式如下:

type name[nmemb];

拆解说明(新手必记):

  • type:数组中所有变量的统一类型(比如int、char、float),数组中不能混合不同类型的元素;

  • name:数组名,本质是一个标识符,遵循C语言命名规则(只能由字母、数字、下划线组成,不能以数字开头);

  • nmemb:数组的成员个数(即数组长度),必须是定长(C语言标准中,数组定义时长度不能是变量,必须是常量或常量表达式,比如int arr[10]合法,int arr[n](n是变量)不合法)。

易错点提醒:数组长度必须是常量,新手不要犯“int n=10; int arr[n]”的错误,这种写法在部分编译器(如Dev-C++)中可能通过,但不符合C语言标准,移植性极差!

三、数组的赋值与访问(核心操作)

3.1 数组元素的访问

数组中的每个元素都有一个唯一的“下标”(索引),通过“数组名[下标]”就能访问或修改对应元素,注意:

  • 数组下标从0开始,不是从1开始;

  • 第一个元素:name[0](下标0);

  • 第二个元素:name[1](下标1);

  • 最后一个元素:name[nmemb - 1](下标 = 数组长度 - 1)。

示例(直观理解):

int arr[5]; // 定义一个长度为5的int数组 arr[0] = 10; // 给第一个元素赋值10 arr[1] = 20; // 给第二个元素赋值20 arr[4] = 50; // 给最后一个元素赋值50(下标5-1=4)

3.2 批量赋值(利用循环遍历)

数组下标是从0到nmemb-1的连续整数,因此我们可以用for循环遍历所有下标,批量访问或赋值数组元素,这是数组最常用的操作之一。

语法模板(记熟!):

for (int i = 0; i < nmemb; i++) { // i从0开始,小于数组长度 name[i] = 赋值内容; // 批量赋值 // 或者 printf("%d", name[i]); // 批量访问 }

四、数组的初始化(避坑重点)

数组定义后,如果不初始化,元素的值是随机的(垃圾值),因此建议养成“定义即初始化”的习惯,初始化语法如下:

type name[nmemb] = {val1, val2, val3...};

两个关键细节(新手必避坑):

  1. 初始化时,值的个数可以少于数组长度:未赋值的元素会自动被初始化为0(int数组)、'\0'(char数组);

  2. 如果数组完全不初始化,每个元素的值都是随机值(垃圾值),后续使用会导致程序异常(比如乱码、计算错误)。

示例(对比理解):

// 示例1:完全初始化 int arr1[3] = {1, 2, 3}; // arr1[0]=1, arr1[1]=2, arr1[2]=3 // 示例2:部分初始化(未赋值元素为0) int arr2[3] = {1}; // arr2[0]=1, arr2[1]=0, arr2[2]=0 // 示例3:不初始化(元素为随机值,不推荐) int arr3[3]; // arr3[0]、arr3[1]、arr3[2]的值随机

五、数组的遍历(必练操作)

数组遍历就是“依次访问数组中的每一个元素”,核心还是利用for循环,结合数组下标的连续性,实现批量访问。

核心逻辑:用循环变量i从0遍历到nmemb-1,通过name[i]访问每个元素。

示例(遍历int数组,打印所有元素):

#include <stdio.h> int main() { int arr[5] = {10, 20, 30, 40, 50}; int len = 5; // 数组长度,建议用变量存储,方便后续修改 // 遍历数组,打印所有元素 for (int i = 0; i < len; i++) { printf("arr[%d] = %d\n", i, arr[i]); } return 0; }

运行结果:

arr[0] = 10 arr[1] = 20 arr[2] = 30 arr[3] = 40 arr[4] = 50

六、随机数生成(数组实战基础)

很多数组练习需要用到随机数(比如生成随机数组),C语言中生成随机数需要借助两个头文件和两个函数,记熟下面的模板即可直接使用。

6.1 必备头文件

#include <time.h> // 提供时间相关函数,用于设置随机数种子 #include <stdlib.h> // 提供rand()和srand()函数

6.2 核心函数说明

  • srand(time(NULL));:设置随机数种子,作用是让每次运行程序生成的随机数都不同(如果不设置种子,每次生成的随机数序列都是一样的);

  • rand();:生成随机数,默认范围是0~65535(无符号短整型的范围)。

技巧:如果想生成指定范围的随机数,比如0~99,可以用 rand() % 100;生成1~100,可以用 rand() % 100 + 1,以此类推。

示例(生成1个随机数):

#include <stdio.h> #include <time.h> #include <stdlib.h> int main() { srand(time(NULL)); // 设置随机数种子(必须放在rand()前面) int num = rand(); // 生成随机数 printf("随机数:%d\n", num); return 0; }

七、实战练习1:生成随机数组,求最值和平均值

题目要求:定义一个由100个整型数组成的数组,值随机产生,求出数组的最大值、最小值以及平均值。

解题思路:

  1. 定义int数组,长度100;

  2. 用srand()设置种子,再用for循环给数组赋值(随机数范围建议0~999,避免数值过大);

  3. 遍历数组,初始化最大值、最小值(用数组第一个元素作为初始值),累加所有元素求总和;

  4. 计算平均值(注意用浮点型计算,避免整数除法丢失精度);

  5. 打印结果。

完整代码(可直接复制运行):

#include <stdio.h> #include <time.h> #include <stdlib.h> int main() { // 1. 定义数组(长度100) int arr[100]; int len = 100; int max, min, sum = 0; double avg; // 平均值用double,避免精度丢失 // 2. 设置随机数种子,给数组赋值(0~999的随机数) srand(time(NULL)); for (int i = 0; i < len; i++) { arr[i] = rand() % 1000; // 生成0~999的随机数 sum += arr[i]; // 累加求和 } // 3. 求最大值和最小值(初始化用数组第一个元素) max = arr[0]; min = arr[0]; for (int i = 1; i < len; i++) { if (arr[i] > max) { max = arr[i]; // 更新最大值 } if (arr[i] < min) { min = arr[i]; // 更新最小值 } } // 4. 计算平均值 avg = (double)sum / len; // 强制转换为double,避免整数除法 // 5. 打印结果 printf("数组的最大值:%d\n", max); printf("数组的最小值:%d\n", min); printf("数组的总和:%d\n", sum); printf("数组的平均值:%.2f\n", avg); // 保留2位小数,更美观 return 0; }

运行说明:每次运行程序,数组中的随机数都会不同,最值和平均值也会随之变化,符合题目要求。

八、数组排序(3种基础排序算法,新手必练)

排序是数组最核心的应用之一,新手入门必掌握3种基础排序:冒泡排序、选择排序、直接插入排序,下面详细讲解每种排序的原理、步骤和代码实现,结合图解思路(文字模拟图解),一看就懂。

8.1 冒泡排序(最易理解)

核心思想:相邻元素两两比较,如果不符合指定的大小关系(比如从小到大),就交换两个元素的位置;经过一趟排序,会将“最大(或最小)”的元素“冒”到无序序列的最后,加入有序区。

图解思路(文字模拟):

  • 黄色区域:有序区(已经排好序的元素);

  • 蓝色区域:无序区(待排序的元素);

  • 绿色元素:正在比较的两个相邻元素。

排序步骤(以“从小到大”为例):

  1. 初始状态:整个数组都是无序区(蓝色),有序区为空;

  2. 第一趟排序:从无序区的第一个元素开始,两两比较相邻元素,大的元素往后移,直到将最大的元素移到无序区的最后,此时该元素加入有序区(黄色);

  3. 第二趟排序:对剩余的无序区重复上述操作,将第二大的元素移到无序区最后,加入有序区;

  4. 重复上述步骤,直到无序区为空,排序完成。

代码实现(从小到大排序):

#include <stdio.h> // 冒泡排序函数(arr:待排序数组,len:数组长度) void bubbleSort(int arr[], int len) { // 外层循环:控制排序趟数(n个元素,需要n-1趟) for (int i = 0; i < len - 1; i++) { // 内层循环:控制每趟比较的次数(每趟少比较1次,因为最后一个元素已排好) for (int j = 0; j < len - 1 - i; j++) { // 相邻元素比较,大的往后移(从小到大) if (arr[j] > arr[j + 1]) { // 交换两个元素 int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } // 打印数组函数(方便查看排序结果) void printArr(int arr[], int len) { for (int i = 0; i < len; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int arr[] = {5, 2, 9, 1, 5, 6}; int len = sizeof(arr) / sizeof(arr[0]); // 计算数组长度(通用写法) printf("排序前:"); printArr(arr, len); bubbleSort(arr, len); // 调用冒泡排序 printf("排序后:"); printArr(arr, len); return 0; }

8.2 选择排序(效率略高于冒泡)

核心思想:依次选择待插入有序区的位置(从0到n-2),从该位置开始到数组末尾,找到最大(或最小)的元素;如果该元素不在选择的位置,就和该位置的元素交换,将其加入有序区。

排序步骤(以“从小到大”为例):

  1. 初始状态:有序区为空,无序区为整个数组;

  2. 第一步:选择位置0(待插入有序区的第一个位置),从位置0到末尾,找到最小的元素,和位置0的元素交换,此时位置0加入有序区;

  3. 第二步:选择位置1(待插入有序区的第二个位置),从位置1到末尾,找到最小的元素,和位置1的元素交换,此时位置1加入有序区;

  4. 重复上述步骤,直到选择到位置n-2(最后一个待插入位置),排序完成。

代码实现(从小到大排序):

#include <stdio.h> // 选择排序函数 void selectSort(int arr[], int len) { // 外层循环:控制待插入有序区的位置(0~n-2) for (int i = 0; i < len - 1; i++) { int minIndex = i; // 假设当前位置的元素是最小值,记录其下标 // 内层循环:从当前位置到末尾,找到真正的最小值下标 for (int j = i + 1; j < len; j++) { if (arr[j] < arr[minIndex]) { minIndex = j; // 更新最小值下标 } } // 如果最小值不在当前位置,交换元素 if (minIndex != i) { int temp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = temp; } } } // 打印数组 void printArr(int arr[], int len) { for (int i = 0; i < len; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int arr[] = {5, 2, 9, 1, 5, 6}; int len = sizeof(arr) / sizeof(arr[0]); printf("排序前:"); printArr(arr, len); selectSort(arr, len); // 调用选择排序 printf("排序后:"); printArr(arr, len); return 0; }

8.3 直接插入排序(贴近日常思维)

核心思想:从数组的第二个元素(下标1)开始,依次选择每个元素作为“待插入元素”,将其插入到前面已排好序的有序序列中,插入时保持有序序列的顺序不变。

关键细节:选择待插入的元素后,先用变量备份该元素,此时该元素的位置会空出来,供前面的有序元素向后移动(找到合适的插入位置)。

排序步骤(以“从小到大”为例):

  1. 初始状态:下标0的元素作为初始有序区,其余元素为无序区;

  2. 第一步:选择下标1的元素作为待插入元素,备份后,将其与有序区的元素(下标0)比较,若待插入元素小,则将有序区元素后移,插入待插入元素;

  3. 第二步:选择下标2的元素作为待插入元素,备份后,从有序区的末尾开始比较,比待插入元素大的元素依次后移,找到合适位置插入;

  4. 重复上述步骤,直到所有元素都插入到有序区,排序完成。

代码实现(从小到大排序):

#include <stdio.h> // 直接插入排序函数 void insertSort(int arr[], int len) { // 外层循环:控制待插入元素(从下标1开始,到len-1结束) for (int i = 1; i < len; i++) { int temp = arr[i]; // 备份待插入元素 int j = i - 1; // 有序区的最后一个元素下标 // 内层循环:找到待插入位置,有序区元素向后移动 while (j >= 0 && arr[j] > temp) { arr[j + 1] = arr[j]; // 元素后移 j--; // 向前移动,继续比较 } arr[j + 1] = temp; // 插入待插入元素 } } // 打印数组 void printArr(int arr[], int len) { for (int i = 0; i < len; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int arr[] = {5, 2, 9, 1, 5, 6}; int len = sizeof(arr) / sizeof(arr[0]); printf("排序前:"); printArr(arr, len); insertSort(arr, len); // 调用直接插入排序 printf("排序后:"); printArr(arr, len); return 0; }

九、实战练习2:随机字符数组排序(综合应用)

题目要求:随机产生26个字母组成的字符数组,数组长度是20,满足以下要求:

  1. 数组元素是26个英文字母中的某一个(大小写都行);

  2. 将数组前10个元素从小到大排序,后10个元素从大到小排序;

  3. 要求使用两种不同的排序算法。

解题思路:

  1. 定义char数组,长度20;

  2. 生成随机字母:利用rand() % 26,结合'a'(小写)或'A'(大写),比如'a' + rand() % 26 生成小写字母;

  3. 拆分数组:前10个元素用一种排序算法(比如冒泡排序)从小到大排序;

  4. 后10个元素用另一种排序算法(比如选择排序)从大到小排序;

  5. 打印排序前后的数组,对比结果。

完整代码(可直接复制运行):

#include <stdio.h> #include <time.h> #include <stdlib.h> // 1. 冒泡排序(从小到大,用于前10个元素) void bubbleSortAsc(char arr[], int start, int end) { // start:排序起始下标,end:排序结束下标(含) int len = end - start + 1; for (int i = 0; i < len - 1; i++) { for (int j = start; j < end - i; j++) { if (arr[j] > arr[j + 1]) { char temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } // 2. 选择排序(从大到小,用于后10个元素) void selectSortDesc(char arr[], int start, int end) { int len = end - start + 1; for (int i = start; i < end; i++) { int maxIndex = i; for (int j = i + 1; j <= end; j++) { if (arr[j] > arr[maxIndex]) { maxIndex = j; } } if (maxIndex != i) { char temp = arr[i]; arr[i] = arr[maxIndex]; arr[maxIndex] = temp; } } } // 打印数组 void printArr(char arr[], int len) { for (int i = 0; i < len; i++) { printf("%c ", arr[i]); } printf("\n"); } int main() { char str[20]; // 定义长度为20的字符数组 int len = 20; // 1. 生成随机字母(小写字母,可改为'A'生成大写) srand(time(NULL)); for (int i = 0; i < len; i++) { str[i] = 'a' + rand() % 26; // 'a'~'z'的随机字母 } printf("排序前的数组:"); printArr(str, len); // 2. 前10个元素(下标0~9):冒泡排序,从小到大 bubbleSortAsc(str, 0, 9); // 3. 后10个元素(下标10~19):选择排序,从大到小 selectSortDesc(str, 10, 19); printf("排序后的数组:"); printArr(str, len); return 0; }

代码说明:

  • 生成大写字母:将代码中的'a'改为'A'即可;

  • 排序算法替换:可将冒泡排序换成直接插入排序,选择排序换成冒泡排序,满足“两种排序算法”的要求;

  • 排序范围:通过start和end参数控制排序的区间,前10个(0~9)、后10个(10~19),逻辑清晰。

十、总结与注意事项

数组是C语言的基础,也是后续学习链表、栈、队列等复杂数据结构的前提,今天的内容总结如下,新手必记:

  1. 数组是相同类型变量的集合,下标从0开始,最后一个元素下标是len-1;

  2. 数组定义时长度必须是常量,初始化时未赋值元素默认为0(int数组);

  3. 遍历、赋值数组的核心是for循环,结合下标连续性操作;

  4. 3种基础排序:冒泡(易理解)、选择(效率高)、直接插入(贴近日常),务必动手练熟;

  5. 生成随机数必须先设置种子(srand(time(NULL))),否则随机数序列固定。

最后提醒:数组操作最容易犯的错误是“下标越界”(比如访问arr[10],但数组长度只有10,最后一个元素是arr[9]),一定要注意控制下标范围,避免程序崩溃!

如果觉得这篇文章对你有帮助,欢迎点赞、收藏、关注,后续会持续更新C语言入门干货,我们下期见~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 15:21:24

树莓派4B性能调优实战:从散热到显存的全面优化指南

1. 树莓派4B性能调优的必要性 树莓派4B作为一款性价比极高的单板计算机&#xff0c;广泛应用于开发学习、媒体中心、智能家居等领域。但受限于硬件规格&#xff0c;在运行视频播放、深度学习等高性能需求场景时&#xff0c;常会遇到卡顿、发热等问题。我自己用树莓派4B搭建家庭…

作者头像 李华
网站建设 2026/4/15 16:45:00

一站式歌词解决方案:免费获取网易云QQ音乐歌词与格式转换

一站式歌词解决方案&#xff1a;免费获取网易云QQ音乐歌词与格式转换 【免费下载链接】163MusicLyrics 云音乐歌词获取处理工具【网易云、QQ音乐】 项目地址: https://gitcode.com/GitHub_Trending/16/163MusicLyrics 还在为本地音乐库缺少歌词而烦恼&#xff1f;或者需…

作者头像 李华
网站建设 2026/4/14 15:08:44

3步掌握专业歌词制作:开源LRC工具完全实战指南

3步掌握专业歌词制作&#xff1a;开源LRC工具完全实战指南 【免费下载链接】lrc-maker 歌词滚动姬&#xff5c;可能是你所能见到的最好用的歌词制作工具 项目地址: https://gitcode.com/gh_mirrors/lr/lrc-maker 你是否曾为制作精准的歌词同步而烦恼&#xff1f;当音乐响…

作者头像 李华
网站建设 2026/4/14 15:08:21

大一新生手搓STM32寻迹小车:从零到跑通,我的HAL库踩坑与填坑实录

大一新生手搓STM32寻迹小车&#xff1a;从零到跑通&#xff0c;我的HAL库踩坑与填坑实录 第一次点亮STM32开发板时&#xff0c;LED微弱的光芒让我兴奋得像个发现新大陆的孩子。作为刚接触嵌入式开发的菜鸟&#xff0c;我从未想过三个月后自己能独立完成一辆寻迹小车的制作。这段…

作者头像 李华
网站建设 2026/4/15 17:29:08

从俾斯麦海之战到现代商业:如何用博弈论中的纳什均衡做决策?

从俾斯麦海之战到现代商业&#xff1a;博弈论中的纳什均衡如何重塑决策逻辑 1943年的俾斯麦海战役中&#xff0c;日本海军将领木村昌福面临一个经典的战略困境&#xff1a;是选择北线还是南线运送补给&#xff1f;盟军指挥官肯尼同样需要预测对手的路线以部署空军。这场战役的决…

作者头像 李华
网站建设 2026/4/14 15:05:55

免费在线PPT制作工具终极指南:5分钟创建专业演示文稿

免费在线PPT制作工具终极指南&#xff1a;5分钟创建专业演示文稿 【免费下载链接】PPTist PowerPoint-ist&#xff08;/pauəpɔintist/&#xff09;, An online presentation application that replicates most of the commonly used features of MS PowerPoint, allowing for…

作者头像 李华