上海海事大学自动化专业C语言课程代码参考(第九周)

听说下周开始就有线下课了,我个人还是比较期待的,希望疫情影响早日结束(拜

现在看看这周的题目吧

上机实验

4-15       找完数

本题要求编写程序,找出任意两正整数mn之间的所有完数。所谓完数就是该数恰好等于除自身外的因子之和。例如:6=1+2+3,其中1、2、3为6的因子。

输入格式:

输入在一行中给出2个正整数mn(1<mn≤10000),中间以空格分隔。

输出格式:

逐行输出给定范围内每个完数的因子累加形式的分解式,每个完数占一行,格式为“完数 = 因子1 + 因子2 + ... + 因子k”,其中完数和因子均按递增顺序给出。若区间内没有完数,则输出“None”。

输入样例:

2 30

输出样例:

6 = 1 + 2 + 3

28 = 1 + 2 + 4 + 7 + 14

完…完数?这是啥?

除自身外的因子之和……好像得找因子,看例子的话,因子应该是指这个数的因数

找因数我们之前有试过找最大公因数,找到全部因数也不麻烦。

那这道题的解题思路也比较简单了,先找到数 n 的所有因数,再全部加起来,判断就行了

(不过好像可以用查找的方法,保存一份完数表,要查询的数直接遍历表,就能简单实现。但这道题显然不是想让我们这么做

代码如下:

#include <stdio.h>

int FindFullNum(int num);
void PrintFullNum(int num);

int main()
{
    int numMin, numMax;

    scanf("%d%d", &numMin, &numMax);
    for (int i = numMin; i <= numMax; i++)
    {
        if(FindFullNum(i))
        {
            PrintFullNum(i);
        }
    }

    return 0;
}

int FindFullNum(int num)
{
    int sum = 0;
    for (int i = 1; i < num; i++)
    {
        if(num % i == 0)
        {
            sum += i;
        }
    }
    if(sum == num)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void PrintFullNum(int num)
{
    printf("%d = ", num);
    for (int i = 1; i < num; i++)
    {
        if(num % i == 0)
        {
            printf("%d + ", i);
        }
    }
    printf("\b\b  \n");
}

可能看起来有点多,因为我在这里用了自定义函数,占篇幅会更多一些,但是结构会更清楚一些

(要不咱给每个函数加个注释?

注意最后一句的 "\b\b  \n" 是有两个空格的,这是为了将最后的 '+' 给擦除。

4-16      求e的近似值

本题要求编写程序,计算自然常数 ee 可以用级数 1+1/1!+1/2!+⋯+1/n!+⋯ 来近似计算。本题要求对给定的非负整数 n,求该级数的前 n+1项和。

输入格式:

输入第一行中给出非负整数 n(≤1000)。

输出格式:

在一行中输出部分和的值,保留小数点后八位。

输入样例:

10

输出样例

2.71828180

又是阶乘,上周的手下败将罢了(doge

这题直接嵌套两个循环就可以,不过我们来试试写自定义函数实现

代码如下:

#include <stdio.h>

float OnePartFacN(int num);


int main()
{
    int num;
    float sum = 1;

    scanf("%d", &num);
    for (int i = 1; i <= num; i++)
    {
        sum += OnePartFacN(i);
    }
    printf("%.8f", sum);

    return 0;
}

/**
 * @brief 计算N分之一的阶乘
 *
 * @param num
 * @return float
 */
float OnePartFacN(int num)
{
    float sum = 1;
    for (int i = 1; i <= num; i++)
    {
        sum *= 1 / (float)i;
    }
    return sum;
}

代码有了注释就有了灵魂(确信

4-17       作品评分

本题要求编写程序,全国中小学生Scratch作品大赛拉开了序幕。每个参赛选手可以通过网络直接上传作品。本次比赛人人可做评委。每个网络评委可以通过网络对每一件作品进行打分。评分系统也是请程序高手设计的,能自动去掉一个最高分和一个最低分,求出平均分。

输入格式:

输入数据包括两行: 第一行为n,表示n个评委,n>2。第二行是n个评委的打分,分数之间有一个空格。打分是可以带有小数部分的。

输出格式:

输出平均分,结果保留两位小数。

输入样例:

6

10 9 8 7.9 9 9.5

输出样例:

8.8

哇哦,Scratch作品大赛。真羡慕城里人(

咳咳,言归正传,这一题有点麻烦。最难的地方不在排序,而在如何分配内存,让这些不定长输入的评分都能存进计算机内。

可能你会疑惑了,不定长的输入我们之前不是做过几次了吗,为什么会在这里才遇到这种问题呢?

因为之前几次虽然是不定长输入,但是都是只需要保存一个值就够了,而现在的情况是所有值都要保存,这要么要用数组,要么得用指针,但这显然我们都没学过。

果然是像题目中说的,是 “请程序高手设计的” ?

………思考中………

仔细一想,我们并不需要每个值都单独存起来,所以并不需要考虑如何分配内存,一股脑全部加起来然后减去最大和最小就好了!(妙极了

所以代码如下:

#include <stdio.h>

float maxNum(float a, float b);
float minNum(float a, float b);

int main()
{
    int num;
    float val, sum = 0, max = 0, min = 10;
    scanf("%d", &num);
    for (int i = 0; i < num; i++)
    {
        scanf("%f", &val);
        sum += val;
        max = maxNum(max, val);
        min = minNum(min, val);
    }
    printf("%.2f", (sum - max - min) / (num - 2));

    return 0;
}

/**
 * @brief 返回两个数的最大值
 *
 * @param a
 * @param b
 * @return float
 */
float maxNum(float a, float b)
{
    if(a > b)
        return a;
    else
        return b;
}

/**
 * @brief 返回两个数的最小值
 *
 * @param a
 * @param b
 * @return float
 */
float minNum(float a, float b)
{
    if(a > b)
        return b;
    else
        return a;
}

4-18      特殊a串数列求和

本题要求编写程序,给定两个均不超过9的正整数an,要求编写程序求a+aa+aaa++⋯+aaana)之和。

输入格式:

输入在一行中给出不超过9的正整数an

输出格式:

在一行中按照“s = 对应的和”的格式输出。

输入样例:

2 3

输出样例:

s = 246

这个是生成类似 2 22 222这样的数,比较简单

直接看代码:

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

int CyclesNum(int a, int b);

int main()
{
    int num, powNum, sum = 0;
    scanf("%d%d", &num, &powNum);
    for (int i = 0; i < powNum; i++)
    {
        sum += CyclesNum(num, i + 1);
    }
    printf("s = %d", sum);

    return 0;
}

/**
 * @brief 生成循环数
 *
 * @param a
 * @param b
 * @return int
 * @example 222 == CyclesNum(2, 3);
 */
int CyclesNum(int a, int b)
{
    int sum = 0;
    for (int i = 0; i < b; i++)
    {
        sum += a * (int)pow(10, i);
    }
    return sum;
}

4-19      打印菱形图案

本题要求编写程序,打印一个高度为n的、由“*”组成的正菱形图案。

输入格式:

输入在一行中给出一个正的奇数n

输出格式:

输出由n行星号“*”组成的菱形,如样例所示。每个星号后跟一个空格。

输入样例:

7

输出样例:

      *
    * * *
  * * * * *
* * * * * * *
  * * * * *
    * * *
      *

这题思路很多,我这里用一种比较简单的思路

首先输入 n,循环 n 次,每次循环的时候嵌套 n 次的循环。在第 i 行的时候,从(n + 1)/ 2 - i 开始打印 2i - 1 个 ‘*’,其余的打印空格就可以,这样可以打印完上面的三角形;下面的三角形只需要将 i 改为 (n - i)就可以了

代码如下:

#include <stdio.h>

int main()
{
    int num;
    scanf("%d", &num);
    for (int i = 1; i <= num; i++)
    {
        for (int j = 1; j <= num; j++)
        {
            if(i <= (num + 1) / 2)
            {
                if (j > (num + 1) / 2 - i && j <= (num + 1) / 2 + i - 1)
                    printf("*");
                else
                    printf(" ");
            }
            else
            {
                if (j >= (num + 1) / 2 - (num - i) && j <= (num + 1) / 2 + (num - i))
                    printf("*");
                else
                    printf(" ");
            }
        }
        printf("\n");
    }

    return 0;
}

4-20       打印九九口诀表

本题要求对任意给定的一位正整数N,输出从1*1N*N的部分口诀表。

输入格式:

输入在一行中给出一个正整数N(1≤N≤9)。

输出格式:

输出下三角N*N部分口诀表,其中等号右边数字占4位、左对齐。

输入样例:

4

输出样例:

1*1=1   
1*2=2   2*2=4   
1*3=3   2*3=6   3*3=9   
1*4=4   2*4=8   3*4=12  4*4=16

拜托,打印一个九九乘法表超酷的好不好!

言归正传,这个表还是很简单的,比上面打印菱形简单,直接看代码吧

#include <stdio.h>

int main()
{
    int num;
    scanf("%d", &num);
    for (int i = 1; i <= num; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            printf("%d * %d = %d\t", i, j, i * j);
        }
        printf("\n");
    }

    return 0;
}

4-21    素数和

本题要求编写程序,现在,给定两个整数n和m,0<n<=m<=200,计算第n个素数到第m个素数之间所有的素数的和,包括第n个素数和第m个素数。我们认为2是第一个素数,3是第二个素数,5是第三个素数,依次类推。

输入格式:

两个整数,第一个表示n,第二个表示m。

输出格式:

一个整数,表示第n个素数到第m个素数之间所有的素数的和,包括第n个素数和第m个素数。

输入样例:

2 4

输出样例:

15

啊?素数和?查表就行了(bushi

言归正传,查素数咱之前有做过,就从2开始取模判断就好了。直接看代码吧:

#include <stdio.h>

int IsPrimeNum(int num);

int main()
{
    int num = 0, min, max, sum = 0;
    scanf("%d%d", &min, &max);
    for (int i = 2;; i++)
    {
        if (IsPrimeNum(i))
        {
            num++;
            if (num >= min && num <= max)
            {
                sum += i;
            }
            else if (num > max)
            {
                break;
            }
        }
    }
    printf("%d", sum);

    return 0;
}

/**
 * @brief 判断传入的数是否为素数
 *
 * @param num
 * @return int / bool
 */
int IsPrimeNum(int num)
{
    for (int i = 2; i < num; i++)
    {
        if (num % i == 0)
            return 0;
    }
    return 1;
}

4-22     念数字

输入一个整数,输出每个数字对应的拼音。当整数为负数时,先输出fu字。十个数字对应的拼音如下:

0: ling
1: yi
2: er
3: san
4: si
5: wu
6: liu
7: qi
8: ba
9: jiu

输入格式:

输入在一行中给出一个整数,如:1234

提示:整数包括负数、零和正数。

输出格式:

在一行中输出这个整数对应的拼音,每个数字的拼音之间用空格分开,行末没有最后的空格。如 yi er san si

输入样例:

-600

输出样例:

fuliu ling ling

行末没有空格…好麻烦,这样一来就得增加判断了

这一题主要是要将数字转化成字符,倒也不难,switch就可以

直接看代码吧:

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

int PrintNumString(int num);
int NumOrder(int num);
int SingleNum(int num, int No);

int main()
{
    int num;

    scanf("%d", &num);
    if (num < 0)
    {
        printf("fu");
        num *= -1;
    }
    for (int i = NumOrder(num); i > 0; i--)
    {
        PrintNumString(SingleNum(num, i));
        if(i != 1)
            printf(" ");
    }

    return 0;
}

/**
 * @brief 判断输入数的数量级
 *
 * @param num
 * @return int
 * @example 3 == NumOrder(200)
 */
int NumOrder(int num)
{
    int order = 0;
    for (int i = 0;; i++)
    {
        if (num / (int)pow(10, i))
            order++;
        else
            break;
    }
    return order;
}

/**
 * @brief 取出单个数
 *
 * @param num 输入数
 * @param No 位数
 * @return int
 * @example 3 == SingleNum(123, 1);
 */
int SingleNum(int num, int No)
{
    num /= pow(10, No - 1);
    return num % 10;
}

/**
 * @brief 打印数字对应的字符串
 *
 * @param num
 * @return int
 */
int PrintNumString(int num)
{
    switch (num)
    {
    case 0:
        printf("lin");
        break;
    case 1:
        printf("yi");
        break;
    case 2:
        printf("er");
        break;
    case 3:
        printf("san");
        break;
    case 4:
        printf("si");
        break;
    case 5:
        printf("wu");
        break;
    case 6:
        printf("liu");
        break;
    case 7:
        printf("qi");
        break;
    case 8:
        printf("ba");
        break;
    case 9:
        printf("jiu");
        break;
    default:
        break;
    }
}

代码看着很唬人,其实只用看main里面就行

结语

最近的作业渐渐麻烦起来了

这周的代码开始尽可能将部分功能作为函数独立出来,这样以后需要的话直接复制过去就行,非常方便;而且在看代码的时候结构也更加清晰,只看函数名就知道功能

虽然一看上去代码量多了不少,十几行能完成的愣是写成了几十行,但这是模块化的代价,能接受。看代码的时候并不需要完全看完,只看main也能了解整体思路

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值