实验四

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),也就是一行的总大小。
屏幕截图 2026-05-04 100208

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;
} 

屏幕截图 2026-05-04 102840

问题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;
		
}

屏幕截图 2026-05-04 105707
问题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;  // 偶数个,中间两个的平均值
    }
	 
}

屏幕截图 2026-05-04 114449

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;     //(最右列移到最左列)             
    }
}

屏幕截图 2026-05-04 133650

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");
}

屏幕截图 2026-05-04 150023

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;
}
![屏幕截图 2026-05-04 151538](https://img2024.cnblogs.com/blog/3779798/202605/3779798-20260504151558654-875158796.png)

test_8
编写程序,找出一个符合下列条件的数字:它的平方值与立方值一共使用了0到9十个数字,且一个数字只是用一次。
以17为例:
172
= 289
17
3
= 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;
}
**实验总结:** 本次实验, 1.明白了循环中scanf读入一个数组,会放入一个缓冲区域随着循环依次读入。不需要每次手动读入. 2.如果在循环中要每次的循环都满足一个条件,某条件才成立,需要引入一个valid变量
点击查看代码
for (i = 0; i < 10; ++i) {
    if (q[i] != 1) {
        valid = 0;
        break;        // 只要有一个不满足,标记失败并跳出
    }
}
if (valid) {
    printf("找到的数字是:%d\n", x);
    // 输出平方、立方和拼接结果
    break;  // 终止外层循环,只找一个数字
}
3. q[d]++; //d 是当前取出来的那一位数字(比如 3),q[d] 就是数组里对应数字 3 的计数器。++把这个计数器的的值加1,表示数字3又出现了一次
posted @ 2026-05-04 15:47  江苏燕双鹰  阅读(17)  评论(0)    收藏  举报