实验三

任务一

验证性实验

源码

#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. 功能是数值分数与等级转换,形参类型int,返回值类型char
  2. 有问题,此时输入一个成绩,会输出其下所有的等级。

任务二

源码

#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. 功能是将输入的数字每一位相加。
  2. 可以实现,运用了递归的算法思想,迭代自上而下,递归自下而上。

任务三

源码

#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的y次方操作。
  2. 是递归函数,有点像二分,先算偶数幂,(如果有)最后乘以落单的最后一个x。

$$\qquad\; n个$$ $$x^n= \overbrace{\underline{\underline{\underline{x*x}*\underline{x*x}}*·\underline{·\underline{·*x}}}*\underline{x}} $$


or

\[\qquad x^n= \begin{cases} x * x^{n-1} &n为奇数;\\ (x^2)^{\frac n2}&n为偶数;\\ 1&n=0. \end{cases} \]


关于MarkDownLaTeX语法

任务四

打印100以内的孪生素数

源码

#include <stdio.h>

int isprime(int n)
{
    if (n < 2)
        return 0;
    for (int i = 2; i <= n / 2; i++)
    {
        if (n % i == 0)
            return 0;
    }
    return 1;
}

int main()
{
    int cnt = 0;
    for (int i = 1; i < 101; i += 2)
    {
        if (isprime(i)&&isprime(i + 2))
        {
                printf("%d %d\n", i, i + 2);
                cnt++;
        }
    }
    printf("Total count: %d\n", cnt);
    //不输出中文的原因是控制台和编辑器编码不同但我不想改了
    return 0;
}

结果

任务五

对教材「例4.9 Hanoi塔问题」稍做改写

源码

法一

#include <stdio.h>

int hanoi(int n, char from, char to, char via)
{
    if (n == 1)
    {
        printf("1 : %c -> %c\n", from, to);
        return 1;
    }

    int cnt = hanoi(n - 1, from, via, to) + 1;
    printf("%d : %c -> %c\n", n, from, to);
    cnt += hanoi(n - 1, via, to, from);

    return cnt;
}

int main()
{
    int n;
    char from, to, via;
    while (scanf("%d", &n) != EOF)
    {
        getchar();
        scanf("%c %c %c", &from, &via, &to);

        int cnt = hanoi(n, from, to, via);
        printf("Total moves: %d\n\n", cnt);
    }

    return 0;
}

法二

//从AI那里拿的,有空修修把它搞懂
#include <stdio.h>

void move(int from, int to) {
    printf("将盘子从柱子 %d 移动到柱子 %d\n", from, to);
}

void hanoi(int n, int a, int b, int c) {
    // n:盘子的数量
    // a:源柱子
    // b:辅助柱子
    // c:目标柱子

    int totalMoves = (1 << n) - 1; // 总移动次数
    int i;

    // 通过奇偶判断选择柱子之间的移动
    for (i = 1; i <= totalMoves; i++) {
        if (i % 3 == 1) {
            // 从 a 移到 c
            move(a, c);
        } else if (i % 3 == 2) {
            // 从 a 移到 b
            move(a, b);
        } else if (i % 3 == 0) {
            // 从 b 移到 c
            move(b, c);
        }

        // 交换柱子
        if (n % 2 == 0) {
            if (i % 3 == 1) {
                // 当 n 为偶数时,前两个柱子是 b 和 c
                // 将 a 移到 b 或 c 时,先进行一次互换
                move(b, c);
            }
        }
    }
}

int main() {
    int n;
    printf("请输入盘子的数量: ");
    scanf("%d", &n);

    // 源柱子为 1,辅助柱子为 2,目标柱子为 3
    hanoi(n, 1, 2, 3);

    return 0;
}

三种非递归算法

结果

任务六

计算组合数 $ C_n^m$

源码

#include <stdio.h>

int func(int n, int m); // 函数声明

int main()
{
    int n, m;
    int ans;

    while (scanf("%d%d", &n, &m) != EOF)
    {
        if (n<m)
        {
            printf("n = %d, m = %d, ans = 0\n\n", n, m);
            continue;// n > m 的检查在这里
        }
        
        ans = func(n, m); // 函数调用
        printf("n = %d, m = %d, ans = %d\n\n", n, m, ans);
    }

    return 0;
}

迭代

// 函数定义
int func(int n, int m)
{
    int ans = 1;
    for (int i = 0; i < m; i++)
    {
        ans *= n--;
    }
    for (int i = 1; i <= m; i++)
    {
        ans /= i;
    }
    return ans;
}

递归一

// 函数定义
int factorial(int n)
{
    if (n == 1)
        return 1;
    else
        return n * factorial(n - 1);
}

int func(int n, int m)
{
    return factorial(n) / factorial(m) / factorial(n - m);
}

递归二

// 函数定义
int func(int n, int m)
{
    if (m == n || m == 0)
        return 1;
    else
        return func(n - 1, m) + func(n - 1, m - 1);
}

结果

任务七

打印字符小人阵列

源码

#include <stdio.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 t = 0;
    for (int i = n; i >= 1; i--)
    {
        for (int j = 0; j < t; j++)
            printf("\t");
        for (int j = 0; j < 2 * i - 1; j++)
            printf(" o\t");
        printf("\n");
        for (int j = 0; j < t; j++)
            printf("\t");
        for (int j = 0; j < 2 * i - 1; j++)
            printf("<H>\t");
        printf("\n");
        for (int j = 0; j < t; j++)
            printf("\t");
        for (int j = 0; j < 2 * i - 1; j++)
            printf("I I\t");
        printf("\n");

        t++;
    }
}

结果

posted @ 2024-10-23 17:33  Churk  阅读(145)  评论(5编辑  收藏  举报