实验 4_C语言数组应用编程
一、实验目的
1. 能正确使用C语法规则定义、初始化、访问、输入/输出一维/二维数组
2. 能正确使用数组作为函数参数
3. 针对具体问题场景,能灵活用数组组织数据,应用、设计算法编程解决实际问题
二、实验过程
Task1:一维、二维数组的地址
源代码:
1 #include <stdio.h> 2 #define N 4 3 #define M 2 4 5 void test1() { 6 int x[N] = {1, 9, 8, 4}; 7 int i; 8 9 // 输出数组x占用的内存字节数 10 printf("sizeof(x) = %d\n", sizeof(x)); 11 12 // 输出每个元素的地址、值 13 for (i = 0; i < N; ++i) 14 printf("%p: %d\n", &x[i], x[i]); 15 16 // 输出数组名x对应的值 17 printf("x = %p\n", x); 18 } 19 20 void test2() { 21 int x[M][N] = {{1, 9, 8, 4}, {2, 0, 4, 9}}; 22 int i, j; 23 24 // 输出二维数组x占用的内存字节数 25 printf("sizeof(x) = %d\n", sizeof(x)); 26 27 // 输出每个元素的地址、值 28 for (i = 0; i < M; ++i) 29 for (j = 0; j < N; ++j) 30 printf("%p: %d\n", &x[i][j], x[i][j]); 31 printf("\n"); 32 33 // 输出二维数组名x, 以及,x[0], x[1]的值 34 printf("x = %p\n", x); 35 printf("x[0] = %p\n", x[0]); 36 printf("x[1] = %p\n", x[1]); 37 printf("\n"); 38 } 39 40 int main() { 41 printf("测试1: int型一维数组\n"); 42 test1(); 43 44 printf("\n测试2: int型二维数组\n"); 45 test2(); 46 47 return 0; 48 }
运行结果:

问题回答:
问题 1 : int 型一维数组 x ,在内存中是否是连续存放的?数组名 x 对应的值,和 &x[0] 是⼀样的吗?
答:是连续存放的。数组名 x 对应的值和数组的首地址 &x[0] 是⼀样的。
问题 2 : int 型⼆维数组 x ,在内存中是否是 " 按行连续存放 " 的?数组名 x 的值、x[0] 、 &x[0][0] ,其值,在字面上,是⼀样的吗? x[0] 和 x[1] 相差多少?你能猜测 / 推断出这个差值的意义吗?
答:int 型⼆维数组 x 在内存中是 " 按行连续存放 " 的。
x:表示二维数组的起始位置,即指向第一行的地址。x[0]:表示第一行的起始位置,即指向 x[0][0] 的地址。&x[0][0]:表示第一行第一列元素的地址。因此,从概念上讲,x 和 x[0]、&x[0][0] 在字面上是相同的,内容都是第一行第一个元素的地址。
x[0] 和 x[1]之间的差值是N * sizeof(int)(即在上面的示例中是 4 * sizeof(int),假设 sizeof(int) 是 4 字节,结果是 4*4=16 字节)。在内存中,第二行的起始地址距离第一行的起始地址相隔 N 个 int 类型的大小的字节。
这个距离表明了二维数组的行数和列数是如何在内存中布局的。具体来说,一个二维数组的行数在内存中是连续存放的,且每行的元素数量决定了后续行的起始地址。差值确保了数组能够被有效地按行索引和访问。
Task2:验证一维数组作为函数形参的用法
源代码:
1 #include <stdio.h> 2 #define N 100 3 4 // 函数声明 5 void input(int x[], int n); 6 double compute(int x[], int n); 7 8 int main() { 9 int x[N]; 10 int n, i; 11 double ans; 12 13 while (printf("Enter n: "), scanf_s("%d", &n) != EOF) { 14 input(x, n); // 函数调用 15 ans = compute(x, n); // 函数调用 16 printf("ans = %.2f\n\n", ans); 17 } 18 19 return 0; 20 } 21 22 // 函数定义 23 void input(int x[], int n) { 24 int i; 25 26 for (i = 0; i < n; ++i) 27 scanf_s("%d", &x[i]); 28 } 29 30 // 函数定义 31 double compute(int x[], int n) { 32 int i, high, low; 33 double ans; 34 35 high = low = x[0]; 36 ans = 0; 37 38 for (i = 0; i < n; ++i) { 39 ans += x[i]; 40 41 if (x[i] > high) 42 high = x[i]; 43 else if (x[i] < low) 44 low = x[i]; 45 } 46 47 ans = (ans - high - low) / (n - 2); 48 49 return ans; 50 }
运行结果:

问题回答:
观察:⼀维数组作为形参时,其书写形式?实参的书写形式?
答:形参的书写形式:在函数声明或定义中,一维数组形参写作 int x[] ,表示传入一个整型数组。
实参的书写形式:调用函数时,直接传入数组名即可。例如:input(x, n); 这里 x 是数组名,表示数组在内存中首元素的地址。
问题:函数 input 的功能是?函数 compute 的功能是?
答:input 的功能是从标准输入读取 n 个整数,依次存入数组 x 中。函数 compute 的功能是计算数组 x 中所有元素的总和 ans,同时找出最大值 high 和最小值 low,然后去掉最大值和最小值再计算剩余元素的平均值,并返回这个平均数。
Task3:验证二维数组作为函数形参的用法
源代码:
1 #include <stdio.h> 2 #define N 100 3 // 函数声明 4 void output(int x[][N], int n); 5 void init(int x[][N], int n, int value); 6 int main() { 7 int x[N][N]; 8 int n, value; 9 while (printf("Enter n and value: "), scanf_s("%d%d", &n, &value) != EOF) { 10 init(x, n, value); // 函数调用 11 output(x, n); 12 printf("\n"); 13 } 14 return 0; 15 } 16 // 函数调用 17 // 函数定义 18 void output(int x[][N], int n) { 19 int i, j; 20 for (i = 0; i < n; ++i) { 21 for (j = 0; j < n; ++j) 22 printf("%d ", x[i][j]); 23 printf("\n"); 24 } 25 } 26 // 函数定义 27 void init(int x[][N], int n, int value) { 28 int i, j; 29 for (i = 0; i < n; ++i) 30 for (j = 0; j < n; ++j) 31 x[i][j] = value; 32 }
运行结果:

问题回答:
观察:两维数组作为函数形参时,形参的书写形式?实参的书写形式?
答:形参写法:函数形参声明时,对于二维数组,如 int x[][N],必须明确第二维的大小N,而第一维可以省略。实参写法:实参传递时就是普通的二维数组变量名,如x,不加任何维度大小。
问题1:两维数组作为函数形参时,哪⼀维的⼤⼩不能省略?
答:答:第二维的大小不能省略。因为C语言编译器需要知道每行的长度,从而正确计算地址偏移。第一维大小可以省略(通常用指向数组的指针代替)。
问题2:函数output功能是?函数init的功能是?
答:函数output功能是输出一个 n x n 的二维数组 x,逐行打印其中的元素。函数init的功能是初始化一个 n x n 的二维数组 x,将所有元素赋值为value。
Task4:计算⼀组数据中值
源代码:
1 #include <stdio.h> 2 #define N 100 3 4 // 函数声明 5 void input(int x[], int n); 6 double median(int x[], int n); 7 8 int main() { 9 int x[N]; 10 int n; 11 double ans; 12 while (printf("Enter n: "), scanf_s("%d", &n) != EOF) { 13 input(x, n); // 读取数据 14 ans = median(x, n); // 计算中值 15 printf("ans = %g\n\n", ans); 16 } 17 return 0; 18 } 19 20 // 从键盘读入n个整数到数组x 21 void input(int x[], int n) { 22 int i; 23 printf("Enter %d numbers: ", n); 24 for (i = 0; i < n; ++i) { 25 scanf_s("%d", &x[i]); 26 } 27 } 28 29 // 计算中值,先对数组排序,再计算中位数 30 double median(int x[], int n) { 31 int i, j, temp; 32 // 简单冒泡排序 33 for (i = 0; i < n - 1; ++i) { 34 for (j = 0; j < n - 1 - i; ++j) { 35 if (x[j] > x[j + 1]) { 36 temp = x[j]; 37 x[j] = x[j + 1]; 38 x[j + 1] = temp; 39 } 40 } 41 } 42 43 // 计算中值 44 if (n % 2 == 1) { 45 // 奇数个数 - 中间那个数 46 return x[n / 2]; 47 } 48 else { 49 // 偶数个数 - 取中间两个数的均值 50 return (x[n / 2 - 1] + x[n / 2]) / 2.0; 51 } 52 }
运行结果:

Task5:实现数值阵列处理
源代码:
1 #include <stdio.h> 2 #define N 100 3 4 // 函数声明 5 void input(int x[][N], int n); 6 void output(int x[][N], int n); 7 void rotate_to_right(int x[][N], int n); // 补充声明 8 9 int main() { 10 int x[N][N]; 11 int n; 12 printf("Enter n: "); 13 scanf_s("%d", &n); 14 15 input(x, n); 16 17 printf("原始矩阵:\n"); 18 output(x, n); 19 20 rotate_to_right(x, n); // 调用按列右移函数 21 22 printf("变换后矩阵:\n"); 23 output(x, n); 24 25 return 0; 26 } 27 28 // 输入函数定义 29 void input(int x[][N], int n) { 30 int i, j; 31 for (i = 0; i < n; ++i) { 32 for (j = 0; j < n; ++j) 33 scanf_s("%d", &x[i][j]); 34 } 35 } 36 37 // 输出函数定义 38 void output(int x[][N], int n) { 39 int i, j; 40 for (i = 0; i < n; ++i) { 41 for (j = 0; j < n; ++j) 42 printf("%4d", x[i][j]); 43 printf("\n"); 44 } 45 } 46 47 // rotate_to_right函数定义 48 void rotate_to_right(int x[][N], int n) { 49 int i, j; 50 int last_col[N]; 51 52 // 先保存最右边一列 53 for (i = 0; i < n; i++) 54 last_col[i] = x[i][n - 1]; 55 56 // 每列元素右移一列 57 for (j = n - 1; j > 0; j--) { 58 for (i = 0; i < n; i++) { 59 x[i][j] = x[i][j - 1]; 60 } 61 } 62 63 // 最左边列赋值为保存的最右边列 64 for (i = 0; i < n; i++) { 65 x[i][0] = last_col[i]; 66 } 67 }
运行结果:

Task6:进制转换
源代码:
1 #include <stdio.h> 2 #define N 100 3 4 void dec_to_n(int x, int n); // 函数声明 5 6 int main() { 7 int x; 8 9 while (printf("输入十进制整数: "), scanf_s("%d", &x) != EOF) { 10 dec_to_n(x, 2); // 函数调用: 把x转换成二进制输出 11 dec_to_n(x, 8); // 函数调用: 把x转换成八进制输出 12 dec_to_n(x, 16); // 函数调用: 把x转换成十六进制输出 13 printf("\n"); 14 } 15 16 return 0; 17 } 18 19 // 函数定义 20 // 功能: 把十进制数x转换成n进制,打印输出 21 void dec_to_n(int x, int n) { 22 char map[]= "0123456789ABCDEF"; //制作转换所需的字符表 23 char exchange[N]; //保存转换后的字符串 24 int d, r; //商和余数 25 int cnt = 0; //计数余数的个数 26 27 // 使用除法和取余法进行进制转换 28 while (1) { 29 r = x % n; //计算余数 30 d = x / n; //计算商 31 exchange[cnt++] = map[r]; //一一映射关系 32 33 if (d == 0) 34 break; 35 36 x = d; //把商作为新的被除数 37 } 38 39 // 把计算出来的余数逆序输出 40 for (--cnt;cnt >= 0;--cnt) { 41 printf("%c", exchange[cnt]); //输出字符 42 } 43 44 printf("\n"); //在不同进制之间换行 45 }
运行结果:

三、实验心得
在使用AI辅助编程练习的过程中,需要学习如何prompt,可以输入更好的算法,以实现高质量的人机对话。
浙公网安备 33010602011771号