【C语言】用函数实现模块化程序设计

前言:如果把所有的程序代码都写在一个主函数(main函数)中,就会使主函数变得庞杂、头绪不清,使阅读和维护程序变得困难。此外,有时程序中要多次实现某一功能,如果重新编写实现此功能就会使得程序冗长、不精炼。

💖 博主CSDN主页:卫卫卫的个人主页 💞

👉 专栏分类:C程序设计谭浩强版本 👈

💯代码仓库:卫卫周大胖的学习日记💫

💪关注博主和博主一起学习!一起努力!


目录


怎样定义函数

为什么要定义函数

C语言要求,在程序中所用到的所有函数,必须"先定义,后使用"。例如max函数去求两个数的较大者,必须事先先按规范对它进行定义,指定它的名字、函数返回值类型、函数实现的功能以及参数的个数与类型,将这些信息通知编译系统。这样,在程序执行max时,编译系统就会按照定义时所指定的功能执行。如果事先不定义,编译系统怎么能知道max是什么、要实现什么功能。

定义函数应包括以下几个内容

  1. 指定函数的名字,以便以后按名调用
  2. 指定函数的类型,即函数的返回值类型
  3. 指定函数的参数的名字和类型,以便在调用函数时向它们传递数据。对无参函数不需要这项。
  4. 指定函数应当完成什么操作,也就是函数是做什么的,即函数的功能。这是最重要的,是在函数体中解决的。

定义函数的方法

  1. 定义无参函数

注:函数名后面括号内的void 表示" ",即函数没有参数。

函数体内包括声明部分语句部分


  1. 定义有参函数
    类型名 函数名()
    {
    函数体
    }
    函数体包括声明部分和语句部分


    类型名 函数名(void)
    {
    函数体
    }

以下定义的max函数是有参函数:

c 复制代码
int max(int x,int y)
{
	int z;    //声明部分
	z = x > y? x:y;
	return z;

类型名 函数名(形式参数列表)
{
函数体
}
函数体包含声明部分和语句部分


  1. 定义空函数
c 复制代码
void dummy()  //类型名:void,函数名:dummy
{}

调用函数

函数调用的形式

函数调用一般形式为:
函数名(实参列表)

  1. 函数调用语句
    把函数调用单数作为一个语句。例如:
c 复制代码
void print()
{
	printf("***********\n");
}
int main()
{
	print();//此时函数不带回任何值
	return 0;
}
  1. 函数表达式
    函数调用出现在另一个表达式中,例如c=max(a,b); max(a,b) 是一次函数调用,它是赋值表达式的一部分。这时函数带回一个确定的值以参加运算。例如:
c 复制代码
c = max(a,b);//将a和b中的较大值赋给c值

3.函数参数

函数调用作为另一个函数调用时的实参。例如:

c 复制代码
m = max(a,max(b,c));//将b,c中的较大值与a比较,在将他们的最大值赋值给m

函数调用时的数据传递

1.形式参数和实际参数

在调用有参函数时,主调函数和被调用函数之间有数据传递关系。从前面已知:在定义函数时函数名后面括号中的变量名称为"形式参数 "(简称形参)或"虚拟参数 "。在主函数中调用一个函数时,函数名后面括号中的参数称为"实际参数 "(简称实参)。实际参数可以是常量、变量或表达式。

  1. 实际参数和形参间的数据传递

在调用函数的过程中,系统会把实参的值传递给被调用函数的形参。或者说,形参从实参得到了一个值。该值在函数调用期间有效,可以参加该函数的运算。


例题:输入两个整数,要求输出其中值较大者。要求用函数来找到大数。

c 复制代码
int Max(int x, int y)
{
	return x > y ? x : y;
}
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	int ret = Max(a, b);
	printf("max = %d\n", ret);
	return 0;
}

运行结果:


函数调用的过程

  1. 在定义函数中指定的形参,在未出现函数调用时,它们并不占内存中的存储单元。在发生函数调用时,函数max的形参才被临时分配内存单元。可以通俗的理解成,形参是对实参的一份临时拷贝。
  2. 将实参的值传递给对应的形参。
  3. 在执行max函数期间,由于形参已经有值,就可以利用形参进行有关的运算。
  4. 通过return语句将函数值带回主调函数。且应当注意返回值的类型与函数类型一致。如果函数不需要返回值,则不需要return语句。这时函数的类型定义为void类型。
  5. 调用结束,形参单元被释放。注意:实参单元仍保留并维持原值,没有改变。

函数的返回值

通常,希望通过函数调用使用主调函数能得到一个确定的值,这就是函数值(函数的返回值)。

  1. 函数的返回值是通过函数中的return语句获得的。
  2. 函数值的类型。既然函数有返回值,这个值当然应属于某一个确定的类型,应当在定义函数时指定函数值的类型。
  3. 在定义函数时指定的函数类型一般应该和return语句中的表达式一致。

习题练习

例题1:写两个函数分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数并输出结果。

c 复制代码
int common_divisor(int x, int y)
{
	int max = x > y ? x : y;
	int min = x < y ? x : y;
	while (min)
	{
		if (x % min  == 0 && y % min == 0)//将它们两个数的较小的数往下除
		{
			return min;
		}
		min--;
	}
}
int common_multiple(int x, int y)
{
	int n = 1;
	while (n * x % y != 0)//最小公倍数一定是他们两个的倍数
	{
		n++;
	}
	return n * x;
}
int main()
{
	int num1 = 0;
	int num2 = 0;
	scanf_s("%d %d", &num1, &num2);
	int divisor = common_divisor(num1, num2);//最大公约数
	int multiple = common_multiple(num1, num2);//最小公倍数
	printf("divisor = %d multiple = %d\n", divisor,multiple);
	return 0;
}

运行结果:


例题2:写一个判素数的函数,在主函数输入一个整数,输出是否为素数的信息。

c 复制代码
void prime_number(int x)//素数只有1和它本身能被整除
{
	int flag = 0;
	int i = 0;
	if (x == 1)//如果该数是1就直接返回素数
	{
		printf("是素数\n");
	}
	else if (x == 0)//是0就返回不是
	{
		printf("不是素数\n");
	}
	else
	{
		for (i = 2; i < x; i++)//从2开始到它本身看是否有能被整除的数
		{
			if (x % i == 0)
			{
				flag = 1;
				break;
			}
		}
		if (flag)
		{
			printf("不是素数\n");
		}
		else
		{
			printf("是素数\n");
		}
	}
}
int main()
{
	int n = 0;
	scanf_s("%d", &n);
	prime_number(n);
	return 0;
}

运行结果:


例题3:写一个函数,使输入的一个字符串按反序存放,在主函数中输入和输出字符串。

c 复制代码
void reverse_arr(char* str, int len)//逆序字符串
{
	char* left = str;//保存左边的地址
	char* right = str + len - 1;//保存右边的地址
	while (left < right)//两两进行交换
	{
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}
int main()
{
	char arr[100] = { 0 };
	gets(arr);
	printf("initial:%s\n", arr);
	int len = strlen(arr);
	reverse_arr(arr,len);
	int i = 0;
	printf("reverse:%s\n", arr);
	return 0;
}

运行结果:


结语:今天的内容就到这里吧,谢谢各位的观看,如果有讲的不好的地方也请各位多多指出,作者每一条评论都会读的,谢谢各位。
🫵🫵🫵 祝各位接下来好运连连 💞

相关推荐
万物得其道者成9 分钟前
React Zustand状态管理库的使用
开发语言·javascript·ecmascript
学步_技术14 分钟前
Python编码系列—Python抽象工厂模式:构建复杂对象家族的蓝图
开发语言·python·抽象工厂模式
wn53138 分钟前
【Go - 类型断言】
服务器·开发语言·后端·golang
Hello-Mr.Wang1 小时前
vue3中开发引导页的方法
开发语言·前端·javascript
救救孩子把1 小时前
Java基础之IO流
java·开发语言
WG_171 小时前
C++多态
开发语言·c++·面试
宇卿.1 小时前
Java键盘输入语句
java·开发语言
Amo Xiang1 小时前
2024 Python3.10 系统入门+进阶(十五):文件及目录操作
开发语言·python
friklogff1 小时前
【C#生态园】提升C#开发效率:深入了解自然语言处理库与工具
开发语言·c#·区块链
重生之我在20年代敲代码2 小时前
strncpy函数的使用和模拟实现
c语言·开发语言·c++·经验分享·笔记