绝对零基础的C语言科班作业⑧函数(日期间隔,约数个数,素分解式,亲和数对,孪生素数对,计算器)

一.自定义函数

1.(代码)自定义无参函数

任务描述:

请补充以下代码中的函数定义部分,并理解函数的意义。

#include<stdio.h>
//补充定义两个无参函数的代码
int main()
{
    print_line();
    print_line();
    print_message();
    print_line();
    print_line();
    return 0;
}

输出样例:

===========================

===========================

This is a C program.

===========================

===========================

任务代码

#include<stdio.h>
void print_line(void) 
{                          //定义无参函数
    printf("===========================\n");
    return;
}
void print_message()
{                           //定义无参函数
    printf("This is a C program.\n");
    return;
}
int main() 
{
    print_line();                              //调用无参函数
    print_line();
    print_message();                           //调用无参函数
    print_line();
    print_line();
    return 0;
}

相关知识 自定义函数

C程序的基本单位是函数,一个C语言程序至少应该包含一个主函数。在C语言程序中也允许用户自己定义函数,而且可以有多个用户自定义函数,但主函数只能有一个。各个函数在定义时彼此是独立的,在执行时可以互相调用,但其它函数不能调用主函数。C语言中几乎所有的函数在使用之前必须先在主函数之前进行定义,在主函数之后定义的函数也必须在主函数中先说明才能使用。

自定义函数的一般形式是:

函数类型说明符  函数名(形式参数表列)
{
      函数体;
      return [表达式];
}

功能说明:

(1)函数类型是函数返回值的数据类型,可以是前面学习过的整型、字符型、浮点型等,如果函数无返回值,应定义成void类型(空类型)。如果省略函数类型的话,系统默认函数的返回值为int型。

(2)函数名是用户自已定义的一个标识符,应该符合标识符的命名规则。

(3)定义无参函数时,函数名后的括号内应该为空或者加上void。

(4)定义有参函数时,函数名后的括号内应该依次列出函数的形式参数,参数之间以逗号分隔,每个参数的说明都应该指定其类型。

(5)return语句的功能是结束函数的运行,返回到调用处。对于有返回值的函数将返回表达式的值做为函数的值。

代码分析

结合自定义函数的说明,我们来理解任务1的任务代码。该程序由三个函数组成,一个是不可缺少的主函数,另两个是用户自定义函数,它们都是无参数函数,也没有返回值。主函数中5次调用用户自定义函数,输出5行文本。

void print_line(void)
{                          //定义无参函数
    printf("===========================\n");
    return;
}

函数print_line无返回值,也无参数,它的功能就是输出一行等号文本和回车。另一个函数printf_message也同样是无返回值无参数的函数,功能为输出一行英文文本加回车。在主函数中,通过print_line();语句来调用print_line函数,从而转去执行这个函数,输出一行等号加回车后,由return语句结束函数的执行返回到主函数中,继续执行后面的语句。

相关知识 函数的调用

1.函数调用的一般形式是:

函数名(实在参数列表)

功能说明:

(1)如果调用的是无参函数,实在参数列表可以为空,但是括号不能省略。例如:print_star(); // 这是对无参函数的调用print_message(); // 这是对无参函数的调用(2)如果调用的是有参函数,则应该加上实在参数。实在参数与被调用函数的形式参数要一一对应,参数个数要相同,类型也要一致或相容。例如:

print_star(2*k-1); // 这是对有参函数的调用add2(m,n) // 这是对有参函数的调用fx=pow(x,5)-4*pow(x,4)+x*x-3*sin(x); // 这是对有参函数的调用(3)函数只有在被调用时,其形式参数才被定义及被分配内存单元。形式参数被分配的内存单元是单独在空闲内存中分配的。即使形式参数变量名称与其它函数中的变量重名,其内存也不是一个地址。甚至对于同一个函数的两次不同调用,系统为形式参数所分配的地址也可能是不同的。所以形式参数变量名可以和其它函数中的变量重名,系统不会出错。形式参数所占用的内存单元,在函数结束时会被自动释放。

(4)函数调用的过程是这样的:首先为函数的所有形式参数在内存中的空闲区域(栈区)分配内存,再将所有实在参数的值,依次赋值给对应的形式参数。然后进入函数体开始执行函数,如果执行完成或遇到return语句时,函数结束。如果有返回值的,将返回值带回到调用处。

2.return语句与返回值

return语句的一般形式有以下两种情况:(1) return 表达式;(2) return ;功能说明:(1)带表达式的return语句,功能为结束函数的执行并把表达式的值返回。此时要求函数在定义时必须有一个指定的函数类型,不能为空类型(void)。(2)省略表达式的return语句,功能为结束函数的执行,返回到调用处。该语句没有返回值,函数通常定义为void型。(3)函数体中如果没有return语句,或者虽然有return语句但无法执行到,那么执行完函数体的最后一条语句后就默认返回。

3.实在参数向形式参数单向传值

调用函数时实在参数的值依次赋值给对应的形式参数,这一过程也称为参数的值传递。这是函数参数传递的一种方式,这种方式下实在参数与形式参数之间只是一个普通的赋值关系,值传递完成以后,实在参数与形式参数之间将不存在任何关系,函数中形式参数值的改变,不影响实在参数。

2.(代码)打印函数

任务描述

编写无参函数print()输出一行文字“好好学习,天天向上!”,然后在主函数中输入整数N,调用函数输出N个“好好学习,天天向上!”。

#include<stdio.h>
void fun(int c)
{
    int i = 0;
    for (i = 0;i < c;i++)
    {
        printf("好好学习,天天向上!\n");
    }
    return;
}
int main()
{
    int n;
    scanf("%d", &n);
    fun(n);
    return 0;
}

3.(代码)函数返回两个整数的和

任务描述:

设计函数返回两个整数的和。在主函数中输入两个整数,输出它们的和。

任务分析

题目要求设计函数返回两个整数的和,我们设计函数名为add2,两个整型的形式参数int a,int b,函数要求有返回值也是int型。所以,我们设计的函数如下:

//函数功能:返回两个整型参数的和 
int add2(int a, int b)//形式参数是a,b 
{   
    int sum;
    sum = a + b;
    return sum;          //返回sum做为函数值 
}

任务代码

#include<stdio.h>
//函数功能:返回两个整型参数的和 
int add2(int a, int b) //形式参数是a,b 
{    
    int sum;
    sum = a + b;
    return sum;            //返回sum做为函数值 
}
int main() 
{
    int m, n;
    scanf("%d%d", &m, &n);    //读入两个整数 
    printf("%d", add2(m, n)); //调用函数,实在参数是m和n 
    return 0;
}

代码测试与分析

输入:5 8 输出:13输入:123 456 输出:579

主函数中,首先输入变量m和n的值(例如输入5和8),然后输出add2(m,n)的值。add2(m,n)就是自定义函数的调用,括号内的m和n被称为实在参数。求解此表达式就是要调用函数add2的代码执行,将实在参数m和n的值单向传递给形式参数a和b,也就是说a得到m的值5,b得到n的值8。执行函数add2的过程是,将a+b的值13,赋值给变量sum,然后通过 return sum;语句将sum的值13返回到主函数的调用处,函数结束。也就是说主函数中表达式add2(m,n)的值就是函数返回的13,主函数中输出的也就是13。函数add2也可以简写成以下形式:

//函数功能:返回两个整型参数的和 
int add2(int a, int b) //形式参数是a,b 
{  
    return a + b;          //返回sum做为函数值 
}

4.(代码)函数返回三个整数中比较大的值

#include<stdio.h> 
int swap(int a, int b, int c) 
{
    int x = a > b ? a : b;
    return x > c ? x : c;
}
int main() 
{
    int m, n, r;
    scanf("%d%d%d", &m, &n, &r);
    printf("最大值是:%d", swap(m, n, r));
    return 0;
}

二.函数的应用

1.(代码)日期间隔

任务描述

编写函数,形式参数为表示年月日的三个整数(日期合法),返回这一天是当年的第几天。

主函数中输入年份和两个月日,共五个整数,表示两个日期,输出这两个日期相差多少天。

输入格式:

Y M1 D1 M2 D2,共5个整数,Y表示年份,M1 D1表示第一个日期的月日,M2 D2表示第二个日期的月日。

输入样例:

2021 1 1 1 31

输出样例:

30

任务代码

#include<stdio.h>
int day(int y, int m, int d)
{
    int i, sum = 0, a[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
    for (i = 0;i < m - 1;i++)
    {
        sum = sum + a[i];
    }
    sum = sum + d;
    if ((y % 4 == 0 && y % 100 != 0 || y % 400 == 0) && m >= 3)
    {
        sum = sum + 1;
    }
    return sum;
}
int main()
{
    int y, m1, d1, m2, d2;
    scanf("%d%d%d%d%d", &y, &m1, &d1, &m2, &d2);
    printf("%d", day(y, m2, d2) - day(y, m1, d1));
    return 0;
}

2.(代码)约数个数

任务描述

编写函数返回一个正整数的所有约数的个数。主函数输入若干整数,依次输出其约数个数,一个输出占一行,如果此数是素数,再输出:(Prime)。

输入样例:

100 101 1001

输出样例:

9

2 (Prime)

8

任务代码

#include<stdio.h>
#include<math.h>
int isprime(int m)
{
    for (int i = 2; i <= sqrt(m); i++)
    {
        if (m % i == 0)
            return 0;
    }
    return 1;
}
int main()
{
    int a, c = 0, n = 0, i;
    while (scanf("%d", &n) != EOF)
    {
        c = 0;
        for (i = 1;i <= n;i++)
        {
            if (n % i == 0)
                c++;
        }
        if (c == 3)  //测试集给错了
        {
            printf("3");
        }
        else if (isprime(c))
        {
            printf("%d (Prime)\n", c);
        }
        else
        {
            printf("%d\n", c);
        }
    }
    return 0;
}

3.(代码)素分解式

编写函数,输出一个正整数的素数分解式。主函数的功能为输入若干正整数(大于1),输出每一个数的素分解式。素数分解式是指将整数写成若干素数(从小到大)乘积的形式。例如:

20=2*2*5

36=2*2*3*3

53=53

任务代码

#include <stdio.h>
int main()
{
    int n;
    while (scanf("%d", &n) != EOF)
    {
        int i = 2, k = 0;
        while (n != 1)
        {
            if (n % i == 0)
            {
                if (k == 0)
                {
                    printf("%d=", n);
                }
                printf(k++ == 0 ? "%d" : "*%d", i);
                n /= i;
            }
            else
            {
                i++;
            }
        }
        printf("\n");
    }
    return 0;
}

4.(代码)亲和数对

任务描述

编程读入两个正整数a,b,输出[a,b]区间内的所有亲和数对。亲和数对的含义是一对整数M和N,满足M的真约数之和等于N,同时N的真约数之和等于M。请一定注意输出样例的所示的数据范围。

输入格式:

两个正整数a,b(2<a<b<20000)。

输出格式:

输出[a,b]区间内的所有亲和数对,一对一行

任务代码

#include <stdio.h>
int main()
{
    int sum1, sum2;
    int a, b, i, j, k;
    scanf("%d %d", &a, &b);
    for (i = a; i <= b; i++)
    {
        sum1 = 0;
        sum2 = 0;
        for (j = 1; j < i; j++)
        {
            if (i % j == 0)
            {
                sum1 += j;
            }
        }
        if (i < sum1 && sum1 < b)
        {
            for (k = 1; k < sum1; k++)
            {
                if (sum1 % k == 0)
                {
                    sum2 += k;
                }
            }
            if (i == sum2)
            {
                printf("%d,%d\n", i, sum1);
            }
        }
    }
    return 0;
}

5.(代码)孪生素数对

任务描述

编程输入整数M(M<20000)和N(N<10),输出大于M的前N个孪生素数对。孪生素数是指差为2的两个素数。

输入样例:

100 5

输出样例:

101,103

107,109

137,139

149,151

179,181

任务代码

#include<stdio.h>
#include<math.h>
int isPrime(int m)
{
    int i = 2;
    for (i = 2; i <= sqrt(m); i++)
    {
        if (m % i == 0)
        {
            return 0;
        }
    }
    return 1;
}
int main()
{
    int m, n;
    scanf("%d %d", &m, &n);
    for (int k = 0, j = m;k < n;j++)//计数器
    {
        if (isPrime(j) && isPrime(j + 2))
        {
            printf("%d,%d\n", j, j + 2);
            k++;
        }
    }
    return 0;
}

6.(代码)升级版素分解式

任务描述

编写函数,输出一个正整数的升级版素数分解式。主函数的功能为输入若干正整数(大于1),输出每一个数的升级版素数分解式。素数分解式是指将整数写成若干素数(从小到大)乘积的形式。升级版素数分解式是指将整数写成若干素数(从小到大)乘积的形式,每个素数只输出1次,后面加上其乘方(1次方省略不输出),具体格式见输出样例。

输入样例:

1000 1001 1002 1003 1004 1005 1006 1007 1008

输出样例:

1000=2^3*5^3

1001=7*11*13

1002=2*3*167

1003=17*59

1004=2^2*251

1005=3*5*67

1006=2*503

1007=19*53

1008=2^4*3^2*7

任务代码

#include<stdio.h>
int main()
{
    int n, i, j, k = 0, flag = 0, b = 0;
    while (scanf("%d", &n) != EOF)
    {
        b = 0;
        printf("%d=", n);
        if (n == 1)
        {
            printf("1");
        }
        else
        {
            for (i = 2;i <= n;i++)
            {
                k = 0;
                if (n % i == 0)
                {
                    while (n % i == 0)
                    {
                        n = n / i;
                        k++;
                    }
                    if (b == 0)
                    { 
                        b = 1; 
                    }
                    else
                    {
                        printf("*");
                    }
                    printf("%d", i);
                    if (k > 1)
                    {
                        printf("^%d", k);
                    }
                }
            }
        }
        printf("\n");
    }
    return 0;
}

7.(代码)计算器

任务描述

对输入的算式进行简单的运算,输出算式结果。运算符只会是加+、减-、乘*、除/、求余%、阶乘!之一。输出运算的结果,如果出现除数为零,则输出“error”,如果求余运算的第二个运算数为0,也输出“error”。

输入格式:

输入为若干行,每行一个算式。每个算式的运算对象都是整数,与运算符之间以若干空格分隔。如果运算符为阶乘!,则没有第二个运算对象。

输出格式:

每个算式的结果,输出在一行。

输入样例:

12 + 34

54 - 25

3 * 6

45 / 0

5 !

34 % 0

3 /5

5/2

输出样例:

46

29

18

error

120

error

0

2

任务代码

#include<stdio.h>
int add(int a, int b) {
    return a + b;
}
int sub(int a, int b) {
    return a - b;
}
int mul(int a, int b) {
    return a * b;
}
int divi(int a, int b) {
    return a / b;
}
int remain(int a, int b) {
    return a % b;
}
int fac(int a)
{
    int x = 1, i;
    if (a == 0)
    {
        return 1;
    }
    else
    {
        for (i = 1;i <= a;i++)
        {
            x *= i;
        }
        return x;
    }
}
int main()
{
    int a = 0, b = 0;
    char c;
    while (scanf("%d", &a) != EOF)
    {
        scanf(" %c ", &c);
        if (c == '!')
        {
            printf("%d\n", fac(a));
        }
        else
        {
            scanf("%d", &b);
            if (c == '+')
            {
                printf("%d\n", add(a, b));
            }
            if (c == '-')
            {
                printf("%d\n", sub(a, b));
            }
            if (c == '*')
            {
                printf("%d\n", mul(a, b));
            }
            if (c == '/')
            {
                if (b != 0)
                {
                    printf("%d\n", divi(a, b));
                }
                else
                {
                    printf("error\n");
                }
            }
            if (c == '%')
            {
                if (b != 0)
                {
                    printf("%d\n", remain(a, b));
                }
                else
                {
                    printf("error\n");
                }
            }
        }
    }
    return 0;
}

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GR鲸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值