函数是什么

第一,函数就是 C 语言的模块,一块一块的,有较强的独立性,可以相互调用,换句话说,C 语言中,一个函数里面可以调用 n 个函数,即大函数调用小函数,小函数又调用“小小”函数。这就是结构化程序设计,所以面向过程的语言又叫结构化语言。

第二,函数就是一系列 C 语句的集合,能完成某个特定的功能。需要该功能的时候直接调用该函数即可,不用每次都堆叠代码。需要修改该功能时,也只需要修改和维护这一个函数即可。

函数的分类

  1. 库函数

    1. IO函数
    2. 字符串操作函数
    3. 内存操作函数
    4. 时间/日期函数
    5. 数学函数
    6. 其他库函数
  2. 自定义函数

自定义函数和库函数一样,有函数名,返回值和函数参数,但是不一样的是这些都是由我们自己来设计

函数的组成:

  1. ret_type fun_name(para1,*)
  2. {
  3. statement; //语句项
  4. }
  5. ret_type 返回类型
  6. fun_name 函数名
  7. paral 函数参数
  1. #include <stdio.h>
  2. //比较两个数的大小
  3. int get_max(int x, int y)
  4. {
  5. int z = 0;
  6. if (x > y)
  7. z = x;
  8. else
  9. z = y;
  10. return z;//z的值与int的返回相关
  11. }
  12. int main()
  13. {
  14. int a = 20;
  15. int b = 30;
  16. //函数的调用
  17. int max = get_max(a, b);
  18. printf("%d\n",max);
  19. return 0;
  20. }
  1. #include <stdio.h>
  2. //函数返回类型的地方写成:void 表示这个函数不返回任何值
  3. //也不需要返回
  4. void Swap(int* pa, int* pb)//引用指针papba,b的地址 *paa *pbb
  5. {
  6. int z = 0;
  7. z = *pa;
  8. *pa = *pb;
  9. *pb = z;
  10. }
  11. int main()
  12. {
  13. int a = 10;
  14. int b = 20;
  15. //写一个函数---交换两个整型变量的值
  16. printf("交换前;a=%d,b=%d\n",a,b);
  17. Swap(&a, &b);
  18. printf("交换后;a=%d,b=%d\n", a, b);
  19. return 0;
  20. }

函数的参数

实际参数(实参)

真实传给函数的参数叫实参。实参可以是:变量、常量、表达式、函数等。无论实参数是何种类型的量,在进行函数调用时,它们都必须以后确定的值,以便把这些值传送给形参

形式参数(形参)

形式参数是指函数名括号中的变量,因为形式蚕食只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了,因此形式参数只在函数中有效

函数的调用

传值调用:

函数的形参和实参分别占有两个不同内存块,对形参的修改不会影响实参

传址调用

  • 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式
  • 这种传址方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量

函数的声明和定义

函数声明:

  1. 告诉编译器有个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,无关紧要
  2. 函数的声明一般出现在函数的使用之前,要满足先声明后使用
  3. 函数的声明一般要放在头文件中

函数的定义

函数的定义具体指函数的具体实现,交代函数的实现功能

练习:

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. //计算1000~200之间的素数
  3. #include <stdio.h>
  4. #include <math.h>
  5. int is_prime(int n)
  6. {
  7. int j = 0;
  8. for (j = 2; j <=sqrt(n); j++)
  9. {
  10. if (n % j == 0)
  11. {
  12. return 0;
  13. }
  14. }
  15. return 1;
  16. }
  17. int main()
  18. {
  19. int i = 0;
  20. int count = 0;
  21. for (i = 100; i <= 200; i++)
  22. {
  23. if (is_prime(i) == 1)
  24. {
  25. count++;
  26. printf("%d\n",i);
  27. }
  28. }
  29. printf("%d",count);
  30. return 0;
  31. }
  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include <stdio.h>
  3. #include <math.h>
  4. //一个函数如果不写返回类型,默认返回int类型
  5. int is_leap_year(int n)
  6. {
  7. if (n % 4 == 0 && n % 100 != 0 || n % 400 == 0)
  8. {
  9. return 1;
  10. }
  11. else
  12. {
  13. return 0;
  14. }
  15. }
  16. int main()
  17. {
  18. int y = 0;
  19. for (y = 1000; y <= 2000; y++)
  20. {
  21. if (is_leap_year(y) == 1)
  22. {
  23. printf("%d\n",y);
  24. }
  25. }
  26. return 0;
  27. }
  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include <stdio.h>
  3. #include <math.h>
  4. //一个函数如果不写返回类型,默认返回int类型
  5. int is_leap_year(int n)
  6. {
  7. return(n % 4 == 0 && n % 100 != 0 || n % 400 == 0);
  8. /*直接返回*/
  9. }
  10. int main()
  11. {
  12. int y = 0;
  13. for (y = 1000; y <= 2000; y++)
  14. {
  15. if (is_leap_year(y) == 1)
  16. {
  17. printf("%d\n",y);
  18. }
  19. }
  20. return 0;
  21. }
  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include <stdio.h>
  3. int binary_search(int a[],int k,int s)
  4. {
  5. int left = 0;
  6. int right = s - 1;
  7. while (left <= right)
  8. {
  9. int mid = (left + right) / 2;
  10. if (a[mid] > k)
  11. {
  12. right = mid - 1;
  13. }
  14. else if (a[mid] < k)
  15. {
  16. left = mid + 1;
  17. }
  18. else
  19. {
  20. return mid;
  21. }
  22. }
  23. return -1;/*找不到情况*/
  24. }
  25. int main()
  26. {
  27. int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
  28. int key = 7;
  29. int sz = sizeof(arr) / sizeof(arr[0]);
  30. int ret = binary_search(arr, key, sz);
  31. if (ret == 1)
  32. {
  33. printf("找不到\n");
  34. }
  35. else
  36. {
  37. printf("找到了,下标是%d",ret);
  38. }
  39. return 0;
  40. }

函数递归

什么是递归?
程序调用自身的编程技巧称为递归(recursion)。递归作为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与与原问题相似的规模小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大减少了代码量。递归主要思考方式在于:把大事化小事。

递归的两个必要条件

  • 存在限制条件,当满足这个条件限制的时候,递归便不再继续
  • 每次递归调用之后越来越接近这个限制条件

例:接受一个整型(无符号),按照顺序打印它的每一位。例如:输入:1234,输出1 2 3 4.

  1. #include <stdio.h>
  2. void print(unsigned int n)
  3. {
  4. if (n > 9)
  5. {
  6. print(n / 10);
  7. }
  8. printf("%d",n % 10);
  9. }
  10. int main()
  11. {
  12. unsigned int num = 0;
  13. scanf("%u",&num);
  14. print(num);
  15. }


image.png

编写函数不允许创建临时变量,求字符串的长度

  1. #include <stdio.h>
  2. int my_strlen(char* str)
  3. {
  4. int count=0;
  5. while (*str != '\0')
  6. {
  7. count++;
  8. str++;
  9. }
  10. return count;
  11. }
  12. int main()
  13. {
  14. char arr[] = "abc";
  15. printf("%d",my_strlen(arr));
  16. return 0;
  17. }
  1. #include <stdio.h>
  2. int my_strlen(char* str)
  3. {
  4. if (*str != '\0')
  5. {
  6. return 1 + my_strlen(str + 1);
  7. }
  8. else
  9. {
  10. return 0;
  11. }
  12. }
  13. int main()
  14. {
  15. char arr[] = "abc";
  16. printf("%d",my_strlen(arr));
  17. return 0;
  18. }
  1. #include <stdio.h>
  2. int main()
  3. {
  4. int n = 0;
  5. scanf("%d",&n);
  6. int i = 0;
  7. int ret = 1;
  8. for (i = 1; i <= n; i++)
  9. {
  10. ret = ret * i;
  11. }
  12. printf("%d",ret);
  13. }
  1. #include <stdio.h>
  2. int ret(int m)
  3. {
  4. if (m <= 1)
  5. {
  6. return 1;
  7. }
  8. else
  9. {
  10. return m * ret(m - 1);
  11. }
  12. }
  13. int main()
  14. {
  15. int n = 0;
  16. scanf("%d",&n);
  17. printf("%d", ret(n));
  18. return 0;
  19. }

求第n个斐波那契数(不考虑溢出)

  1. #include <stdio.h>
  2. int Fib(int m)
  3. {
  4. if (m <= 2)
  5. {
  6. return 1;
  7. }
  8. else
  9. {
  10. return Fib(m-1)+Fib(m-2);
  11. }
  12. }
  13. int main()
  14. {
  15. int n = 0;
  16. scanf("%d",&n);
  17. printf("%d", Fib(n));
  18. return 0;
  19. }
  1. #include <stdio.h>
  2. int Fib(int m)
  3. {
  4. int a = 1;
  5. int b = 1;
  6. int c = 1;
  7. while (m>2)
  8. {
  9. c = a + b;
  10. a = b;
  11. b = c;
  12. m--;
  13. }
  14. return c;
  15. }
  16. int main()
  17. {
  18. int n = 0;
  19. scanf("%d",&n);
  20. printf("%d", Fib(n));
  21. return 0;
  22. }