实验四
test_1
验证性实验。验证数组的特性:类型相同、有序存放。
在C开发环境下,输入如下程序。结合运行结果,理解代码、回答问题。
点击查看代码
#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("测试2: int 型二维数组\n");
test2();
return 0;
}
问题1:一维数组x在内存中是否连续存放?x和&x[0]的值相同吗?
ans:
是连续存放的,因为每个元素地址相差 sizeof(int)(4 字节)所以看上去地址的数字不是1 2 3 4的这种连续。
x 和 &x[0] 的值相同。数组名 x 代表数组首元素的地址,与 &x[0] 的值完全一致。
问题2:二维数组x在内存中是否按行连续存放?x、x[0]和&x[0][0]的值相同吗?x[0]和x[1]相差多少?该差值的含义是什么?
ans:
是按行连续存放的,所有元素地址依次递增,第一行末尾与第二行开头紧邻。
x、x[0] 和 &x[0][0] 的值相同,都指向二维数组在内存中的起始位置。
x[0] 和 x[1] 相差 16 字节(在 4 字节 int 环境下)。
该差值的含义:二维数组每一行所占的字节数,即 N * sizeof(int),也就是一行的总大小。

test_2
验证性实验。验证一维数组作为函数参数的用法。
在C开发环境下,输入如下程序。结合运行结果,理解代码、回答问题。
点击查看代码
#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;
}

问题1:一维数组作为参数时(以 input 函数为例),形参、实参书写形式分别是什么?
ans :
形参(在函数定义/声明中):
input 函数的第一个形参写作 int x[](也可以写作 int *x,两种形式等价)。它表示函数接受一个 int 型数组。
实参(在函数调用时):
main 函数中调用 input(x, n); 时,实参是 数组名 x(以及整型变量 n)。
数组名 x 在这里代表数组的首地址,传递给函数后,函数可以通过这个地址操作原数组。
结论:
形参写 int x[],实参写数组名 x
问题2:函数 input 的功能是?函数 compute 的功能是?
ans:
input 函数的功能:
从标准输入读取 n 个整数,依次存入数组 x 的前 n 个元素中。
简单说:为数组输入数据。
compute 函数的功能:
对数组 x 中的 n 个整数,去掉一个最大值和一个最小值后,计算剩余 n-2 个元素的平均值,并将计算结果返回。
如果 n<=2 时程序会出错(分母为0或负数),但实验假设正常输入 n>2。
读写代码是产生一个问题:for(i = 0; i < n;++i)
scanf("%d", &x[i]);这个看上去不是输入每次输入一个数字放到对应的位置吗,为什么实际运行时输入一个完整的数组自动对应
通过deepseek解决:代码的逻辑确实是每次循环调用一次 scanf,读一个数字到 x[i] 的位置。然后回车,这些字符(包括空格和换行)会先被送到一个叫输入缓冲区的地方。
scanf("%d", ...) 的工作方式是:它会跳过前面的空白字符(空格、换行、制表符等),然后读取连续的数字字符直到遇到非数字字符,将这个数字转换成一个整数,存入对应变量。关键点:它会读走它需要的那个数字,但是剩下的内容依然留在缓冲区里,不会被丢掉了。然后循环,逐步从缓冲区中提取。
test_3
验证性实验。验证二维数组作为函数参数的用法。
在C开发环境下,输入如下程序。结合运行结果,理解代码、回答问题。
点击查看代码
#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;
}

问题1:两维数组作为函数参数时(以函数 output 为例),形参、实参书写形式分别是什么?
ans:
形参(函数定义/声明处)
output 的第一个形参写作 int x[][N](第二维必须显式写出大小,第一维可以省略)。
完整形参:int x[][N], int n
实参(函数调用处)
在 main 中调用 output(x, n);
实参是二维数组名 x(代表数组首地址),以及整型变量 n。
结论:形参中二维数组写作 int x[][N],实参直接写数组名 x。
问题2:两维数组作为函数形参时,第二维大小能省略吗?(以函数 output 为例,试着把形参 x[][N] 写成 x[][] ,编译代码,观察编译器是否报错)
不能省略,编译器会报错。error: array type has incomplete element type 'int[]'
问题3:函数 output 的功能是?函数 init 的功能是?
output 的功能
以矩阵形式(每行 n 个元素,空格分隔,每行末尾换行)输出二维数组 x 的前 n 行、前 n 列构成的子矩阵。
即按 n×n 的格式打印数组内容。
init 的功能
将二维数组 x 的前 n 行、前 n 列的所有元素都赋值为 value。
即把这个 n×n 的区域初始化为同一个指定值。
test_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 获取中值,打印输出中值。
待补足的代码如下:
点击查看代码
#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, k;
//使用冒泡 排序先由小到大将数组排序
for (i=0;i<n-1;++i){
for(j = 0;j<n-1;++j){
if(x[j]>x[j+1]){
k = x[j];
x[j] = x[j+1];
x[j+1] = k;
}
}
}
//现在根据奇偶算
if (n % 2 == 1) {
return x[n / 2]; // 奇数个,正中间
} else {
return (x[n / 2 - 1] + x[n / 2]) / 2.0; // 偶数个,中间两个的平均值
}
}

test_5
编写程序,实现数值阵列处理。具体要求如下:
设计、编写函数 rotate_to_right ,实现将一个n×n (n <= 100)的方阵,按列循环右移。最右边一列数据绕回
左边。
在 main 中编写主体代码:输出原始方阵,调用 rotate_to_right 按列循环右移,输出变换后方阵。
点击查看代码
#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("Enter n:");
scanf("%d",&n);
input(x,n);
printf("原始矩阵:\n");
output(x, n);
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");
}
}
//功能:把n*n的矩阵x每一行循环右移一列
void rotate_to_right(int x[][N], int n) {
int i, j, k;
for (i = 0; i < n; ++i) {
k = x[i][n - 1];
for (j = n - 1; j > 0; --j) {
x[i][j] = x[i][j - 1];
}
x[i][0] = k; //(最右列移到最左列)
}
}

test_6
编写程序,实现进制转换。具体要求如下:
编写函数 dec_to_n ,实现把十进制整数x转换成n进制输出。(n限定取2, 8, 16)
在 main 函数中编写主体代码逻辑:从键盘输入n,调用 dec_to_n ,把十进制整数转换成二进制、八进制、十
六进制输出。
不使用格式符%o, %x
点击查看代码
#include <stdio.h>
// 函数声明
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;
}
// 将十进制整数 x 转换为 n 进制(n为2、8、16)并输出
void dec_to_n(int x, int n) {
char map[] = "0123456789ABCDEF";
char ans[100];
int cnt = 0;
int r;
// 特殊情况:x 为 0
if (x == 0) {
printf("0\n");
return;
}
do {
r = x % n;
ans[cnt++] = map[r];
x = x / n;
} while (x > 0);
for (int i = cnt - 1; i >= 0; --i)
printf("%c", ans[i]);
printf("\n");
}

test_7
编程判断魔方矩阵。
魔方矩阵,是一个n×n(n为奇数)的方阵。其元素值为1, 2, 3, 4, ...,n**2。
这些元素的排列需满足:每行、每列、两条对角线上的和均等于幻和 n(n²+1)/2。
程序编写要求如下:
设计、编写函数is_magic,用于判断一个n阶方阵是否为魔方矩阵,如果是,返回1; 否则,返回0
在main中编写主体代码逻辑
输入n
调用函数input从键盘输入n阶方阵x
调用函数output输出n阶方阵x
// xxx 23
调用函数is_magic判断n阶方阵x
点击查看代码
#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);
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;
}
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]);
}
}
}
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");
}
}
// 功能:判断 n 阶方阵 x 是否为魔方矩阵,是则返回1,否则返回0
int is_magic(int x[][N], int n) {
// 魔方矩阵要求 n 为奇数
if (n % 2 == 0)
return 0;
int total = n * n;
int sum_magic = n * (total + 1) / 2;
int i,j;
// 检查各行和
for (i = 0; i < n; ++i) {
int row_sum = 0;
for (j = 0; j < n; ++j)
row_sum += x[i][j];
if (row_sum != sum_magic)
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 != sum_magic)
return 0;
}
// 检查主对角线(左上 -> 右下)
int diag1 = 0;
for (i = 0; i < n; ++i)
diag1 += x[i][i];
if (diag1 != sum_magic)
return 0;
// 检查副对角线(右上 -> 左下)
int diag2 = 0;
for (i = 0; i < n; ++i)
diag2 += x[i][n - 1 - i];
if (diag2 != sum_magic)
return 0;
// 全部条件满足
return 1;
}
test_8
编写程序,找出一个符合下列条件的数字:它的平方值与立方值一共使用了0到9十个数字,且一个数字只是用一次。
以17为例:
172
= 289
173
= 4913
17不满足条件,因为它的平方、立方只包含1,2,3,4,8,9这几个数字,没有包含0,5,6,7,而且,9重复了一次。
编写程序,找出符合条件的一个数字,只要找到一个就终止程序。打印出找到的数字。
点击查看代码
#include <stdio.h>
int main(){
int x,sq,cu;
int q[10];
int i,d ,cnt,valid;
int temp;
for (x=10;x<=99;++x){
sq = x*x;
cu = x*x*x;
for (i=0;i<10;++i)
q[i] = 0;
cnt = 0;
temp = sq;
while(temp>0){
d = temp%10;
q[d]++; //d 是当前取出来的那一位数字(比如 3),q[d] 就是数组里对应数字 3 的计数器。++把这个计数器的值加1,表示数字3又出现了一次
cnt++;
temp/=10;
}
temp = cu;
while (temp > 0) {
d = temp % 10;
q[d]++;
cnt++;
temp /= 10;
}
if (cnt != 10) continue;
valid = 1;
for (i = 0; i < 10; ++i) {
if (q[i] != 1) {
valid = 0;
break; // 只要有一个不满足,标记失败并跳出
}
}
if (valid) {
printf("找到的数字是:%d\n", x);
// 输出平方、立方和拼接结果
break; // 终止外层循环,只找一个数字
}
}
return 0;
}
点击查看代码
for (i = 0; i < 10; ++i) {
if (q[i] != 1) {
valid = 0;
break; // 只要有一个不满足,标记失败并跳出
}
}
if (valid) {
printf("找到的数字是:%d\n", x);
// 输出平方、立方和拼接结果
break; // 终止外层循环,只找一个数字
}
浙公网安备 33010602011771号