2023深圳技术大学OJ平台C语言实验课实验八 ABCDE题

文章介绍了C语言实验中的几个题目,包括输出三角形字符阵列、幂级数部分和的求和、判断整数各位数字、回文数识别以及验证哥德巴赫猜想的素数检查。通过实例展示了C语言的基本语法和函数应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

感觉c实验课强度开始上来了

【id:404】【20分】A. 输出三角形字符阵列

这一题难点在于如何表达字符ABCD……

#include <stdio.h>

int main() {
	int N;
	scanf("%d", &N);

	for (int a = N, add = 0; a > 0; a--) {  /* add为ASCII码增加值 */

		for (int n = 1; n <= a; n++, add++) {  /* 定义步长n,每次执行n=a次循环 */
			printf("%c ", 'A' + add);
		}
		printf("\n");
	}

	return 0;
}

如代码,A~Z的ascii码值是连续递增的,因此只需要每次在前一次的ascii值上+1即可

救命,原来ascii最后两个是ii不是ll

(American Standard Code for Information Interchange)

【id:478】【20分】B. 求幂级数展开的部分和

#include <stdio.h>
#include <math.h>

double fact(int k) {  /* 求k的阶乘 */
	double a = 1;
	for (; k > 0; k--) {
		a = a * k;
	}
	return a;
}

int main() {
	double x, y = 1;
	int k = 1;
	scanf("%lf", &x);

	for (; fabs(1.0 * pow(x, k) / fact(k)) >= 0.00001; k++) {  /* 虽然题目要求要加fab但是好像一定是正数其实并不需要他…… */
		y = y + 1.0 * pow(x, k) / fact(k);
	}

	k++;
	y = y + 1.0 * pow(x, k) / fact(k);  /* 再执行一次 */

	printf("%.4lf", y);

	return 0;
}

这里开始用到了函数的定义和调用。

为了方便求k的阶乘我在代码的开头定义了一个函数fact()。而后当我需要求某个数的阶乘时就只需要像使用fabs()这些函数一样直接写出来就可以用了。

下面单独拎出我定义的fact()函数谈谈:

#include <stdio.h>
#include <math.h>

/* 求k的阶乘 */
double fact(int k) {  /*"double"表示后续要return回主函数的值的类型 */
	double a = 1;     /* 上面括号中的"int k"代表读入的数的类型是整型 */
	for (; k > 0; k--) {
		a = a * k;
	}
	return a;  /* 这里返回主函数一个值,返回的类型是开头的"double" */
}

int main() {
    int a=3;
    a = fact(a);  /* 调用前面定义的fact()函数,括号里输入了要运算的数,待函数执行完后会被return回一个值 */
	printf("%d", a);

	return 0;
}

输出结果为:6

————————

在这道题中要注意的是,for循环一旦条件不满足就不会执行,但是题目要求的是“求和一直继续到最后一项的绝对值小于0.00001”,因此最后的一项依然要加到y中,因此第22,23行单独又执行了一遍相加

下面看看我第一次写的代码:

#include <stdio.h>
#include <math.h>

double fact(int k) {  /* 求k的阶乘 */
	double a = 1;
	for (; k > 0; k--) {
		a = a * k;
	}
	return a;
}

int main() {
	double x, y = 1;
	int k = 0;
	scanf("%lf", &x);

	do {
		k++;
		y = y + 1.0 * pow(x, k) / fact(k);

	} while (fabs(1.0 * pow(x, k) / fact(k)) >= 0.00001);

	k++;
	y = y + 1.0 * pow(x, k) / fact(k);  /* 再执行一次 */
	printf("%.4lf", y);

	return 0;
}

这是一个错误的案例。这个代码与上面代码的差异只是for循环换成了do-while循环,但是造成的结果却大不相同——差异在输入特殊值后得运行上。

do-while循环会先无视条件执行一次循环,这就导致如果我输入的x是一个非常小的数——使得第21行条件pow(x, k) / fact(k) 已经比0.00001还要小了,但是do-while循环会先执行一次,而后面22-23行还会再执行一次,这就使得运算出来的结果多执行了一次求和,导致有一个样例会过不去。

【id:403】【20分】C. 输出整数各位数字

#include <stdio.h>

int main() {
	int x, mask = 1;
	scanf("%d", &x);
	int temp = x;  /* temp为临时值 */
	/* 计算x为几位数,若两位则mask为10,三位则为100,类推 */
	while (temp > 9) {
		temp = temp / 10;
		mask *= 10;
	}
	/* 逐一输出 */
	for (; mask >= 1; mask /= 10) {
		temp = x / mask;  /* 从左到右取出数字 */
		x = x % mask;
		printf("%d ", temp);
	}

	return 0;
}

因为要正序输出各个位数所以要先计算一共是多少位数,如果是倒序输出则不用那么麻烦。

然后!!差点没写上来!!有个人写了个超简单厉害的!!!(这里特别点名yyx同学咳咳

yyxyyxyyxyyxyyxyyxyyxyyx这次没打错了(哭死

#include <stdio.h>
#include <string.h>

int main() {
	char num_str[20];
	int i;

	scanf("%s", num_str);
	for (i = 0; i < strlen(num_str); i++) {
		printf("%c ", num_str[i]);
	}

	return 0;
}

看完她的我感觉我写的要那么多代码好像小丑(哭

【id:34】【20分】D. 判断回文数

与上题相反,这一题的思路是想办法得到倒序的数字(或者可以让中间的数或者中间的位置为跷跷板,比较两边是否镜像)

以下是用倒序比较的写法:

#include <stdio.h>

int main() {
	int n, x, y = 0, temp;  /* temp为临时值 */
	scanf("%d", &n);

	for (; n > 0; n--, y = 0) {  /* 每次都要重置一次y */ /* 这里用来循环n次 */

		scanf("%d", &x);
		temp = x;   /* 保存x值(下面计算会破坏x值) */

		for (; x >= 1; x /= 10) {  /* 这里用来倒序x */
			y = y * 10 + x % 10;  /* 关键计算 */
		}

		if (temp == y) {
			printf("Yes\n");
		} else {
			printf("No\n");
		}
	}

	return 0;
}

下面是用把数字当成跷跷板比较镜像数字的写法(取自hgx):

#include <stdio.h>
#include <string.h>

int main() {
	int n;
	scanf("%d", &n);
	getchar();  /* 这个用于吃掉输入数字后的换行符,不然第10行gets()会吃进换行符 */
	char s[1005];
	while (n--) {  /* 当n为0时表示条件不满足 */
		gets(s);
		int flag = 1;
		int lenth = strlen(s);  /* 保存读入数组长度 */
		for (int i = 0; i < lenth; i++) {
			if (s[i] != s[lenth - 1 - i]) {  /* 将数字前后镜像位数比较 */
				flag = 0;
				break;

			}
		}
		if (flag != 0) {
			printf("Yes\n");
		} else {
			printf("No\n");
		}
	}
	return 0;
}

上面第13行的镜像比较实际上会多反过来比较一轮(如判断131,先第一位和第三位比较,然后第二位和第二位比较,然后再第三位和第一位比较)。但是考虑到时间复杂度本来就不高所以不需要做优化。

样例中有一项是判断一个个位数是不是回文数(应该输出Yes)。如果你一直卡在第二个样例的话那就是你的代码需要特判个位数。

【id:400】【20分】E. 验证“哥德巴赫猜想”

#include <stdio.h>
#include <math.h>

int fact(int p) {   /* 验证是否素数 */
	int a = 1;
	if (p == 1 || p == 2) {  /* 特判1和2 */
		return a;
	}
	for (int n = 2; n <= sqrt(p) + 1; n++) {  /* 这里如果不以根号判断会超时 */
		if (p % n == 0) {
			a = 0;
			break;
		}
	}
	return a;
}

int main() {
	int N;
	scanf("%d", &N);
	int n = 2;
	for (; n <= N; n++) {
		if (fact(n) && fact(N - n)) {  /* 验证两数是否都是素数 */
			break;
		}
	}
	printf("%d = %d + %d", N, n, N - n);


	return 0;
}

自信之作!!

关于N的定义,因为在32位和64位机器中,int占32位,取值范围为-2147483648~2147483647(-2^{31} \sim 2^{31}-1)而2*10^9刚好小于这个最大的正数,所以不需要用double型或者long long型

如果你的答案提交总是报告“超时”,是因为你判断素数的方法还不够优化。如第9行,判断一直到根号p即可,不需要从2-p全部判断一遍。(我一开始这样超时了三四次。。)

剩下要注意的点就是使用sqrt()函数需要引入<math.h>库

关于第23行能运行的原理,需要了解一下c的逻辑判断。在python中有布尔值True和False,而c以1和0分辨。所以当你的if后括号内内容为“1”时会判断为“真”,为“0”时会判断为“假”。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值