函数
1、函数是什么
函数是子程序。
在计算机科学中,子程序是一个大型程序中的某部分代码, 由一个或多个语句块组成。它负责完成某项特定任务,而且相较于其他代 码,具备相对的独立性。
一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软件库。
2、函数
函分为库函数和自定义函数
库函数包含以下几种:
IO函数 |
字符串操作函数 |
字符操作函数 |
内存操作函数 |
时间/日期函数 |
数学函数 |
其他库函数 |
3、自定义函数
自定义函数和库函数一样,有函数名,返回值类型和函数参数。 但是不一样的是这些都是我们自己来设计。这给程序员一个很大的发挥空间
1最大值函数
#include <stdio.h>
#include <stdlib.h>
int get_max(int x, int y)
{
return (x > y) ? (x) : (y);
}
int main()
{
int num1 = 10;
int num2 = 20;
int max = get_max(num1, num2);
printf("%d\n", max);
system("pause");
return 0;
}
2交换函数
#include <stdio.h>
#include <stdlib.h>
void Swap1(int x, int y)
{
int tmp = 0;
tmp = x;
x = y;
y = tmp;
}
void Swap2(int *px, int *py)
{
int tmp = 0;
tmp = *px;
*px = *py;
*py = tmp;
}
int main()
{
int num1 = 1;
int num2 = 2;
Swap1(num1, num2);
printf("Swap1::num1 = %d num2 = %d\n", num1, num2);
Swap2(&num1, &num2);
printf("Swap2::num1 = %d num2 = %d\n", num1, num2);
system("pause");
return 0;
}
4、函数参数
包含实际参数和形式参数
#实际参数:
真实传给函数的参数,叫实参。实参可以是:常量、变量、表达式、函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
#形式参数
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。
//形参实例化以后相当于实参的一份临时拷贝
5、函数调用
包含传值调用和传址调用
#传值调用
·函数的形参和实参分别占有不同的内存块,对形参的修改不会影响实参。
#传址调用
·传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
·这种传参方式可以让函数和函数外边的变量建立起联系,即函数内部可以操作函数外部的变量。
6、函数的嵌套调用和链式访问
函数嵌套调用
函数和函数之间可以有机组合
函数的链式访问
把一个函数的返回值作为另外一个函数的参数
3嵌套调用
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
//嵌套调用
void new_line()
{
printf("Hello World!\n");
}
void three_line()
{
int i = 0;
for (i = 0; i < 3; i++)
{
new_line();
}
}
int main()
{
three_line();
system("pause");
return 0;
}
4链式访问
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char arr[20] = "hello";
int ret = strlen(strcat(arr, "bit"));
printf("%d\n", ret);
system("pause");
return 0;
}
7、函数的声明
函数声明:
·告诉编译器有一个函数叫什么,参数是什么,返回值类型是什么的,但是不知道具体实现。
·函数的声明一般出现在函数的使用之前,要满足先声明后使用
·函数的声明一般要放在头文件中
5函数声明和定义
#ifndef _TEST_H_
#define _TEST_H_
//函数声明
int add(int x, int y);
#endif //_TEST_H_H
#include <stdio.h>
#include "test.h"
//函数定义
int add(int x, int y)
{
return x + y;
}
int main()
{
printf("%d\n", add(2, 3));
system("pause");
return 0;
}
8、函数递归
什么是递归:
程序调用自身的编程技巧称为递归。 递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的主要思考方式是:把大事化小。
递归的两个必要条件
·存在限制条件,当满足这个限制条件的时候,递归停止;
·每次递归调用之后越来越接近这个限制条件。
如何解决函数递归调用的栈溢出问题
·将递归函数改为非递归函数
·使用static对象代替nonstatic局部对象。(旨在减少每次递归调用和返回时产生和释放nonstatic局部对象的开销,而且static对象还可以保存递归调用的中间状态)
6函数递归1
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
//接收一个整型值(无符号),按照顺序打印它的每一位。 例如: 输入:12345678,输出 1 2 3 4 5 6 7 8.
void print(int num)
{
if (num > 9)
{
print(num / 10);
}
printf("%d ", num%10);
}
int main()
{
int num = 12345678;
print(num);
system("pause");
return 0;
}
7函数递归2
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
//函数递归实现求字符串长度
int Strlen(const char* str)
{
if (*str == '\0')
{
return 0;
}
else
{
return 1 + Strlen(str + 1);
}
}
int main()
{
char* pstr1 = "abcdef";
int len = Strlen(pstr1);
printf("%d", len);
system("pause");
return 0;
}
8函数递归3
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
//递归求n的阶乘
int factorial1(int n)
{
if (n <= 1)
{
return 1;
}
else
{
return n * factorial1(n - 1);
}
}
//非递归求n的阶乘
int factorial2(int n)
{
int res = 1;
while (n > 1)
{
res *= n;
n--;
}
return res;
}
int main()
{
printf("%d\n", factorial1(5));
printf("%d\n", factorial2(5));
system("pause");
return 0;
}
9函数递归4
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
//递归斐波那契数列
int fib1(int n)
{
if (n <= 2)
{
return 1;
}
else{
return fib1(n - 1) + fib1(n - 2);
}
}
//非递归求斐波那契数列
int fib2(int n)
{
int l1 = 0;
int l2 = 1;
int res = 0;
if ((n == 0) || (n==1))
{
return 1;
}
while (n >= 2)
{
res = l1 + l2;
l1 = l2;
l2 = res;
n--;
}
return res;
}
int main9()
{
printf("%d\n", fib1(1));
printf("%d\n", fib1(2));
printf("%d\n", fib1(3));
printf("%d\n", fib1(4));
printf("%d\n", fib1(5));
printf("%d\n", fib1(6));
printf("%d\n", fib1(7));
printf("%d\n", fib1(8));
printf("%d\n", fib1(9));
printf("%d\n", fib1(10));
printf("%d\n", fib2(1));
printf("%d\n", fib2(2));
printf("%d\n", fib2(3));
printf("%d\n", fib2(4));
printf("%d\n", fib2(5));
printf("%d\n", fib2(6));
printf("%d\n", fib2(7));
printf("%d\n", fib2(8));
printf("%d\n", fib2(9));
printf("%d\n", fib2(10));
system("pause");
return 0;
}
练习
1判断素数的函数
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int isPrime(int n)
{
int res = 0;
int tmp = sqrt(n);
for (int i = 2; i < tmp; i++)
{
if (n % i == 0)
{
return 0;
break;
}
}
return 1;
}
int main() {
int n;
printf("请输入一个整数:\n");
scanf("%d", &n);
if (!isPrime(n)) {
printf("%d是素数!\n", n);
}
else {
printf("%d不是素数!\n", n);
}
system("pause");
return 0;
}
2判断闰年函数
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int isLeap(int* n)
{
if ((*n % 100 != 0 && *n % 4 == 0) || *n % 400 == 0)
{
return 1;
}
return 0;
}
int main() {
int n;
printf("请输入一个年份:\n");
scanf("%d", &n);
if (isLeap(&n))
{
printf("%d是闰年!\n", n);
}
else
{
printf("%d是平年!\n", n);
}
system("pause");
return 0;
}
3实现整形数组的二分查找
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int binsearch(int x, int v[], int n)
{
for (int i = 0; i < n; i++)
{
if (v[i] == x)
{
return i;
}
}
return -1;
}
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
printf("%d\n", binsearch(4, arr, 10));
system("pause");
return 0;
}
4实现一个函数,每次调用num加1
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int add1(int num)
{
return ++num;
}
int main()
{
int num = 10;
num = add1(num);
printf("%d\n", num);
system("pause");
return 0;
}
5汉诺塔问题
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
//汉诺塔问题
void hannuota(int n, char a, char b, char c)
{
if (n == 1)
{
printf("%d:%c-->%c\n", n, a, c);
}
else
{
hannuota(n - 1, a, c, b);
printf("%d:%c-->%c\n", n, a, c);
hannuota(n - 1, b, a, c);
}
}
int main5()
{
int n;
char a = 'a';
char b = 'b';
char c = 'c';
printf("请输入盘子个数:");
scanf("%d", &n);
hannuota(n, a, b, c);
system("pause");
return 0;
}
6青蛙跳台阶问题
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
//青蛙跳台阶问题
int jumpFloor1(int n)
{
if ((n == 1) || (n == 2))
{
return n;
}
else
{
return jumpFloor1(n - 1) + jumpFloor1(n - 2);
}
}
int jumpFloor2(int n)
{
int l1 = 1;
int l2 = 2;
int res = 0;
if ((n == 1) || (n == 2))
{
return n;
}
while (n > 2)
{
res = l1 + l2;
l1 = l2;
l2 = res;
n--;
}
return res;
}
int main()
{
int n;
printf("请输入台阶个数:");
scanf("%d", &n);
printf("跳的方法有%d种\n", jumpFloor1(n));
printf("跳的方法有%d种\n", jumpFloor2(n));
system("pause");
return 0;
}