实验3 C语言函数应用编程
实验任务1
1.源代码
#include <stdio.h>
char score_to_grade(int score); // 函数声明
int main() {
int score;
char grade;
while (scanf("%d", &score) != EOF) {
grade = score_to_grade(score); // 函数调用
printf("分数: %d, 等级: %c\n\n", score, grade);
}
return 0;
}
// 函数定义
char score_to_grade(int score) {
char ans;
switch (score / 10) {
case 10:
case 9: ans = 'A'; break;
case 8: ans = 'B'; break;
case 7: ans = 'C'; break;
case 6: ans = 'D'; break;
default: ans = 'E';
}
return ans;
}
2.运行结果

3.Q&A
Q1:函数score_to_grade的功能是什么?形参类型、返回值类型是什么?
A1:将输入的数字分数转换为对应的字母等级。其形参类型为int,返回值类型为字符型char。
Q2:如果line21-28以下形式,代码存在哪些问题,请逐一指出。
switch(score/10) {
case 10:
case 9: ans = "A";
case 8: ans = "B";
case 7: ans = "C";
case 6: ans = "D";
default: ans = 'E';
}
A2:如果将代码改为赋值为"A"、"B",存在数据类型不匹配的问题。"A"是一个字符串字面量,而变量ans被声明为char类型。将字符串的地址赋值给char类型变量会导致编译警告或错误,且运行结果绝对不符合预期。正确的做法必须使用单引号'A'表示字符常量。
实验任务2
1.源代码
#include <stdio.h>
int sum_digits(int n); // 函数声明
int main() {
int n;
int ans;
while (printf("Enter n: "), scanf("%d", &n) != EOF) {
ans = sum_digits(n); // 函数调用
printf("n = %d, ans = %d\n\n", n, ans);
}
return 0;
}
// 函数定义
int sum_digits(int n) {
int ans = 0;
while (n != 0) {
ans += n % 10;
n /= 10;
}
return ans;
}
2.运行结果

3.Q&A
Q1:函数sum_digits的功能是什么?
A1:计算并返回一个整数n各位数字之和。
Q2:如果把函数sum_digits定义成如下实现方式,能实现同样的输出吗?如果能,说明两种实现方式的算法思维区别;如果不能,分析原因。
int sum_digits(int n) {
if(n < 10)
return n;
}
return sum_digits(n/10) + n%10
A2:能够实现相同的输出结果。区别在于原代码采用的是迭代算法,通过while循环不断对数字取余和整除,累加求和。修改后的代码采用的是递归算法,它将原问题分解为求最后一位数字加上剩余位数字之和的子问题,通过函数调用自身来解决,直到当数字小于10时直接返回数字本身。
实验任务3
1.源代码
#include <stdio.h>
int power(int x, int n); // 函数声明
int main() {
int x, n;
int ans;
while (printf("Enter x and n: "), scanf("%d%d", &x, &n) != EOF) {
ans = power(x, n); // 函数调用
printf("n = %d, ans = %d\n\n", n, ans);
}
return 0;
}
// 函数定义
int power(int x, int n) {
int t;
if (n == 0)
return 1;
else if (n % 2)
return x * power(x, n - 1);
else {
t = power(x, n / 2);
return t * t;
}
}
2.运行结果

3.Q&A
Q1:函数power的功能是什么?
A1:计算x的n次幂
Q2:函数power是递归函数吗?如果是,找出递归模式。写出这个递归模式对应的数学公式模型。
A2:是一个递归函数
实验任务4
1.源代码
#include <stdio.h>
int classify_triangle(int a, int b, int c);
int main() {
int a, b, c, type;
while (scanf("%d %d %d", &a, &b, &c) != EOF) {
type = classify_triangle(a, b, c);
switch (type) {
case 0: printf("不能构成三角形\n\n"); break;
case 1: printf("普通三角形\n\n"); break;
case 2: printf("等边三角形\n\n"); break;
case 3: printf("等腰三角形\n\n"); break;
case 4: printf("直角三角形\n\n"); break;
}
}
return 0;
}
int classify_triangle(int a, int b, int c) {
if (a + b <= c || a + c <= b || b + c <= a) {
return 0;
}
if (a == b && b == c) {
return 2;
}
if (a == b || b == c || a == c) {
return 3;
}
if (a * a + b * b == c * c || a * a + c * c == b * b || b * b + c * c == a * a) {
return 4;
}
return 1;
}
2.运行结果

实验任务5
1.源代码
迭代
#include <stdio.h>
int func(int n, int m);
int main() {
int n, m;
int ans;
while (scanf("%d%d", &n, &m) != EOF) {
ans = func(n, m);
printf("n=%d, m=%d, ans=%d\n\n", n, m, ans);
}
return 0;
}
int func(int n, int m) {
if (m == 0 || n == m) return 1;
long long ans = 1;
for (int i = 1; i <= m; i++) {
ans = ans * (n - i + 1) / i;
}
return (int)ans;
}
递归
#include <stdio.h>
int func2(int n, int m);
int main() {
int n, m;
int ans;
while (scanf("%d%d", &n, &m) != EOF) {
ans = func(n, m);
printf("n=%d, m=%d, ans=%d\n\n", n, m, ans);
}
return 0;
}
int func2(int n, int m) {
if (m == 0 || n == m) {
return 1;
}
if (m > n) {
return 0;
}
return func(n - 1, m) + func(n - 1, m - 1);
}
2.运行结果
迭代

递归

实验任务6
1.源代码
#include <stdio.h>
int gcd(int a, int b, int c);
int main() {
int a, b, c;
int ans;
while (scanf("%d%d%d", &a, &b, &c) != EOF) {
ans = gcd(a, b, c);
printf("最大公约数: %d\n\n", ans);
}
return 0;
}
int gcd(int a, int b, int c) {
int min = a;
if (b < min) min = b;
if (c < min) min = c;
for (int i = min; i >= 1; i--) {
if (a % i == 0 && b % i == 0 && c % i == 0) {
return i;
}
}
return 1;
}
2.运行结果

实验任务7
1.源代码
#include <stdio.h>
#include <stdlib.h>
void print_charman(int n);
int main() {
int n;
printf("Enter n: ");
while (scanf("%d", &n) != EOF) {
printf("input n: %d\n", n);
print_charman(n);
printf("\nEnter n: ");
}
return 0;
}
void print_charman(int n) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j < i; j++) {
printf("\t");
}
for (int j = 1; j <= 2 * (n - i) + 1; j++) {
printf(" O \t");
}
printf("\n");
for (int j = 1; j < i; j++) {
printf("\t");
}
for (int j = 1; j <= 2 * (n - i) + 1; j++) {
printf(" <H> \t");
}
printf("\n");
for (int j = 1; j < i; j++) {
printf("\t");
}
for (int j = 1; j <= 2 * (n - i) + 1; j++) {
printf(" I I \t");
}
printf("\n");
}
}
2.运行结果

实验感悟
在实验任务4中,限定了三角形边长为整数,若把变量改成double类型来兼容小数,则程序大概率会出错。原因在于计算机的二进制算法在表示诸如0.1这样的小数时为0.000110011001100110011...这样的无限循环二进制数,存在截断的现象。所以为了更贴合实际,可以引入极小误差值来认为它们是在工程中相等的。在三边被判定为能够组成三角形时,可以利用海伦公式计算三角形面积。
#include <stdio.h>
#include <math.h>
#define EPSILON 1e-6
int is_equal(double x, double y) {
return fabs(x - y) < EPSILON;
}
int is_right_triangle(double a, double b, double c) {
return is_equal(a*a + b*b, c*c) ||
is_equal(a*a + c*c, b*b) ||
is_equal(b*b + c*c, a*a);
}
void analyze_triangle(double a, double b, double c) {
if (a + b <= c + EPSILON || a + c <= b + EPSILON || b + c <= a + EPSILON) {
printf("不能构成三角形\n");
return;
}
double p = (a + b + c) / 2.0;
double area = sqrt(p * (p - a) * (p - b) * (p - c));
printf("这是一个有效的三角形,面积为: %.2f\n", area);
if (is_equal(a, b) && is_equal(b, c)) {
printf("类型: 等边三角形\n");
} else if (is_equal(a, b) || is_equal(b, c) || is_equal(a, c)) {
if (is_right_triangle(a, b, c)) {
printf("类型: 等腰直角三角形\n");
} else {
printf("类型: 等腰三角形\n");
}
} else if (is_right_triangle(a, b, c)) {
printf("类型: 直角三角形\n");
} else {
printf("类型: 普通三角形\n");
}
}
int main() {
double a, b, c;
printf("请输入三角形的三边长\n");
while (scanf("%lf %lf %lf", &a, &b, &c) == 3) {
analyze_triangle(a, b, c);
printf("----------------------------------------\n");
printf("请输入三角形的三边长:\n");
}
printf("输入结束,程序退出。\n");
return 0;
}
运行结果


浙公网安备 33010602011771号