对函数的认识

目录

1.函数是什么?

2.C语言中函数的分类

2.1库函数

2.2自定义函数

3.函数的参数

3.1实际参数(实参)

3.2形式参数(形参)

4.函数调用

4.1传值调用

4.2传址调用

4.3练习

5.函数的嵌套调用和链式访问

5.1嵌套调用

5.2链式访问

6.函数的声明和定义

6.1函数声明

6.2函数定义

7.函数递归

7.1什么是递归

7.2递归的两个必要条件

7.3递归与迭代

7.3.1练习1:

7.3.2练习2:



1.函数是什么?

y=f(x)这是数学中的函数。在C语言中的函数是:子程序。

子程序是大型程序中的某部分代码,由一个或多个语句块组成,它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性一般有输入参数并有返回值可以没有),提供对过程的封装和细节的隐藏。这些代码通常被集成软件库。

2.C语言中函数的分类

  • 1.库函数
  • 2.自定义函数 

库函数是C语言本身提供给我们可以直接使用的函数,比如说printf()函数,strlen()函数,system()函数,strcmp()函数等都是库函数。

自定义函数是自己创造实现的一种函数。

2.1库函数

为什么会有库函数呢?

支持可移植性(跨平台性)和提高程序的效率,把常用的函数提供给我们使用。

怎么学习库函数呢?

学习网址:(电脑端)

​​​​​​Reference - C++ Reference (cplusplus.com)

cppreference.com

C语言常用的库函数有:

  • IO函数:输入输出函数(如scanf、printf、getchar、putchar)
  • 字符串操作函数:与字符串相关的(如strcmp)
  • 字符操作函数
  • 时间/日期函数
  • 数学函数
  • 其他库函数

使用库函数,必须包含#include对应的头文件。

如一个库函数:1.strlen()(函数名)

size_t strlen ( const char * str );

Get string length

strlen()函数的参数是:const char * str;返回类型是:size_t

作用是:获取字符串长度,返回的是无符号整型(size_t)

即使用时是:传一个字符串给它(放在它的括号里),然后再把它的返回值((size_t)类型)接收一下。

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abc";
	int len = strlen(arr);//返回值保存起来放到len里
	printf("%d", len);
	//printf("%s",len)是错误的。返回的值是打印的值,是整型。
	return 0;
}//3

更标椎的写法:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abc";
	size_t len = strlen(arr);
	printf("%u", len);
	return 0;
}//3
//因为size_t—>unsigned int 
//打印无符号字符串时用%u

所以:

%d——打印有符号整数,能打印出正负;

%u——打印无符号整数,打印正数。

2.strcpy库函数——功能是:拷贝一个字符串

char *strcpy( char *strDestination, const char *strSource );

                                         目的地                                 源头

char *是一种指针,即strcpy的参数是两个指针:strDestination和strSource

返回类型也是char *也是一种指针。

指针存放的是地址。所以传的参数是地址。

即意思是:把源头拷贝到目的地中。

返回的是:目的地,即返回的是目标字符串

strDestination是目的地字符串,strSource 是源字符串

在文档中看到的Null表达的意思是\0

#include<stdio.h>
#include<string.h>
int main()
{
	//把arr2中内容拷贝到的arr1
	char arr1[20] = {0};//目的地
	char arr2[] = "HELLO";//源数据
	strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}//HELLO

3.memset库函数——功能为一个指针设置内存

void *memset( void *dest, int c, size_t count );

void *dest:dest是设置内存块的起始位置即目的地,指向目的地的指针dest。要设置哪个空间,初始化哪个空间dest就是谁。

int c:c是设置的字符

size_t count :count是设置字符的个数 

即函数的意思是:把从dest位置开始向后的count个字节的内容初始化我们想要的c里放的字符。

函数返回的是:dest

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "hello world";
	//把hello改成xxxxx,h开始,就是目的地
	memset(arr,'x',5);
	printf("%s", arr);
	//先把arr传过去,数组名代表的是数组首个元素(h)的地址,要改成x字符,把x传过去,要改5个字符。
	return 0;
}//xxxxx world

注意:int c是整型,这里传的是字符x,因为字符本身是ASCII值。

4、scanf()函数

scanf()函数在读取正常的时候会返回有效数字1(因为只读一个数字);在读取失败的时候会返回EOF,利用这个特点可以写多组输入。

(OJ在线判题中题型分为I/O型和接口型,这两种都又分为一组输入和多组输入,大多是多组输入。接口型只需完成规定的函数就可以了)。

如果scanf()返回的结果不等于EOF,说明读取正常。

//判断整数奇偶性——一组输入(只能输入一个判断一个)
#include <stdio.h>
int main()
{
	int m = 0;
	scanf("%d", &m);
	if (m % 2 == 1)
	{
		printf("Odd\n");
	}
	else
	{
		printf("Even\n");
	}
	return 0;
}
//判断整数奇偶性——多组输入(可以输入多个判断多个)
#include <stdio.h>
int main()
{
	int m = 0;
	while (scanf("%d", &m) != EOF)
	{
		if (m % 2 == 1)
		{
			printf("Odd\n");
		}
		else
		{
			printf("Even\n");
		}
	}
	return 0;
}

有些编译器下可以Ctrl+z结束循环。

EOF——end of file的缩写,文件的结束标志,一般放在文件末尾,作为文件的结束标志而存在的。scanf()函数本身读取失败的时候会返回EOF。

 多组输入还可以写成~的形式:

#include <stdio.h>
int main()
{
	int m = 0;
	while (~scanf("%d", &m))
	{
		if (m % 2 == 1)
		{
			printf("Odd\n");
		}
		else
		{
			printf("Even\n");
		}
	}
	return 0;
}

因为:

EOF的本质是-1
-1的在内存中存储的补码是:11111111111111111111111111111111
~EOF是:00000000000000000000000000000000(~是取反)
全0为假,即不会进入循环。
这种写法也对,说明当scanf()函数返回的结果是EOF时循环就停下。

借此题再看一道例题:判断是元音还是辅音

——输入描述:多组输入,每行输入一个字母。

——输出描述:针对每组输入,输出为一行,如果输入字母是元音(包括大小写),输出“Vowel”,如果输入字母是非元音,输出“Consonant”。

#include <stdio.h>
int main()
{
	char ch = 0;
	char v[] = { 'a','A','e','E','i','I','o','O','U','u' };
	while (~scanf("%c", &ch))
	{
		//遍历数组
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			if (ch == v[i])
			{
				printf("Vowel\n");
				break;
			}
		}
		if (i == 10)
		{
			printf("Consonant\n");
		}
		//清理缓冲区中的\n
		getchar();
	}
	return 0;
}

注意:无论是scanf()函数还是getchar()函数他们在读取数据的时候是从缓冲区读的,在键盘和函数之间还放了一个缓冲区。

scanf在读取字符的时候,为了让它读取在输入数字(例如输入了a)后面还敲了\n,而scanf()函数只读取%c一个字符,当敲了一个a和\n的时候,a拿走放进ch里处理会打印Vowel,当下一次sxanf()读取的时候,缓冲区还有\n,scanf就把\n拿走了,\n放到ch里,\n不是元音字母还会打印Consonant,即\n会干扰打印结果。所以需要清理掉\n,即用getchar()函数把刚刚留下的\n拿走,达到清理缓冲区的作用。

或者:

while (~scanf("%c", &ch))—变成—>while (~scanf("%c\n", &ch))

#include <stdio.h>
int main()
{
	char ch = 0;
	char v[] = { 'a','A','e','E','i','I','o','O','U','u' };
	while (~scanf("%c\n", &ch))
	{
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			if (ch == v[i])
			{
				printf("Vowel\n");
				break;
			}
		}
		if (i == 10)
		{
			printf("Consonant\n");
		}
	}
	return 0;
}

%c是从缓冲区拿走一个字符,后面如果有\n,则也会把缓冲区的\n顺便拿走——这种方法仅限于拿字符的时候可以拿走\n,拿整形的时候是不起效果的。

或者:

while (~scanf("%c", &ch))—变成—>while (~scanf(" %c", &ch))

#include <stdio.h>
int main()
{
	char ch = 0;
	char v[] = { 'a','A','e','E','i','I','o','O','U','u' };
	while (~scanf(" %c", &ch))
	{
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			if (ch == v[i])
			{
				printf("Vowel\n");
				break;
			}
		}
		if (i == 10)
		{
			printf("Consonant\n");
		}
		
	}
	return 0;
}

在%c的前面加上空格,会跳过空白字符。因为\n是看不见的空白字符,跳过\n也就相当于清理掉缓冲区的\n了。第一次输入a时a前面没有空白字符,scanf()直接拿走a,\n还在缓冲区,当下一次输入字符如b时,本质是想读b,因为在b之前还留有刚刚的\n,则跳过\n直接拿b。

2.2自定义函数

自己创建的函数(程序员也是艺术家,创造函数)

自定义函数和库函数一样,有函数名,返回值类型和函数参数。但不一样的是这些都是我们自己来设计——这给程序员很大的发挥空间。

前面一个库函数的讲解:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abc";
	size_t len = strlen(arr);
//strlen是函数名,传给strlen的是它的参数arr,返回的值放到Len里面了。
	printf("%u", len);
	return 0;
}

函数的基本组成:

ret_type fun_name(paral, *)
{
	statement;//语句项
}
ret_type  函数返回类型
fun_name  函数名
paral     函数参数
大括号括的是函数体,函数体里是语句项

举例:

写一个函数可以找出两个整数中的最大值

代码展示:(用的是自定义的函数)

#include<stdio.h>
int get_max(int x, int y)
{
	int z = 0;
	z = (x > y ? x : y);
	return z;
}
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	int m = get_max(a, b);
	printf("%d\n", m);
	return 0;
}

代码讲解:

#include<stdio.h>
//a和b是两个整数,传给get_max()函数,则int x来接收,int y来接收
int get_max(int x,int y) 
{
	//当x和y的较大值找到后就需要返回——创建z变量,z求出x和y的较大值
	int z = 0;
	z = (x > y ? x : y);
	//x大于y吗?如果大于,那较大值就是x,否则就是y
	return z;
}
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	//写一个函数:get_max——获取最大值
	//get_max();算出a和b的较大值,则传进去a和b
	//get_max(a, b);找到较大值,要告诉较大值是几,则返回较大值,则把较大值放到m里去
	int m = get_max(a, b);//即get_max就把a和b的较大值找出来返回放到m中
	printf("%d\n", m);
	return 0;
}//还没有这个函数get_max,则在主函数上面创造

这里实现get_max函数时,get_max就是函数名,int x和int y是两个参数,即a和b传的就是它——这是输入操作
int z = 0;
z = (x > y ? x : y);//这两行是加工制造,最后return z;把算出的z再返回来。因为z的类型是int,所以在int get_max(int x, int y)前面写了int
所以get_max函数返回的是整型值,所以接收时也用整型来接收,所以是int m
(所以函数返回类型,函数返回值,接收值这三者是相呼应的)

上述函数只有一个语句块({}),有返回值。

如没有返回值的函数:menu()函数,只需要它打印菜单。

上述函数若x=y则返回x或y都可以,若x<=y则返回y。

#include<stdio.h>
void menu()
{
	printf("*******    1.play    *******\n");
	printf("*******    0.exit    *******\n");
}
int main()
{
	menu();
	return 0;
}//*******    1.play    *******
//*******    0.exit    *******

调用一次,在屏幕上就打印一次;

调用两次,就在屏幕上打印两次。

#include<stdio.h>
void menu()
{
	printf("*******    1.play    *******\n");
	printf("*******    0.exit    *******\n");
}
int main()
{
	menu();
	return 0;
}//*
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值