一.自定义函数
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;
}