实验三

任务1

  • 源代码task1.c

点击查看代码

复制代码
#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;
}
  • 运行测试截图

  • 问题1:把分数转化成等级

  • 问题2:1.双引号是字符串常量;ans是char字符变量,字符要用单引号,否则会类型不匹配。
    2.缺少break;,会发生case穿透。匹配成功后继续执行所有分支,结果错乱。

任务二

  • 源代码

点击查看代码

复制代码
#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;
}
  • 运行截图
  • 问题1:计算并返回一个非负整数n的各数字之和。
  • 问题2:能。对于正整数的输入,结果完全一致。思维区别:原来的实现方式按照"顺序处理",每次把结果累加到ans中去,直到数字变为0.这是一种状态不断更新的过程。
    新的实现方式是"自顶而上,分而治之",是递归法。不断调用,直至达到终止条件,才开始意义返回相加。

任务三

  • 源代码

点击查看代码

复制代码
#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;
    }
}
  • 运行截图

  • 问题1:
    计算x^n(n=>0)

  • 问题2:是递归函数。递归出口:n=0,x^0=1.
    数学模型:

问题3:1.逻辑上仍然正确。数学上等价,只是写法实现方式改变了。

2.原版只调用一次power(x,n/2),保存结果再自乘,子问题只算一遍。原版power(3,16)有4次子问题求值。

修改版连续调用两次power(x,n/2),同一个子问题连续计算两遍,每一次计算量翻倍。修改版调用了47次。

任务四

  • 源代码

点击查看代码

复制代码
#include <stdio.h>

// 函数原型声明
int classify_triangle(int a, int b, int c);

int main() {
    int a, b, c;
    
    // 支持多组输入,当成功读取三个整数时继续循环
    while (scanf("%d %d %d", &a, &b, &c) == 3) {
        int result = classify_triangle(a, b, c);
        
        // 基于返回值判断,配合 if 或 switch 输出三角形类型
        switch (result) {
            case 0:
                printf("不能构成\n");
                break;
            case 1:
                printf("普通\n");
                break;
            case 2:
                printf("等边\n");
                break;
            case 3:
                printf("等腰\n");
                break;
            case 4:
                printf("直角\n");
                break;
            default:
                printf("未知类型\n");
        }
    }
    
    return 0;
}

// 判断三角形类型函数实现
int classify_triangle(int a, int b, int c) {
    // 1. 判断是否能构成三角形(三边均为正,且满足两边之和大于第三边)
    // 排序后只需判断较短两边之和是否大于最长边
    int temp;
    if (a <= 0 || b <= 0 || c <= 0) {
        return 0; // 不能构成
    }
    // 简单排序,确保 a <= b <= c
    if (a > b) { temp = a; a = b; b = temp; }
    if (b > c) { temp = b; b = c; c = temp; }
    if (a > b) { temp = a; a = b; b = temp; }
    
    if (a + b <= c) {
        return 0; // 不能构成
    }
    
    // 2. 判断具体类型
    // 直角三角形判断(勾股定理 a^2 + b^2 == c^2)
    // 注意:题目返回值中直角为4,若有特殊叠加(如等腰直角),通常优先返回直角或按题目隐含优先级
    if (a * a + b * b == c * c) {
        return 4; // 直角
    }
    
    // 等边三角形
    if (a == b && b == c) {
        return 2; // 等边
    }
    
    // 等腰三角形(恰好两边相等)
    if (a == b || b == c || a == c) {
        return 3; // 等腰
    }
    
    // 普通三角形
    return 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) {
    // 边界条件:m > n 或 m < 0 时,组合数为 0
    if (m < 0 || m > n) {
        return 0;
    }
    //C(n, m) = C(n, n-m),取较小的 m 减少循环次数
    if (m > n - m) {
        m = n - m;
    }
    // 边界条件:m = 0 或 m = n 时,组合数为 1
    if (m == 0) {
        return 1;
    }
    
    long long res = 1;
    // 使用公式:C(n, m) = n(n-1)...(n-m+1) / m(m-1)...1
    for (int i = 1; i <= m; i++) {
        res = res * (n - m + i) / i;
    }
    return (int)res;
}

// 方式二:递归方式
/*
int func(int n, int m) {
    // 边界条件(递归出口):根据测试结果 m>n 返回0,m=0或m=n返回1
    if (m < 0 || m > n) {
        return 0;
    }
    if (m == 0 || m == n) {
        return 1;
    }
    // 递归调用
    return func(n - 1, m) + func(n - 1, m - 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;
	int i;
	for(i=min;i>=1;i--)
	{
		if(a%i==0&&b%i==0&&c%i==0)
		return i;
	}
}
  • 运行测试截图

任务七

  • 源代码

点击查看代码

复制代码
#include <stdio.h>
#include <stdlib.h>

// 函数声明
void print_charman(int n);

int main() {
    int n;
    printf("Enter n: ");
    scanf("%d", &n);
    print_charman(n); // 函数调用
    return 0;
}

// 函数print_charman定义
void print_charman(int n) {
    int i, j, k;
    
    // 外层循环控制行数,从 n 递减到 1
    for (i = n; i >= 1; i--) {
        // 打印头部 " 0 "
        // 每一层前面先打印缩进空格。缩进量随着行数递减而增加。
        // 观察效果,大概每次缩进2个字符宽度
        for (k = 0; k < (n - i); k++) {
            printf("  "); 
        }
        for (j = 0; j < i; j++) {
            printf("  0  "); // 注意 0 前后的空格以匹配预览图
        }
        printf("\n");

        // 打印身体 "<H>"
        for (k = 0; k < (n - i); k++) {
            printf("  ");
        }
        for (j = 0; j < i; j++) {
            printf(" <H> ");
        }
        printf("\n");

        // 打印腿部 " I "
        for (k = 0; k < (n - i); k++) {
            printf("  ");
        }
        for (j = 0; j < i; j++) {
            printf("  I  ");
        }
        printf("\n");
    }
}
  • 运行截图