当前位置:   article > 正文

C语言-函数(详尽版)_c语言函数

c语言函数

目录

函数【C语言的第二个重点】:

 什么叫做函数

如何定义函数

函数的分类

函数注意的问题

形参和实参

常用的系统函数

变量的作用域和存储方式 


函数【C语言的第二个重点】:

     为什么需要函数:【定义之后就把他当工具来使用】

           操作一样,针对的数据不一样,我们就需要减少代码量,来使用函数来简化这些代码量,

           函数使用完毕之后,空间就会释放,不然的话每次调用占一块空间 

           那调用100次,内存不就爆炸了(满了)!

           程序一定从main()函数开始,也一定从main()结束

           避免了重复性操作,有利于模块化

代码举例:

  1. # include <stdio.h>
  2. /*
  3. 函数第一个例子
  4. */
  5. //定义一个无返回值,函数名字为max,两个形式参数
  6. void max(int i, int j) //后面不要加分号!!!
  7. {
  8. if (i > j)
  9. printf("%d\n", i);
  10. else
  11. printf("%d\n", j);
  12. }
  13. int main(void)
  14. {
  15. int a,b,c,d,e,f;
  16. a = 1, b = 2, c = 3, d = 9;
  17. e = -5, f = 100;
  18. max(a,b); //调用函数时,直接加函数名和要操作的的变量
  19. max(c,d);
  20. max(e,f);
  21. /*
  22. if (a > b) //第一个if -else
  23. printf("%d\n", a);
  24. else
  25. printf("%d\n",b);
  26. if (c > d) //和第一个一样if-else
  27. printf("%d\n", c);
  28. else
  29. printf("%d\n",d);
  30. if (e > f) //又和第一个重复了,此时我们就要用函数l简化代码
  31. printf("%d\n", e);
  32. else
  33. printf("%d\n",f);
  34. */
  35. return 0;
  36. }

          

          

    什么叫做函数

           逻辑上:能够完成特定功能代码块

           物理上:

              能够接收数据int f(int i),也可以不接受数据

                        int f(void)

              能够对接收的数据进行处理 调用时函数名加处理的数据

                        如f(10)能够将处理得到数据返回值int f(int i)

                        要与return配套使用,也可以没有返回值void(int i)

                        处理完之后没有return的函数                                                  

             

           总结:函数是一个工具,它是为了解决大量类似问题而设计的

                     函数可以当成一个黑夹子(只管输入数据,他给我一个

                        结果就行了)

             

             

                        

如何定义函数

           函数的返回值类型 函数的名字(函数的形参列表)

           {

              函数的执行体;

                  }

           例如:int max(int i, int j)

               {

                  if(i>j)

                     printf("%d",i);

                  else

                     printf("%d",j);

              }

          

           1.函数的定义本质是详细描述函数之所以能够实现某个特定功能

             的具体方法。   

代码如下

          

           2.return 表达式(重点):含义:

              1> 终止被调函数,向主调函数返回表达式的值                        

              2> 如果表达式为空,则终止函数,不向被调函数返回

                 任何值

                 例如:

                     void f()

                         {

                            return;//单纯的终止函数

                         }

                     int f()

                         {

                            return 10;//终止函数,并向

                                   被调函数返回

                                                            了一个值             

                         }

   

        3.函数返回值的类型也称函数的类型,因为如果函数名前的返回和函数执行体中的return表达式;中表达式的类型不同的话则最终函数返回值类型以函数名前的返回值类型为准

           代码如下:到底什么什么函数类型

  1. # include <stdio.h>
  2. /*
  3. 到底什么是函数返回值类型
  4. */
  5. int f()
  6. { //函数的返回值类型与return 表达式不同,以函数返回值类型为准
  7. //该函数返回值是10,而不是10.5
  8. return 10.5;
  9. }
  10. int main(void)
  11. {
  12. float x = 6;
  13. x = f();//f()返回的是一个整型变量10,放到x中
  14. printf("%f\n", x);
  15. return 0;
  16. }

       4.return和break的区别:return是终止函数的,break是终止函数

        代码举例:

  1. # include <stdio.h>
  2. /*
  3. return和break的区别
  4. */
  5. void f(void)
  6. {
  7. int i;
  8. for (i=0; i<5; i++)
  9. {
  10. printf("大家辛苦了!\n");
  11. break;
  12. }
  13. printf("同志们好!\n");
  14. }
  15. void g(void)
  16. {
  17. int i;
  18. for (i=0; i<5; i++)
  19. {
  20. printf("大家辛苦了!\n");
  21. return ; //return不是终止for循环的,而是终止g()函数的
  22. }
  23. printf("同志们好!\n");
  24. }
  25. //主调函数
  26. int main(void)
  27. {
  28. printf("下面为break执行的结果\n");
  29. f();
  30. printf("------------\n");
  31. printf("下面为return执行的结果\n");
  32. g();
  33. return 0;
  34. }
  35. /*
  36. 执行结果
  37. ------------------
  38. 下面为break执行的结果
  39. 大家辛苦了!
  40. 同志们好!
  41. ------------
  42. 下面为return执行的结果
  43. 大家辛苦了!
  44. ------------------
  45. 总结:return是终止函数的,break是终止循环的
  46. */

      5.函数在输出时,可以在被调函数里直接将函数输出也可以通

             return将函数处理过的结果返回到函数中在通过主调函数进行

             输出,简单言之就是处理过的结果可以直接在被调函数里直输

         也可以通过main函数(主函数)里输出,但是要利用return语  句将结果返回到函数中去中去( 实际上函数名也是一个地址),将返回的值返回到函数中之后,通过主函数使用处理过的结果 值    

例子如下代码:函数举例_1

  1. # include <stdio.h>
  2. /*
  3. 函数第一个例子
  4. */
  5. //定义一个无返回值函数名字为max含有形式参数的被调函数
  6. void max(int i, int j) //后面不要加分号!!!
  7. {
  8. if (i > j)
  9. printf("%d\n", i);
  10. else
  11. printf("%d\n", j);
  12. }
  13. //被调函数
  14. int max2(int i, int j)
  15. {
  16. if (i > j)
  17. return i; //把值返回给被调函数max2(实参)
  18. else
  19. return j;
  20. }
  21. //主调函数
  22. int main(void)
  23. {
  24. int a,b,z;
  25. a = 1, b = 2;
  26. //结果通主调函数输出
  27. z = max2(a,b);//通过return语句将传入的数据处理过的结果返回到函数名中(相当于地址)
  28. printf("在主调函数输出为%d\n", z);
  29. printf("结果在被调函数输出为");
  30. //结果在被调函数就被输出
  31. max(a,b); //调用函数时,直接加函数名和要操作的的变量
  32. return 0;
  33. }
  34. /*
  35. 输出结果
  36. ----------------
  37. 在主调函数输出为2
  38. 结果在被调函数输出为2
  39. ---------------------
  40. 总结:
  41. 函数在输出时,可以在被调函数里里直接将函数输出,也可以通
  42. return将函数处理过的结果返回到函数中在通过主调函数进行
  43. 输出,简单言之就是处理过的结果可以直接在被调函数里直接输
  44. 也可以通过main函数(主函数)里输出,但是要利用return
  45. 句将结果返回到函数中去中去(实际上函数名也是一个地址)
  46. 将返回的值返回到函数中之后,通过主函数使用处理过的结果值
  47. */

          

代码举例_2:判断素数

  1. # include <stdio.h>
  2. # define true 1
  3. # define false 0
  4. /*
  5. 编一个输出素数函数
  6. 素数:只能被1和自己整除,且1不是素数
  7. 解题思路:假如我们判断9是不是素数
  8. 除去1和本身,从2-8只要
  9. 有一个被9整除,则该数就不是素数
  10. 很明显在2-8,3能够被9整除即9不是素数
  11. */
  12. //定义一个素数判断的函数
  13. int IsPrime(int val)
  14. {
  15. int i;
  16. for(i=2; i<val; i++)
  17. {//2到val-1中找到能否被val整除的数
  18. if(val%i == 0)
  19. break;
  20. }
  21. // 输出是否为素数
  22. if (val == i)
  23. return true;
  24. else
  25. return false;
  26. }
  27. //主调函数
  28. int main(void)
  29. {
  30. int k;
  31. char ch;
  32. int val; //定义要输入的数
  33. do
  34. {
  35. printf("请输入一个数: ");
  36. scanf("%d", &val);//接收键盘输入的值
  37. k = IsPrime(val); //将传入的值放入k中
  38. printf("%d\n", k);
  39. printf("是否继续(Y/N):");
  40. scanf(" %c", &ch);
  41. } while(ch=='y' || 'Y'==ch);
  42. return 0;
  43. }

   

函数的分类

           有参函数 和 无参函数

           有返回值 和 无返回值

           库函数  和 用户自定义函数

           值传递 和 地址传递(指针)

           普通函数 和 主函数(main函数)

              一个函数必须有且仅有一个主函数

              普通函数不能调用主函数(如递归)

              普通函数可以相互调用

              主函数是程序的入口,也是程序的出口

代码举例:函数举例

  1. # include <stdio.h>
  2. /*
  3. 202361511:26:24
  4. 函数复习例子
  5. */
  6. void f() //无参无返回值
  7. {
  8. printf("f()是无参无返回值\n");
  9. }
  10. void f(int i) //有参无返回值
  11. {
  12. printf("f(int i)是有参无返回值\n");
  13. }
  14. int f1() //无参有返回值
  15. {
  16. return 1;
  17. }
  18. int f1(int val)//有参有返回值
  19. {
  20. int sum = 0;
  21. int i;
  22. for (i=1; i<val; i++)
  23. {
  24. sum = sum + i;
  25. }
  26. return sum;
  27. }
  28. int main(void)
  29. {
  30. int i;
  31. f();
  32. f(2);
  33. printf("f1()是无参有返回值通过return返回一个int型变量值为:%d\n",f1());
  34. printf("f1(int i)是有参有返回值通过return返回一个sum值为:%d\n", f1(10));
  35. return 0;
  36. }
  37. /*
  38. 执行结果
  39. -----------------
  40. f()是无参无返回值
  41. f(int i)是有参无返回值
  42. f1()是无参有返回值通过return返回一个int型变量值为:1
  43. f1(int i)是有参有返回值通过return返回一个sum值为:45
  44. -----------------
  45. */

判断素数代码优化:

代码1:

  1. # include <stdio.h>
  2. /*
  3. 如何合理设计一个函数
  4. 判断一个函数是否是素数
  5. 一个函数实现它
  6. */
  7. bool f(int val)//判断是否为素数
  8. {
  9. int i;
  10. for (i=2; i<val; i++) //2~val-1循环
  11. {
  12. if(val%i == 0) //判断在2~val-1是否存在能被val整除的数
  13. break; //找到就退出循环
  14. }
  15. if (i == val) //如果val和i相等就是素数
  16. return true;//是就返回真
  17. else
  18. return false;//否则就返回假
  19. }
  20. int main(void)
  21. {
  22. int val;
  23. int k;
  24. printf("请输入一个数:");
  25. scanf("%d", &val);
  26. k = f(val);
  27. if(k == 1)
  28. printf("是素数!\n");
  29. else
  30. printf("不是素数!\n");
  31. return 0;
  32. }

代码2:

  1. # include <stdio.h>
  2. /*
  3. 202361517:32:46
  4. 1到某个数字之间(包括该数字)所有的素数,并将其输出
  5. 用单独函数实现,代码的可重复性提高
  6. 只用main函数实现,有局限性
  7. 1.代码重复性不高
  8. 2.代码也不容易理解
  9. */
  10. int main()
  11. {
  12. int val;
  13. int i;
  14. int j;
  15. scanf("%d",&val);
  16. for (i=2; i<=val; i++)
  17. { //判断i是否为为素数,是就输出,不是不输出
  18. for (j=2; j<i; j++)
  19. {
  20. if (i%j == 0)
  21. break;
  22. }
  23. if (j == i)
  24. printf("%d\n",i);
  25. }
  26. return 0;
  27. }

代码3:进行模块化

  1. # include <stdio.h>
  2. /*
  3. 202361517:32:46
  4. 1到某个数字之间(包括该数字)所有的素数,并将其输出
  5. 用单独函数实现,代码的可重复性提高
  6. 用一个函数实现比在main单独实现可读性更好
  7. 用函数实现
  8. */
  9. bool IsPrime(int m)
  10. {
  11. int j;
  12. for (j=2; j<m; j++)
  13. {
  14. if (m%j == 0)
  15. break;
  16. }
  17. if (j == m)
  18. return true;
  19. }
  20. void IsPrime2(int val)
  21. {
  22. int i;
  23. int k;
  24. for (i=2; i<=val; i++)
  25. { //判断i是否为为素数,是就输出,不是不输出
  26. k = IsPrime(i);
  27. if (1 == k)
  28. printf("%d\n", i);
  29. }
  30. }
  31. int main()
  32. {
  33. int val;
  34. scanf("%d",&val);
  35. IsPrime2(val);
  36. return 0;
  37. }

代码4:再次进行模块化

  1. # include <stdio.h>
  2. /*
  3. 202361517:32:46
  4. 1到某个数字之间(包括该数字)所有的素数,并将其输出
  5. 用单独函数实现,代码的可重复性提高
  6. 用一个函数实现比在main单独实现可读性更好
  7. 函数实现:主要里函数的使用
  8. */
  9. bool IsPrime(int m);//函数声明
  10. void IsPrime2(int val);
  11. void TraverseVal() //1-n之间所有的素数输出,输出几遍
  12. {
  13. int i;
  14. int val;
  15. int n;
  16. int count = 0;
  17. scanf("%d %d",&val, &n);
  18. for (i=0; i<n; i++)
  19. {
  20. count++;
  21. printf("第%d遍历开始\n",count);
  22. printf("----------------\n");
  23. IsPrime2(val);
  24. }
  25. }
  26. bool IsPrime(int m)//判断m是否是素数,是返回true,不是返回false
  27. {
  28. int j;
  29. for (j=2; j<m; j++)
  30. {
  31. if (m%j == 0)
  32. break;
  33. }
  34. if (j == m)
  35. return true;
  36. }
  37. void IsPrime2(int val)
  38. {
  39. int i;
  40. int k;
  41. for (i=2; i<=val; i++)
  42. { //判断i是否为为素数,是就输出,不是不输出
  43. k = IsPrime(i);
  44. if (1 == k)
  45. printf("%d\n", i);
  46. }
  47. }
  48. //主函数
  49. int main()
  50. {
  51. TraverseVal();
  52. return 0;
  53. }

函数注意的问题

 函数定义的顺序  

1.函数声明格式:返回值类型 函数名(参数);例如voidf(void);一定要在开头,函数神声明是一条语句,一定要有分号‘’

2.函数声明1:函数声明,程序都是从上往下执行的,如果被调函数在主函数下面定义一定                要声明,声明时分号能不能丢掉

代码如下:函数声明1

  1. # include <stdio.h>
  2. /*
  3. 函数声明,程序都是从上往下执行的,如果被调函数在主函数下面定义一定要声明
  4. */
  5. void f(void); //函数声明,分号不能丢掉
  6. int main()
  7. {
  8. f();
  9. return 0;
  10. }
  11. void f(void)
  12. {
  13. printf("哈哈!\n");
  14. }

             

3.函数声明2:函数声明一定要定义在主调函数前或另一个被调函数前面不然会报错,解决方法:前置声明被调函数1调用被调函数2被调用的一定要在前,在后的话 一定要声明,在函数开头声明,声明一定 要有分号

 

代码如下:函数声明_2

  1. # include <stdio.h>
  2. /*
  3. 202361516:13:11
  4. 函数声明2,一个被调函数调用另一个被调函数,
  5. 被调函数在后,主被调函数在前,一定要声明
  6. */
  7. void f(void);//函数声明
  8. void g(void)//被调函数1
  9. {
  10. f(); //被调函数1调用被调函数2被调用的一定要在前,在后的话一定要声明
  11. }
  12. void f()//被调函数2
  13. {
  14. printf("哈哈!\n");
  15. }
  16. int main()
  17. {
  18. g();
  19. return 0;
  20. }

 

4.对库函数的声明通过# include <库函数所在文件的名字.h>来实现的(如printf库函数)

5.void的含义:

  1. # include <stdio.h>
  2. /*
  3. void 含义
  4. f()是被调函数,调用的函数是主调函数 如main()函数调用f()
  5. */
  6. int f(void) //括号中的void表示该函数不能接收数据,int表示该函数返回值是int类型的数据
  7. { //该函数有返回值 返回一个int类型的值
  8. return 10; //向主调函数返回10
  9. }
  10. void g(void) //定义一个无返回值的函数g()
  11. {
  12. //return 0; //函数是无返回值的不能加return,与void相矛盾
  13. }
  14. int main()
  15. {
  16. int j = 88;
  17. int i = 10;
  18. j = f(); //将f()的返回值放到j变量中
  19. printf("%d\n", j);
  20. i = g();
  21. printf("%d\n", i);
  22. return 0;
  23. }

          

形参和实参

           形参定义格式:

                 类型返回值 函数名(形式参数1,形式参数2 ...)

                 每个形式参数以逗号隔开

           形参:形式参数,例如函数定义时:int f(int i),这个i

                      就是一个形式参数,没有实际意义,当主调函数的实参

                     传入形参,这时候形参才有实际意义,

          实参:顾名思义实际参数,例如f(4);括号里面有个具体值,一   

              定是个具体数值,如果是形参也是被赋了具体值的形参
              总之,一定是个值,有实际意义的数值。

           两者有什么关系?

              形参和实参必须一一对应,形参有几个,实参 就必须有几个例如 int f(int i, int j)的

              形参有两个则实参必须传入两个如f(2,3)

       如何在软件开发过程中合理的设计函数来解决实际问题(重点)?

           多模仿牛人,一个函数功能尽量独立 

                 

常用的系统函数

           double sqrt(double x); 求x的平方根

           int abs(int x); 求x绝对值

           double fabs(double x);求x的绝对值

           引用以上需加上预编译头文件#incldue<math.h>

           printf()scanf() 引用以上需加上预编译头文件

           #include<stdio.h>,stdio.h是标准输入输出文件

   

变量的作用域和存储方式 

           按作用域分:

                    全局变量:在所有函数外定义的就属于全局变量

                      

                   局部变量:在函数内部定义的变量或者函数的形参

代码举例如下:

  1. # include <stdio.h>
  2. /*
  3. 全局变量和局部变量
  4. */
  5. int k = 1000;//全局变量 在最顶端
  6. void f(int i)
  7. {
  8. //int i;与形参定义重复,形参内的定义的也相当于局部变量
  9. int k = 20;//局部变量
  10. }
  11. void g()
  12. {
  13. printf("%d\n", k);//函数内部使用的是全局变量
  14. }
  15. int main()
  16. {
  17. int k = 30;//局部变量
  18. printf("%d\n", k);//输出局部变量30
  19. g();
  20. return 0;
  21. }

                    

           按变量的存储方式分:

                  静态变量:static关键字:分配的一块静态

                                    存储空间 ,用完不释放

                  自动变量:auto关键字:

                                   运行在堆栈中的动态分配内存

                                   用完就释放

                  寄存器变量:register关键字:也是一中存储

                                      数据的变量,只不过是将变量和寄存

                                      相关联,执行效率特别高

             

    专题:

       递归:数据结构内容(郝斌数据结构)

递归的概念,递归指的是一个函数自己调用自己,首先我们知道主函数main只能有一个也不可能被其他函数调用,所以我们肯定要写一个子函数,然后再子函数里用递归。然后我们去找递归的结束标志,如果没有结束标志,那么这个递归程序会一直调用自己,导致你的程序崩溃,所以去找递归的结束标志很重要。很明显,当n的值等于1的时候,我们就不用再调用自己了,然后返回到上一层,乘上这一层的n,然后再一层一层返回,每返回一层,n的值就比返回的n大1,直到返回到第一层的时候,就是我们的第一个乘数。这样我们就模拟出了阶乘的算法,然后再返回给主函数打印。 

    递归举例:求阶乘

  1. 题目: 利用递归方法实现一个函数,该函数能够实现n的阶乘,即 n! = n*(n-1)**3*2*1;
  2. #include <stdio.h>
  3. int factorial(int n)
  4. {
  5. if(n == 1) //结束递归判断条件
  6. {
  7. return;
  8. }
  9. return n*factorial(n - 1); //递归调用自己
  10. }
  11. int main()
  12. {
  13. int n;
  14. printf("please input a number:\n");
  15. scanf("%d",&n);
  16. printf("result = %d\n",factorial(n));
  17. return 0;
  18. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/367943
推荐阅读
相关标签
  

闽ICP备14008679号