115.C语言_函数

第六章 函数

  • 6.2 函数定义的一般形式
    • 函数的定义
      • C语言中函数定义的一般形式如下:
        • 函数返回值的类型名  函数名(类型名  形式参数1,类型名  形式参数2, … )
        • {
        • 说明部分;
        • 语句部分;
        • }
    • 说明:
      • 函数名和各个形式参数都是由用户命名的合法标识符,与普通变量名的定义规则相同。在同一程序中,函数名必须唯一,不能出现重名的情况。形式参数名只要在同一函数中唯一即可,由于形式参数的作用域不相同,因此形式参数名可以与其他函数中的变量名同名。C语言规定,不能在一个函数内部再定义函数,也就是说函数不能嵌套定义。
      • 若在函数的首部省略了函数返回值的类型名,可以把函数首部写成:
        • 函数名(类型名形式参数1 ,类型名 形式参数2 ,…,类型名 形式参数n)
      • 紧跟在函数名之后的圆括号中的内容是形式参数和类型说明表,在每个形参之前都要有类型名,以标识形式参数的类型。各形参的定义之间用逗号分隔。
        • 例如,求两整数和的函数:
          • int  add(int a ,int b)
          • {
          • intt;       /* 函数体中声明部分 */
          • t=a+b;
          • return t;
          • }
      • 若所定义的函数没有形参,函数名后的一对圆括号依然不能省略。本例中函数体中的语句是用来完成求和的功能。在某些情况下,函数体可以是空的,例如:
        • fun()
        • {  }
        • 该函数中没有任何语句,什么工作也不做,没有任何实际作用。之所以要在主调函数上这样写,是为了表明此处要调用一个函数,而现在这个函数的具体功能可能还没有设计好,没有起作用,等以后扩充函数功能时补充上即可。
      • 在函数体中,除形参外,用到的其他变量必须在说明部分进行定义,这些变量(包括形参)只在函数被调用时才被临时分配内存单元,当退出函数时,这些临时开辟的存储单元全部被释放掉,即在该函数体内部定义的变量都将不存在。因此,这些变量只在函数体内部起作用,与其他函数体内的变量并不相关。
  • 6.3 函数参数和函数返回值
    • 6.3.1 形式参数和实际参数
      • 定义
        • 在程序中调用函数时,绝大多数情况下,主调函数和被调函数之间会发生数据传递关系,这就要用到前面提到的有参函数。在定义函数时,函数名后面括号中的变量称为“形式参数“(简称“形参“);在主调函数中,函数名后面括号中的参数(可以是一个表达式)称为“实际参数“(简称“实参“)。
      • 说明:
        • (1)实参可以是常量、变量或表达式。
        • (2)在被定义的函数中必须指定形参类型。
        • (3)实参与形参的类型应相同或赋值相兼容。
        • (4)C语言规定,实参变量对形参变量的数据传递是“值传递“,即单向传递。只能由实参传给形参,而不能由形参返回来给实参。在内存中,实参单元与形参单元是不同的单元。
        • (5)在调用函数时,给形参分配存储单元,并将实参对应的值传递给形参。调用结束后,形参单元被释放,实参单元仍保留并维持原值。
        • (6)一定要注意参数之间的传递,实参和形参之间 传数值,和传地址的差别。传数值的话,形参的变化不会改变实参的变化。传地址的话,形参的变化就会有可能改变实参的变化。
    • 6.3.2 函数的返回值
      • 函数的返回值就是通过函数调用使主调函数能得到一个确定的值。函数的值通过return语句返回,return语句的形式如下:
        • return 表达式;
        • 或return(表达式);
        • 或return;
      • return 语句中的表达式的值就是所求的函数值。此表达式值的类型必须与函数首部所说明的类型一致。若类型不一致,则以函数值的类型为准,由系统自动进行转换。
        • 例如 通过函数调用的方法求1到自然数n(n>1)自然数的和,有程序段如下
          • #include<stdio.h>
          • ints(int n)
          • {
          • int i,sum=0;
          • for(i=1;i<=n;i++)
          • sum+=i;
          • return sum;
          • }
          • main()
          • {
          • int n;
          • printf("input number\n");
          • scanf("%d",&n);
          • n=s(n);
          • printf("1到n的和为:%d\n",n);
          • }
  • 6.4 函数的调用
    • 6.4.1 函数调用的一般形式
      • 函数名(实参表列);
      • 函数的调用可以分为调用无参函数和调用有参函数两种,如果是调用无参函数,则不用“实参表列“,但括号不能省略。在调用有参函数时,若实参列表中有多个实参,各参数间用逗号隔开。实参与形参要求类型一致。
    • 6.4.2 函数调用的方式
      • (1)函数语句。把函数调用做为一个语句,这时该函数只需要完成一定的操作而不必有返回值。
      • (2)函数表达式。当一个函数出现在一个表达式中,该表达式就被称为函数表达式。因为要参与表达式中的计算,所以要求该函数有一个确定的返回值提供给表达式。
      • (3)函数参数。函数调用做为一个函数的实参。
    • 6.4.3 C语言中,调用函数和被调用函数之间的数据可通过3种方式进行传递。
      • (1)实参与形参之间进行数据传递。
      • (2)通过return语句把函数值返回到主调用函数中。
      • (3)通过全局变量。
    • 6.4.3  函数的递归调用
    • 函数的递归调用一定要记得有结束的条件
    • 在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。允许函数的递归调用是C语言的特点之一。
    • 当一个问题在采用递归法解决时,必须符合以下3个条件:
    • (1)可以把要解决的问题转化为一个新的问题。而这个新的问题的解决方法仍与原来的解决方法相同,只是所处理的对象有规律地递增或递减。
    • (2)可以应用这个转化过程使问题得到解决。
    • (3)必须要有一个明确的结束递归的条件。
    • 当函数自己调用自己时,系统将自动把函数中当前的变量和形参暂时保留起来,在新一轮的调用过程中,系统将为本次调用的函数所用到的变量和形参,开辟新的存储单元。因此,递归调用的层次越多,同名变量所占的存储单元也就越多。当本次调用的函数运行结束时,系统将释放本次调用所占的存储单元。当程序执行的流程返回到上一层的调用点时,同时取用进入该层函数中的变量和形参所占用的存储单元中的数据。
  • 6.5 函数的说明
    • 6.5.1  形式
      • 概念
        • C语言中,除了主函数外,对于用户定义的函数要遵循先定义后使用的规则。把函数的定义放在调用之后,应该在调用之前对函数进行说明(或函数原型说明)。
      • 函数说明的一般形式如下:
        • 类型名 函数名(参数类型1 ,参数类型2 ,…,参数类型n);
            • intadd(int  ,int  );
        • 类型名 函数名(参数类型1 参数名1,参数类型2 参数名2 ,…,参数类型n  参数名n);
          • 此处的参数名完全是虚设的,它们可以是任意的用户标识符,既不必与函数首部中的形参名一致,又可以与程序中的任意用户标识符同名,实际上参数名常常省略。函数说明语句中的类型名必须与函数返回值的类型一致。
      • 函数说明可以是一条独立的语句。对函数进行说明,能使C语言的编译程序在编译时进行有效的类型检查。当调用函数时,若实参的类型与形参的类型不能赋值兼容而进行非法转换,C编译程序将会发现错误并报错;当实参的个数与形参的个数不同时,编译程序也将报错。
    • 6.5.2函数说明的位置
      • 一个函数在所有函数的外部,如在被调用之前说明,则在说明后的所有位置上都可以对该函数进行调用。如在main()函数内部进行说明,则只能在main()函数内部才能识别。
      • 例如 调用求和函数输出1到n的和值,程序段如下:
        • #include<stdio.h>
        • main()
        • {
        • int n;
        • int s(int n);
        • printf("input number\n");
        • scanf("%d",&n);
        • s(n);
        • printf("n=%d\n",n);
        • }
        • ints(int n)
        • {
        • int i,sum=0;
        • for(i=1;i<=n;i++)
        • sum+=i;
        • printf("1到n的和值为:%d\n",n);
        • }
    • 一定要有:函数名,函数的返回类型,函数的参数类型。不一定要有:形参的名称。
  • 6.6 常用函数
    • 6.6.1  字符串 <string.h>
      • 6.6.1.1  strlen 计算长度
      • 6.6.1.2  strcmp 比较
      • 6.6.1.3  strcpy 复制 (不安全,越界)
      • 6.6.1.4  strcat 追加 (不安全,越界)
    • 6.6.2  数学函数<math.h>
      • 6.6.2.1   向上,向下取整
        • 函数名: ceil
          • 功能:向上取整
          • 用法: double ceil(double x);
        • 函数名: floor
          • 功能:向下取整
          • 用法: double floor(double x);
      • 6.6.2.2  取绝对值
        • 函数名:abs
          • 功能:返回整型数的绝对值.
          • 用法:abs(number)
          • number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回Null;如果是未初始化变量,则返回 0.
        • 函数名:fabs
          • 功能:求浮点数x的绝对值.
          • 用法:fabs  (double x);
      • 6.6.2.3  平方根
        • 函数名:sqrt
          • 功能:返回指定数字的平方根.
          • 用法:sqrt  (double x);
      • 6.6.2.4  求幂
        • 函数名:exp
          • 功能:返回 e 的 n 次幂.
          • 用法:exp  (double x);
        • 函数名:pow
          • 功能:返回指定数字的指定次幂.
          • 用法:pow   (double x, double y);(将返回x的y次幂)
      • 6.6.2.5  取余
        • 函数名: fmod
          • 功  能: 计算x对y的模, 即x/y的余数
          • 用  法:double fmod(double x, double y);
      • 6.6.2.6  对数
        • 函数名:log
          • 功能: 自然对数函数ln(x)
          • 用法: double log(double x);
        • 函数名:log10
          • 功能:返回以 10 为底的对数.
          • 用法:log10(double x);
      • 6.6.2.7  三角函数:(所有参数必须为弧度)
        • sin
          • 函数声明:sin  (double x);
          • 用途:用来返回给定的 X 的正弦值。
        • cos
          • 函数声明:cos  (double x);
          • 用途:用来返回给定的 X 的余弦值。
        • tan
          • 函数声明:tan   (double x);
          • 用途:用来返回给定的 X 的正切值。
      • 6.6.2.8  反三角函数
        • acos
          • 函数申明:acos  (double x);
          • 用途:用来返回给定的 X 的反余弦函数。
        • asin
          • 函数申明:asin  (double x);
          • 用途:用来返回给定的 X 的反正弦函数。
        • atan
          • 函数申明:atan  (double x);
          • 用途:用来返回给定的 X 的反正切函数。
        • atan2
          • 函数声明:atan2 (double y, double x);
          • 用途:返回给定的 X 及 Y 坐标值的反正切值
      • 6.6.2.9  双曲函数
        • 函数名:cosh
          • 功能:返回指定角度的双曲余弦值.
          • 用法:Double Cosh(double x(以弧度计量的角度)) ;
        • 函数名:sinh
          • 功能:返回指定角度的双曲正弦值。
          • 用法:sinh (double x);(其中参数x必须为弧度制)
        • 函数名:tanh
          • 功能:回指定角度的双曲正切值.
          • 用法:tanh  (double x);
      • 6.6.2.10  实型数分整数和小数
        • 函数名:modf
          • 功  能: 把数分为整数部分和小数部分
          • 用  法: double modf(doublevalue, double *iptr);
          • eg
            • 1.  #include<math.h>
            • 2.
            • 3.  #include<stdio.h>
            • 4.
            • 5.  int main(void)
            • 6.
            • 7.  {
            • 8.
            • 9.  double fraction,integer;
            • 10.
            • 11. double number =100000.567;
            • 12.
            • 13. fraction =modf(number, &integer);
            • 14.
            • 15. printf("Thewhole and fractional parts of %lf are %lf and %lf\n",
            • 16.
            • 17. number, integer,fraction);
            • 18.
            • 19. return 0;
            • 20.
            • 21. }
            • The whole andfractional parts of 100000.567000 are 100000.000000 and 0.567000
      • 6.6.2.11  随机数
        • 在编程的时候需要电脑来获取一些随机的反应,这个时候我们可以使用随机数,比较常见的是 rand() 函数,它可以随机的产生 0 ~rand_max 的随机数。rand_max 是一个很大的数字,具体关系到IDE和数据类型,我们一般的需要不可能超出它的范围
        • C语言中还有一个 random() 函数可以获取随机数,但是 random() 函数不是ANSI C标准,不能在VC等编译器通过,所以比较少用。
        • eg
          • int a=rand()%10; //产生0~9的随机数,注意10会被整除
          • int a=rand()%51+13; //产生13~63的随机数
          • 产生 13~63 范围内随机数的完整代码:
            • 1.      #include <stdio.h>
            • 2.      #include <stdlib.h>
            • 3.      #include <time.h>
            • 4.      int main(){
            • 5.      int a;
            • 6.      srand((unsigned)time(NULL));
            • 7.      a=rand()%51+13;
            • 8.      printf("%d\n",a);
            • 9.      return 0;
            • 10.  }
          • 下面是一个实例:
            • 1.      #include <stdio.h>
            • 2.      #include <stdlib.h>
            • 3.      int main(){
            • 4.      int a=rand();
            • 5.      printf("%d\n",a);
            • 6.      return 0;
            • 7.      }
            • 编译后再运行几次,你会发现产生的随机数是相同的。实际上,rand() 函数产生的随机数是伪随机数,是根据一个数按照某个公式推算出来的,这个数我们称之为“种子”,但是这个种子在系统启动之后就是一个定值,我们需要用 srand() 来进行播种,即在int a前加一句:
              • 1.      srand((unsigned)time(NULL)); //这里利用时间进行播种,需要time.h
      • sqrt( ) fabs( )  pow( )  sin( )
    • 6.6.3 malloc
      • malloc的返回类型是 void *
        • int  *p;
        • p = (int *)malloc(2);
        • p = (int *)malloc(sizeof(int));以上两个等价

 

 

 

 

posted @ 2018-11-24 22:26  Zander_Zhao  阅读(849)  评论(0编辑  收藏  举报