experiment 4
一、实验目的
- 能正确使用C语言定义、初始化、访问、输入/输出一维/二维数组
- 能正确使用数组作为函数参数
- 针对具体问题场景,能灵活用数组组织数据,设计算法编程解决实际问题
二、实验准备
实验前,请复习第5章以下内容:
- C语法规则:数组(一维/二维)的定义、初始化、访问
- C语法规则:数组作为函数参数时,函数的定义、声明、调用语法
- 冒泡排序算法
三、实验内容
1. 实验任务1
验证性实验。验证数组的特性:类型相同、有序存放。
在C开发环境下,输入如下程序。结合运行结果,理解代码、回答问题。
task1.c
task1.c
SHOW CODE
#include <stdio.h>
#define N 4
#define M 2
void test1() {
int x[N] = {1, 9, 8, 4};
int i;
// 输出数组x占用的内存字节数
printf("sizeof(x) = %d\n", sizeof(x));
// 输出每个元素的地址、值
for (i = 0; i < N; ++i)
printf("%p: %d\n", &x[i], x[i]);
// 输出数组名x对应的值
printf("x = %p\n", x);
}
void test2() {
int x[M][N] = {{1, 9, 8, 4}, {2, 0, 4, 9}};
int i, j;
// 输出二维数组x占用的内存字节数
printf("sizeof(x) = %d\n", sizeof(x));
// 输出每个元素的地址、值
for (i = 0; i < M; ++i)
for (j = 0; j < N; ++j)
printf("%p: %d\n", &x[i][j], x[i][j]);
printf("\n");
// 输出二维数组名x, 以及,x[0], x[1]的值
printf("x = %p\n", x);
printf("x[0] = %p\n", x[0]);
printf("x[1] = %p\n", x[1]);
printf("\n");
}
int main() {
printf("测试1: int型一维数组\n");
test1();
printf("\n测试2: int型二维数组\n");
test2();
return 0;
}
//预览结果如图所示

问题一:连续存放且相同
问题二:按行连续存放;相同;4*4=16个字节;含义是二维数组中一行元素所占的内存字节数。
2. 实验任务2
验证性实验。验证一维数组作为函数参数的用法。
在C开发环境下,输入如下程序。结合运行结果,理解代码、回答问题。
task2.c
SHOW CODE
#include <stdio.h>
#define N 100
// 函数声明
void input(int x[], int n);
double compute(int x[], int n);
int main() {
int x[N];
int n, i;
double ans;
while(printf("Enter n: "), scanf("%d", &n) != EOF) {
input(x, n); // 函数调用
ans = compute(x, n); // 函数调用
printf("ans = %.2f\n\n", ans);
}
return 0;
}
// 函数定义
void input(int x[], int n) {
int i;
for(i = 0; i < n; ++i)
scanf("%d", &x[i]);
}
// 函数定义
double compute(int x[], int n) {
int i, high, low;
double ans;
high = low = x[0];
ans = 0;
for(i = 0; i < n; ++i) {
ans += x[i];
if(x[i] > high)
high = x[i];
else if(x[i] < low)
low = x[i];
}
ans = (ans - high - low)/(n-2);
return ans;
}
//预览结果如图所示

问题一:void input(int x[],int n)中x[]和n是形参;input(x,n)中x和n是实参。
问题二:函数 input 的功能:通过循环遍历数组,接收用户输入的 n 个整数,将其存入数组 x 中
函数 compute 的功能:先计算数组所有元素的总和,同时找出数组中的最大值 high 和最小值 low ;然后用总和减去最大值和最小值,再除以 n-2 ,得到去掉最大值和最小值后的平均值,并返回该平均值。
3. 实验任务3
验证性实验。验证二维数组作为函数参数的用法。
在C开发环境下,输入如下程序。结合运行结果,理解代码、回答问题。
task3.c
SHOW CODE
#include <stdio.h>
#define N 100
// 函数声明
void output(int x[][N], int n);
void init(int x[][N], int n, int value);
int main() {
int x[N][N];
int n, value;
while(printf("Enter n and value: "), scanf("%d%d", &n, &value) != EOF) {
init(x, n, value); // 函数调用
output(x, n); // 函数调用
printf("\n");
}
return 0;
}
// 函数定义
void output(int x[][N], int n) {
int i, j;
for(i = 0; i < n; ++i) {
for(j = 0; j < n; ++j)
printf("%d ", x[i][j]);
printf("\n");
}
}
// 函数定义
void init(int x[][N], int n, int value) {
int i, j;
for(i = 0; i < n; ++i)
for(j = 0; j < n; ++j)
x[i][j] = value;
}
//预览效果如图所示

问题一:output(int x[][N], int n)中,int x[][N], int n为形参;output(x, n)中,x和n是实参
问题二:不能,二维数组的列不能省略
问题三: 函数 output 的功能:通过嵌套循环遍历二维数组的前 n 行 n 列,逐行打印数组中的元素,每行元素打印后换行。
函数 init 的功能:通过嵌套循环遍历二维数组的前 n 行 n 列,将所有元素赋值为指定的 value (即初始化二维数组的前 n×n 个元素为 value )
4. 实验任务4
编写程序,计算一组数据中值。
中值在统计学中定义如下:
一组数据集有序排序后,如果数据集个数是奇数,中值就是排序后位于正中间的那个数值;如果数据集个数是偶
数,排序后中值就是中间两个数均值。
例如:
{1, 2, 3, 4, 5}中值是3
{1, 2, 3, 4, 5, 6}中值是(3+4)/2 = 3.5
具体要求如下:
设计函数 median ,实现:计算n个整数的中值,并返回中值
设计函数 input , 实现: 从键盘录入n个整数
在 main 函数中编写主体代码逻辑:调用函数 input 完成数据录入,调用 median 获取中值,打印输出中值。
task4
SHOW CODE
#include <stdio.h>
#define N 100
// 函数声明
void input(int x[],int n);
double median(int x[],int n);
int main() {
int x[N];
int n;
double ans;
while(printf("Enter n: "), scanf("%d", &n) != EOF) {
input(x, n); // 函数调用
ans = median(x, n); // 函数调用
printf("ans = %g\n\n", ans);
}
return 0;
}
// 函数定义
void input(int x[],int n)
{
int i;
for(i=0;i<n;++i)
scanf("%d",&x[i]);
}
double median(int x[],int n){
int i,j,temp;
for(i=0;i<n-1;++i)
{
for(j=0;j<n-1-i;++j)
{
if(x[j]>x[j+i])
{
temp = x[j];
x[j]=x[j+1];
x[j+1]=temp;
}
}
}
if(n%2!=0){
return (double)x[n/2];
}
else{
return (x[n/2-1]+x[n/2])/2.0;
}
}
//预览效果如图所示

5. 实验任务5
编写程序,实现数值阵列处理。具体要求如下:
设计、编写函数 rotate_to_right ,实现将一个n×n (n <= 100)的方阵,按列循环右移。最右边一列数据绕回
左边。
在 main 中编写主体代码:输出原始方阵,调用 rotate_to_right 按列循环右移,输出变换后方阵。
task5.c:
SHOW CODE
#include <stdio.h>
#define N 100
// 函数声明
void input(int x[][N], int n);
void output(int x[][N], int n);
// 函数rotate_to_right声明
void rotate_to_right(int x[][N],int n) ;
// ×××
int main() {
int x[N][N];
int n;
printf("输入n: ");
scanf("%d", &n);
input(x, n);
printf("原始矩阵:\n");
output(x, n);
// 函数rotate_to_right调用
rotate_to_right(x,n) ;
printf("变换后矩阵:\n");
output(x, n);
return 0;
}
// 函数定义
// 功能: 输入一个n*n的矩阵x
void input(int x[][N], int n) {
int i, j;
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j)
scanf("%d", &x[i][j]);
}
}
// 函数定义
// 功能: 输出一个n*n的矩阵x
void output(int x[][N], int n) {
int i, j;
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j)
printf("%4d", x[i][j]);
printf("\n");
}
}
// 函数rotate_to_right定义
// 功能: 把一个n*n的矩阵x,每一列向右移, 最右边一列绕回左边
// 实现列循环右移
void rotate_to_right(int x[][N], int n) {
int i;
int last_col[N];
int j;
for (i = 0; i < n; ++i) {
last_col[i] = x[i][n-1];
}
// 列右移
for (j = n-1; j > 0; --j) {
for (i = 0; i < n; ++i) {
x[i][j] = x[i][j-1];
}
}
// 最右列放最左列
for (i = 0; i < n; ++i) {
x[i][0] = last_col[i];
}
}
//预览效果如图所示

6. 实验任务6
编写程序,实现进制转换。具体要求如下:
编写函数 dec_to_n ,实现把十进制整数x转换成n进制输出。(n限定取2, 8, 16)
在 main 函数中编写主体代码逻辑:从键盘输入n,调用 dec_to_n ,把十进制整数转换成二进制、八进制、十
六进制输出。
不使用格式符%o, %x
task.6
SHOW CODE
#include <stdio.h>
#define N 100
// 函数声明
void dec_to_n(int x, int n);
int main() {
int x;
while (printf("输入十进制整数:"), scanf("%d", &x) != EOF) {
dec_to_n(x, 2); // 转二进制
dec_to_n(x, 8); // 转八进制
dec_to_n(x, 16); // 转十六进制
printf("\n");
}
return 0;
}
// 函数定义:十进制转n进制(n=2,8,16)
void dec_to_n(int x, int n) {
int remainder, i = 0;
int result[N];
int temp = x;
while (temp != 0) {
remainder = temp % n;
result[i++] = remainder;
temp = temp / n;
}
printf("%d转%d进制:", x, n);
int j;
for ( j = i - 1; j >= 0; j--) {
if (n == 16 && result[j] >= 10) {
printf("%c", 'A' + result[j] - 10);
} else {
printf("%d", result[j]);
}
}
printf("\n");
}
//预览结果如下

7. 实验任务7
编程判断魔方矩阵。
魔方矩阵定义如下:
魔方矩阵,是一个n×n(n为奇数)的方阵。其元素值为1, 2, 3, 4, ...,n
这些元素在矩阵中的位置要确保方阵每行、每列、每条对角线上的和都相等。
程序编写要求如下:
设计、编写函数is_magic,用于判断一个n阶方阵是否为魔方矩阵,如果是,返回1; 否则,返回0
在main中编写主体代码逻辑
输入n
// xxx 23
调用函数input从键盘输入n阶方阵x
调用函数output输出n阶方阵x
调用函数is_magic判断n阶方阵x
task 7
SHOW CODE
#include <stdio.h>
#define N 100
// 函数声明
void input(int x[][N], int n);
void output(int x[][N], int n);
int is_magic(int x[][N], int n); // 补充is_magic声明
int main() {
int x[N][N];
int n;
while(printf("输入n:"), scanf("%d", &n) != EOF) {
printf("输入方阵:\n");
input(x, n);
printf("输出方阵:\n");
output(x, n);
if(is_magic(x, n))
printf("是魔方矩阵\n\n");
else
printf("不是魔方矩阵\n\n");
}
return 0;
}
// 输入n阶方阵
void input(int x[][N], int n) {
int i, j;
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j)
scanf("%d", &x[i][j]);
}
}
// 输出n阶方阵
void output(int x[][N], int n) {
int i, j;
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j)
printf("%d ", x[i][j]);
printf("\n");
}
}
// 判断是否为魔方矩阵
int i,j;
int is_magic(int x[][N], int n) {
if (n % 2 == 0) return 0;
int target_sum = n * (n * n + 1) / 2;
for (i = 0; i < n; ++i) {
int row_sum = 0;
for ( j = 0; j < n; ++j) {
row_sum += x[i][j];
}
if (row_sum != target_sum) return 0;
}
for ( j = 0; j < n; ++j) {
int col_sum = 0;
for ( i = 0; i < n; ++i) {
col_sum += x[i][j];
}
if (col_sum != target_sum) return 0;
}
int diag1_sum = 0;
for (i = 0; i < n; ++i) {
diag1_sum += x[i][i];
}
if (diag1_sum != target_sum) return 0;
int diag2_sum = 0;
for (i = 0; i < n; ++i) {
diag2_sum += x[i][n - 1 - i];
}
if (diag2_sum != target_sum) return 0;
int exist[N*N + 1] = {0};
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
int val = x[i][j];
if (val < 1 || val > n*n || exist[val]) {
return 0;
}
exist[val] = 1;
}
}
return 1;
}
//预览效果如图所示


浙公网安备 33010602011771号