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

张开发
2026/4/14 15:10:15 15 分钟阅读

分享文章

嵌入式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 n10; 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-143.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...};两个关键细节新手必避坑初始化时值的个数可以少于数组长度未赋值的元素会自动被初始化为0int数组、\0char数组如果数组完全不初始化每个元素的值都是随机值垃圾值后续使用会导致程序异常比如乱码、计算错误。示例对比理解// 示例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个整型数组成的数组值随机产生求出数组的最大值、最小值以及平均值。解题思路定义int数组长度100用srand()设置种子再用for循环给数组赋值随机数范围建议0~999避免数值过大遍历数组初始化最大值、最小值用数组第一个元素作为初始值累加所有元素求总和计算平均值注意用浮点型计算避免整数除法丢失精度打印结果。完整代码可直接复制运行#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 冒泡排序最易理解核心思想相邻元素两两比较如果不符合指定的大小关系比如从小到大就交换两个元素的位置经过一趟排序会将“最大或最小”的元素“冒”到无序序列的最后加入有序区。图解思路文字模拟黄色区域有序区已经排好序的元素蓝色区域无序区待排序的元素绿色元素正在比较的两个相邻元素。排序步骤以“从小到大”为例初始状态整个数组都是无序区蓝色有序区为空第一趟排序从无序区的第一个元素开始两两比较相邻元素大的元素往后移直到将最大的元素移到无序区的最后此时该元素加入有序区黄色第二趟排序对剩余的无序区重复上述操作将第二大的元素移到无序区最后加入有序区重复上述步骤直到无序区为空排序完成。代码实现从小到大排序#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从该位置开始到数组末尾找到最大或最小的元素如果该元素不在选择的位置就和该位置的元素交换将其加入有序区。排序步骤以“从小到大”为例初始状态有序区为空无序区为整个数组第一步选择位置0待插入有序区的第一个位置从位置0到末尾找到最小的元素和位置0的元素交换此时位置0加入有序区第二步选择位置1待插入有序区的第二个位置从位置1到末尾找到最小的元素和位置1的元素交换此时位置1加入有序区重复上述步骤直到选择到位置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开始依次选择每个元素作为“待插入元素”将其插入到前面已排好序的有序序列中插入时保持有序序列的顺序不变。关键细节选择待插入的元素后先用变量备份该元素此时该元素的位置会空出来供前面的有序元素向后移动找到合适的插入位置。排序步骤以“从小到大”为例初始状态下标0的元素作为初始有序区其余元素为无序区第一步选择下标1的元素作为待插入元素备份后将其与有序区的元素下标0比较若待插入元素小则将有序区元素后移插入待插入元素第二步选择下标2的元素作为待插入元素备份后从有序区的末尾开始比较比待插入元素大的元素依次后移找到合适位置插入重复上述步骤直到所有元素都插入到有序区排序完成。代码实现从小到大排序#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满足以下要求数组元素是26个英文字母中的某一个大小写都行将数组前10个元素从小到大排序后10个元素从大到小排序要求使用两种不同的排序算法。解题思路定义char数组长度20生成随机字母利用rand() % 26结合a小写或A大写比如a rand() % 26 生成小写字母拆分数组前10个元素用一种排序算法比如冒泡排序从小到大排序后10个元素用另一种排序算法比如选择排序从大到小排序打印排序前后的数组对比结果。完整代码可直接复制运行#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语言的基础也是后续学习链表、栈、队列等复杂数据结构的前提今天的内容总结如下新手必记数组是相同类型变量的集合下标从0开始最后一个元素下标是len-1数组定义时长度必须是常量初始化时未赋值元素默认为0int数组遍历、赋值数组的核心是for循环结合下标连续性操作3种基础排序冒泡易理解、选择效率高、直接插入贴近日常务必动手练熟生成随机数必须先设置种子srand(time(NULL))否则随机数序列固定。最后提醒数组操作最容易犯的错误是“下标越界”比如访问arr[10]但数组长度只有10最后一个元素是arr[9]一定要注意控制下标范围避免程序崩溃如果觉得这篇文章对你有帮助欢迎点赞、收藏、关注后续会持续更新C语言入门干货我们下期见

更多文章