C语言基础03——数组——习题
一、数组基础题
1.定义一个数组:55,66,77,88,99.找出其中的最大值。
#include <stdio.h>int main() {//定义数组并初始化int arr[] = { 55,66,77,88,99 };//定义一个变量max,用于记录最大值(其初始值一定要是数组中的元素)int max = arr[0];//获取数组长度int len = sizeof(arr) / sizeof(int);for (int i = 0; i < len; i++){if (arr[i] > max) {max = arr[i];}}printf("%d", max);
}
2.生成10个1~100之间的随机数存入数组,
并 : 1.求数组中所有数据之和;2.求数组中所有数据的平均值;3.统计有多少个数字比平均数要小
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
int main() {//生成10个1~100之间的随机数存入数组int arr[10] = { 0 };int len = sizeof(arr) / sizeof(int);int sum = 0;srand(time(NULL));for (int i = 0; i < len; i++){int num = rand() % 100 + 1;arr[i] = num;}//求出所有数据的和for (int i = 0; i < len; i++){printf("%d\n", arr[i]);sum = sum + arr[i];}//求平均值int avg = sum / len;//统计有多少个数字比平均数要小int count = 0;for (int i = 0; i < len; i++){if (arr[i] < avg){count++;}}printf("----------\n");printf("该数组数据之和为%d\n", sum);printf("该数组数据平均值为%d\n", avg);printf("该数组数据低于平均值的数据有%d\n", count);return 0;
}
结果如图:
3.键盘录入5个数据并存入数组;并:1.对该数组进行遍历;2.反转该数组;3.再对数组进行遍历。
#include<stdio.h>
void printArr(int arr[], int len);int main() {int arr[5] = { 0 };int len = sizeof(arr) / sizeof(int);for (int i = 0; i < len; i++){printf("请输入第%d个元素\n", i + 1);scanf_s("%d", &arr[i]);}//遍历数组printArr(arr, len);//反转数组int i = 0;int j = len - 1;while (i<j){int temp = arr[i];arr[i] = arr[j];arr[j] = temp;i++;j--;}printf("反转后的数组:\n");printArr(arr, len);return 0;}void printArr(int arr[], int len)
{for (int i = 0; i < len; i++){printf("%d,", arr[i]);}printf("\n");
}
结果如下:
二、数组算法题
1.基本查找
#include<stdio.h>
//基本查找
//输入一个数,查找是否在定义的数组中
int basefind(int a, int len, int arry[]);
int main() {//定义一个数组int arry[] = { 11,15,45,52,63,25,74,99,56,32,44,55 };//获取数组长度int len = sizeof(arry) / sizeof(int);//输入一个数int a;scanf_s("%d", &a);basefind( a, len, arry);return 0;
}//定义基本查找函数
int basefind(int a ,int len,int arry[]) {int is_found = 0;for (int i = 0; i < len; i++){if (arry[i] == a){is_found++;}}if (is_found == 0){printf("你输入的%d不在这个数组中", a);return 0;}else{printf("你输入的%d在这个数组中", a);return 1;} }
这段代码可以优化:
#include<stdio.h>
//基本查找
//输入一个数,查找是否在定义的数组中
int basefind(int a, int len, int arry[]);
int main() {//定义一个数组int arry[] = { 11,15,45,52,63,25,74,99,56,32,44,55 };//获取数组长度int len = sizeof(arry) / sizeof(int);//输入一个数int a;scanf_s("%d", &a);basefind(a, len, arry);return 0;
}//定义基本查找函数
int basefind(int a, int len, int arry[]) {for (int i = 0; i < len; i++){if (arry[i] == a){printf("你输入的%d在这个数组中第%d个\n", a,i+1);return 1;}}printf("你输入的%d不在这个数组中\n", a);return 0;
}
2.二分查找
#include<stdio.h>
//二分查找
int binarySearch(int arr[], int len, int num);
int main() {//定义一个数组int arr[] = { 7,8,9,11,15,25,36,45,56,64,78,79,88,99 };int len = sizeof(arr) / sizeof(int);//输入一个数int num;scanf_s("%d", &num);int index = binarySearch(arr, len, num); printf("%d\n", index);return 0;
}int binarySearch(int arr[], int len, int num) {//查找范围int min = 0;int max = len - 1;//循环查找while (min<=max){//中间位置int mid = (min + max) / 2;if (arr[mid]<num){min = mid + 1;}else if (arr[mid]>num){max = mid - 1;}else{return mid;}}return -1;
}
三、改错题
1.定义一个数组,1,2,3,4,5;要求反转该数组;再对数组进行遍历。
小明的想法是定义一个新数组,将原来数组的数据逆序输入到新数组中,在遍历输出新数组。
他敲了如下代码,请你帮他修改:
#include<stdio.h>
int main() {int arr1[5] = { 1,2,3,4,5 };int len = sizeof(arr1) / sizeof(int);int arr2[] = { 0 };for (int i = len; i >=0 ; i--){for (int j = 0; j < 5; j++){int arr2[j] = arr1[i];}printf("%d", arr2);}
}
问题分析:
1.错误的数组初始化
int arr2[] = { 0 }; // 只初始化了1个元素
arr2
被初始化为长度为 1 的数组(仅arr2[0]
有效)
说明:
(1)在定义数组时,需要指定数组中元素的个数,方括号中的常量表达式用来表示元素的个数,即数组长度。例如,指定a10],表示a数组有10个元素。注意,下标是从0开始的,这 10 个元素是a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]。请特别注意,按上面的定义,不存在数组元素a[10]。
(2)常量表达式中可以包括常量和符号常量,如“int a[3+5];”是合法的。不能包含变量,如“int a[n]”是不合法的。也就是说,C语言不允许对数组的大小作动态定义,即数组的大小不依赖于程序运行过程中变量的值。
2. 数组下标越界访问
for (int i = len; i >=0 ; i--) // len=5,i从5开始
数组arr1
的有效下标范围是0
到4
(因为长度为 5)。
当i
初始化为len
(即 5)时,arr1[i]
访问的是arr1[5]
,这就超出了数组的边界,会导致未定义行为。
针对此条改进点:修正数组访问范围,把循环范围调整为0
到len-1
,防止越界。
for (int i = len-1; i >=0 ; i--)
3. 重复定义局部变量
int arr2[j] = arr1[i]; // 错误的变量声明
这里的int arr2[j]
在循环内部又定义了一个局部变量,这和数组arr2
并非同一个东西。
每次循环都会创建一个新的局部变量,而不是给数组arr2
的元素赋值。
直接给arr2[j]
赋值,去掉多余的int
声明。
// 错误:重复定义局部变量
int arr2[j] = arr1[i];// 正确:给已有的数组元素赋值
arr2[j] = arr1[i]; // 去掉int!
关键点:在 C 语言里,int
关键字只能在声明变量时使用,赋值时不需要它。
错误原因:你混淆了 “声明变量” 和 “给变量赋值” 这两个操作。
4. 错误的打印方式
printf("%d", arr2);
arr2
代表的是数组的首地址,使用%d
格式说明符来打印地址是错误的。
若要打印数组元素,应该使用arr2[j]
,并且需要在循环里逐个打印。
5.逻辑错误
外层循环从i = len开始,一直到i = 0,这会让数组被重复覆盖。
内层循环每次都把所有元素设为arr1[i],这并非预期的逻辑。
逻辑修正:
原代码的内层循环会重复覆盖arr2的所有元素
例如,当i = 4时,arr2会被赋值为{5,5,5,5,5}
修正后:直接通过一次循环完成逆序复制
arr2[0] = arr1[4](5)
arr2[1] = arr1[3](4)
... 依此类推
核心问题:内层循环逻辑错误
for (int i = len-1; i >= 0; i--) // 外层循环:i从4递减到0
{for (int j = 0; j < 5; j++) // 内层循环:每次覆盖arr2的所有元素{arr2[j] = arr1[i]; // 把arr2的所有元素都设为arr1[i]}
}
代码执行过程分析:
当i = 4(第一次外层循环):
内层循环会把arr2的所有元素设为arr1[4](即 5)
arr2变为:{5, 5, 5, 5, 5}
当i = 3(第二次外层循环):
内层循环会把arr2的所有元素设为arr1[3](即 4)
arr2变为:{4, 4, 4, 4, 4}
依此类推:
每次外层循环都会完全覆盖arr2的所有元素
最终arr2会变成:{1, 1, 1, 1, 1}(因为最后一次i = 0时,所有元素被设为 1)
预期:逆序复制arr1 → arr2应为{5, 4, 3, 2, 1}
实际:arr2最终全是1 → 输出11111
关键改进
去掉内层循环:不需要嵌套循环,一次循环就能完成逆序复制
直接映射元素位置:
arr2[0]对应arr1[4]
arr2[1]对应arr1[3]
...
通用公式:arr2[i] = arr1[len - 1 - i]
修正后完整代码:
#include<stdio.h>
int main() {int arr1[5] = { 1, 2, 3, 4, 5 };int len = sizeof(arr1) / sizeof(arr1[0]); // 更安全的写法int arr2[5]; // 明确指定数组大小// 正确复制数组元素(逆序)for (int i = 0; i < len; i++) {arr2[i] = arr1[len - 1 - i]; // 将arr1逆序复制到arr2}// 正确打印数组元素for (int i = 0; i < len; i++) {printf("%d ", arr2[i]); // 打印每个元素}printf("\n"); // 换行return 0;
}
额外说明
sizeof(arr1[0]):使用arr1[0]比int更安全,避免硬编码;
打印格式:添加空格分隔元素,使用printf("\n")换行,让输出更易读。