第五章 C++函数 

5.2 函数的调用

5.2.1函数递归调用(P113)

函数直接或间接调用自身.

传递参数4

阶乘fact(4)

返回24---------4*fact(3)----- 传递参数3

4*6

返回6

5.1 n!的阶乘

编程求出113中每一个数的阶乘值 JC.CPP

#include<iostream.h>

long f(int n);

void main( )

{

int n;

long p;

cout<<"\n";

cout<<"  程序运行结果:\n";

cout<<"\n";

for(n=1;n<=13;n++)

{

p=f(n);

cout<<"  "<<n<<"!="<<p<<"\n";

}

}

long f(int n)                              // n  

{                                               // 5   5*f(4)

long h;                                      // 4   4*f(3)

if (n>1) h=(long)n*f(n-1);        // 3  3*f(2)

else h=1;                                  // 2   2*f(1)

return h;                                   // 1  

}

 

5.3 函数原形与头文件(P117)

  1.程序结构:头文件保存函数原型,程序文件实现(定义)函数,

    主程序测试函数。

  2.函数:原型说明、定义、调用。

    3.数据流程 :变量--->实参--->形参--->计算--->返回--->显示。

    4.函数原形(prototype),例如:double  Area(double r);

 例5.4 求圆面积Area(P119)

 1: //头文件Area.h

 2: double Area(double r)    //原形说明

 

 4: //程序文件Area.cpp

 5: #include "Area.h"         //包函头函数

 

 7: #define PI 3.14 16

 

 9:  double Area(double r)    //定义函数   3.传给形参 r

11: return  r*r*PI;                //函数计算

 

14: //主程序文件 Areat.cpp

 

16: #include"Area.h"

 

23: cin>>radius;                  //变量radius取值

 

28: area=Area(radius);       //调用函数  2.实参radius   5.返回值给area

29: cout<<"area="<<area  // 6.显示area

5.4 函数调用中的参数传递(P122)

例如:

......

void main( ){

int a=3,b=4;              //形参

add(a,b);                   //函数调用

......

}

int add(int x,int y)    //函数定义  实参

......

程序运行时实际参数的值(a=3,b=4)

顺序对应传递给形式参数(x, y).

5.4.2 数组参数

  例5.5 计算参数数组中的元素和

3:int sum(int array[ ],int size);     //函数说明

 

8:int sum(int array[ ],int size )     //函数定义  3.传给形参

 

11:for(int i=0;i<size;i++)s+=array[i];  //求和计算

12:return s;  //返回s

 

21:int v1[ ]={1,2,3,4,5};  // 1.数组初始化

22:cout<<sum(v1,5);        // 2.实参  6.显示

 

5.4.3 可选参数(P127)

 例如:int f(int a,char b, char c='Z',char *s="READY");

       其中:c,*s有默认值

5.5 内联(inline)函数

    inline int add2(int n){return n+2;} 

    函数调用可直接用函数体代码。

5.6 函数重载与名字混成

  1.函数重载(P129)

    同名函数,参数数量或类型不同

    int add(int a,int b){ };

    long add(long a,long b){ };

   2.名字混成(P130)

          例:外部名字同 add

                  内部名字不同 add+参数信息

5.7 函数和变量的作用域(P131)

5.7.1函数的作用域:全局,文件作用域(static)。

5.7.2 变量的作用域和生存期(P132)

  1.全局变量:定义于函数外部;

  2.局部变量:定义于函数内部,

    auto自动,register寄存器,static静态。

5.8 函数模板(P135)

  例如:函数 Max(x,y)的类型说明

        int Max(int a,int b){return a>b? a:b;}

        long Max(long a,long b){return a>b? a:b;}

  例如:Max模板

        template<class T>      //T是虚拟类型参数

        T Max(Tx,Ty)           //用实参的实际类型替代虚拟类型

        {

          return(x>y)?x:y;

        };

  例如:cout<<Max(3,5);

        实参的实际类型int,生成函数实例如下:

        int Max(int a,int b){return a>b? a:b;}

预处理

1. 简单的宏定义(P)

形式:#define 宏标识符 字符串

功能:用常量表达式替换程序中的宏标识符.

#define PI 3.14149

#include<stdio.h>

main()

{

int r=2.0,s;

s=PI*r*r;

}

2. 带参数的宏定义(P)

形式:#defin 宏标识符(形式参数表)

   程序中 宏标识符(实际参数表)

功能:程序编译时实际参数的值(a+b,c+d)

   顺序对应传递给形式参数( m, n).

例如:#define MAX(m,n) ((m>n)? m:n)

   程序中 x=MAX(a+b,c+d);

   编译后 x=((a+b)>(c+d))? (a+b):(c+d)

3. 文件包含(P)

形式:#include"头文件名"

   #include<头文件名>

功能:程序文件包含另一文件的内容.

   " " 自建的头文件,按标准方式检索.

   < > 检索顺序:源程序文件目录,标准方式检索.

例如:#include"point.h"

   #include<iostream.h>

 

习题五(P142)

5-5 求多边形周长(参考P123, 实验P100)

1.2

3.4

5.6 p0 p1
7.8 p3 p2
   //头文件:保存函数原型arrownd.h

   double arrownd(double x[ ],double y[ ],int p);

   //程序文件:实现(定义)函数arrownd.cpp

   #include "arrownd.h"

   static double distance(double x1,double y1,double x2,double y2)

   {return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));}

    

   double arrownd(double x[ ],double y[ ],int p)

   {

    double s=0;

    for(int j=0;j<p-1;j++)

       s+=distance(x[j],y[j],x[j+1],y[j+1]);

     s+=distance(x[p-1],y[p-1],x[0],y[0]);

      return s;

    }

   //主程序:测试函数arrowndz.cpp

    #include <iostream.h>

    #include "arrownd.h"

    void main( )

    {

      x[ ]={1.2,3.4,3.4,1.2};

      y[ ]={5.6,5.6,7.8,7.8};

      cout<<arrownd(x[ ],y[ ],4);

    }

实验六 函数与程序设计(P41)

   2. 用递归调用对数组求和(P45)

a[5]

元素 a[0]

a[size-5]

a[1]

a[size-4]

a[2]

a[size-3]

a[3]

a[size-2]

a[4]

a[size-1]

地址 a a+1 a+2 a+3 a+4
内容 1 2 3 4 5

       int sumAll(int a[ ],int size)                  //3. 形参 a[ ], size

      {

        if(size= =1) 

          return a[size-1] ;

          return a[0]+ sumAll(a+1, size-1) ;   //4. 计算

        //或return a[0] ;

              return a[sinz-1]+ sumAll(a[size-1],size-1) ;

       }

       void main( )

       {

         int d[ ] = {1,2,3,4,5};              //1. 数组 d[ ]

         cout<<sumAll(d, sizeof(d)/sizeof(d[0]));

                                                         //2. 实参 数组d, 元素个数size

                                                         //5. 输出显示

       }

 

第六章 指针、引用和动态空间管理

6.1 指针概念和指针变量的定义

6.1.1 指针的概念

   例如:字符串“ABCD”的地址(P145)

起始地址 3690  A  
3691
3692
3693 D
3694 \0

  1. 指针:存储特定类型数据的地址。(P146)

  2.  空指针:地址值为0,符号常量NULL。

  3.  指针类型:指针所指数据的类型。

  4.  无类型(Void)指针:指向任何类型的数据。

 6.1.2 指针变量的定义和初始化(P146)

    格式:类型  * 变量名;

    例如:double d,  * pd=&d;

    表明:pd是指向某一双精度变量的指针变量。

地址 存储单元
指针变量 变量
pd d
3690 1.234

6.1.3  常值指针(P147)

地址

存储单元
指针变量

变量

常值指针 常值数据
指针不变 数据不变
* const s const * s

6.2 指针的基本操作(P148)

6.2.1 赋值:char c='X',* s = &c;

6.2.2 取变量的地址:操作符 &(取地址)

       int k,*p;

       p=&k;

    合并:int k,* p = &k;

6.2.3  间接访问:操作符 *(P148)

     int *pd,d;

     pd=&d;

   *pd=99;

   cout<<  *pd  <<' '<<  d;

         间接访问      直接访问

    *  &    k=3;

   相互抵消

地址 存储单元
指针变量 变量
pk k
3690 3

6.2.4  判断空指针(P149)

    如果p是空指针,则……

    if(P= =0)...

     if(P= =NULL)...

    if(!P)...

6.2.5 指针相减(P149)

    int n,m[12],*p1=&m[5],*p2=&m[10];

    n=p2-p1;

6.2.6 指针移动操作符(P150)

    移动n个单位:+、-、+ =、- =

    例如:int m[12],*p1=&m[6];

                p1- =3;

m[12]

元素 0 1 2 3 4 5 6 7 8 9 10 11
地址 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699    
内容       333     666          
指针       p1     p1          

    移动1个单位:++、- -

6.2.7 指针表达式的副作用(P151)

+ +

继续当

变量操作

(+ + pk)

操作结果

视同变量

          (pk + +)

操作结果

视同常量地址

+ +

不能当

变量操作

6.2.8 指针类型的强制转换(P152)

     short i=258;

     char * p=(char *) &i;    //用指针表示

     char p=(char) i              //用变量名表示(P33)

6.3 指针与数组

6.3.1 一维数组元素的指针访问方式(P156)

   1. 数组名指向0号元素。

    int  A[10];     //*A 等同 A[0]

   2. 设:int A[10],  * pa[i]=A;

    则:* (pa+i), pa[i] 访问同元素A[i]

   3. 等价关系:

    A[i]-----*(A+i)

    A[0]-----*(A+0)-----*A

   4. 不同方式访问数组元素(P156)

       int s[ ]={0,1,2,3,4,5},*p=s;

       cout<<*p<<p[1]<<*(p+2)<<s[3]<<p[4]<<*(s+5);

      输出:012345

6.3.2 多维数组元素的指针访问方式(P157)

      例如:int B[6][8];

      看成六个单元的一维数组:B[0] B[1] B[3] B[4] B[5]

      每个单元又是8个单元的一维数组:B[0]有元素b[0] b[1]..........b[7]

6.3.3 指向数组的指针(P159)

     例如:int w[3][4];

                int (*p1)[3][4]=&w;        //指向整个二维数组

                int (*p2)[4]=w;                //指向二维数组的首行

                int (*p3)=&w[0][0];        //指向二维数组的首元素

6.3.4 字符指针与字符串(P160)

     char *p2="string2";        //p2指向首元素s

     例6.2 设计函数STRLEN

     6:while(*d++)p++;      //字符串d

     12:cout<<STRLEN("ABCDEF");

6.3.5 指针数组与命令行参数(P161)

    1. 指针数组:数组的每个元素都是指针。

    例如:int * ip[10];

                double * dp[5][8];

  2. 命令行参数(P162)

        C:\>TREE  A:\

   例 6.4 显示命令参数(P163)

       //文件名doscomm.cpp

        3: #include<stdlib.h>

        5: int main(int argc,char * argv[ ])

        //argc:命令行参数个数

        //argv[ ]:全路径程序文件名,命令行参数

        9: cout<<"argv["<<i<<"]:">>argv[i]<<endl;

       执行:D:\DATA>DOSCOMM aaa bbb ccc

       显示:argv[0]:  D:\DATA\DOSCOMM.EXE

                   argv[1]:  aaa

        

6.4 指针与函数

6.4.1 指针参数(P167)

    1. 传指针:形参指针和实参指针指向同一数据。

      例如:(P168)

     int addTo(int data,  int * agg)           //3.形参

     {return *agg+=data;}                       //4.计算

     int total=0;                                        //1.变量

    addTo(5,&total);                                //2. 实参,  5.返回

    cout<<total;                                       //6.显示

    cout<<endl<<addTo(8,&total); 

    2. 定义常值指针:传递给被调用函数的数据只读不能改。(P168)

        例如:

    void f(const int U[ ])   //定义常值指针

    {

     cout<<U[3];                  //数据只读不能改

     U[3]=-1;

    }

   3.指向指针的指针传递给函数(P169)

   例6.6 查找第一个不含空格的连续字符,

         设形参为指向扫描指针的指针

     3:char * nextWord(char * *pp);  //pp是指向扫描指针的指针

     12:char * pw=word;

     13:while(* * pp && * * pp!=' ')* pw++=*(*pp)++; //复制词

     14:*pw='\0';                    //置字符串结束符

     24:char s[ ]="what is your name.",*ps=s;

     25:do cout<<nextWord(&ps)<<endl;while(ps);

 

main
 s  w h a t   i s  
          * *pp      
ps *pp              

 

nextWord
pw            pp      
                 
Word w h a t

 

        

6.4.2 返回指针值的函数(P171)

  例:截去参数字符串的尾部空格

      char * trim(char * s)      //指针值函数

      {

       char * P=s+strlen(s)-1;   //p指s最后字符

       while(p-s>=0 && * p=' ')p--;

       * (p+1)='\0';             //s字符串后置结束符

       return s;                 //返回字符指针s

      }

6.4.3 指向函数的指针(P172)

  例:int f1(int n){...}

      int (* pf1)(int);      //指向函数的指针

      pf1=f1;                //函数名指向该函数的指针

6.4.4 作为参数传递的函数(P173)

  例6.8 函数作为参数

    2: inline int add(int a,int b){return a+b;}

    4: inline int Double(int a, int b, int(* P)(int,int))

                                // 实参 add传给形参p

    5: return P(a,b)*2;         // 计算 add(a,b)*2

    13: cout<<Double(3,5,add);   // 显示

6.5 引用

6.5.1 引用变量和引用参数(P175)

  1. 引用(reference):给变量、函数取别名。

  例:int i=0;

      int &ir=i;    //给变量i取别名ir

      ir=2;         //等同i=2;

      int * p=&ir;  //等同int * p=&i;

  2. 用引用实现按地址传递参数

  例6.9 模板函数swap,变量地址通过指针参数传递。

    4: void swap(T * a, T * b)  //虚拟类型 T,指针形参 *a,*b

    12: swap(&x,&y);                      //实参类型 int,实参指针&x,&y

 

  例6.10 模板函数swap,变量地址通过引用参数传递。

    4: void swap(T &a, T &b)

                                          //虚拟类型 T,引用形参的地址 &a,&b

    12: swap(x,y);                        //实参是变量x,y

6.6 动态空间管理

6.6.1 非数组动态空间

     动态空间管理操作符(P180)

     new:申请动态空间,

     delete:释放动态空间。

  例:p1=new int(5);

      cout<<* p1;

      delete p1;

6.6.2 数组动态空间(P181)

  例:int * ap=new int[10];

         delete [ ]ap;

 

习题六(P192)6-6,6-8