zoukankan      html  css  js  c++  java
  • C++ Primer Plus 笔记第七章

    复习函数基本知识:

      要使用C++函数,要完成工作:

         1. 提供函数基本知识;

         2. 提供函数原型;

         3. 调用函数

       库函数是已经定义和编译好的函数,同时可以使用标准库头文件提供其原型

         eg:标准头文件 cstring 中包含了 strlen() 和其它一些字符串相关的函数原型

    函数原型和函数调用:

       函数原型描述了函数到编译器的接口,将函数返回值的类型及参数类型和数量告诉编译器;

       double cube ( double x );   or  double cube ( double );    

       原型的功能:

        编译器正确处理函数返回值;

        编译器检查使用的参数数目是否正确;

        编译器检查使用参数类型是否正确,如果不正确,转换为正确的类型(可能的话)

    函数和数组:

      int sum_arr ( int * arr,int n )   //  数组的元素为 int 型,因此 正确的函数头传递参数为 int * arr

      int sum_arr ( int arr[ ],int n )  // 用 int arr[ ] 替换 int * arr ,含义相同。同时 int arr[ ] 还提醒用户 arr 不仅指向 int 而且是指向数组的第一个 int 

       在大多数情况下,C++和C语言一样,将数组名视为指针,存在两种例外:

        1. 数组声明,使用数组名来标记存储位置;

        2. 对数组名使用 sizeof 将得到整个数组的长度

       函数传递数组时,将数组的位置(地址)、包含的元素种类(类型)以及元素的数目(n变量)提交给函数;

       函数传递常规变量时,函数将使用变量的拷贝,但使用数组时,函数使用原来的数组;

       可以在被传递函数中,数组参数使用 const 限定符,保证原始数组数据不被修改(只读传入)

        int show_array ( const double arr[ ],int limit );  // 函数原型

    键盘输入数组并显示输入数组例程:

     1 #include<iostream>
     2 using namespace std;
     3 int fill_array(double ar[], int limit);
     4 void show_array(const double ar[],int n);   // const 可以防止修改数组内容
     5 
     6 int main()
     7 {
     8     const int arsize = 5;
     9     double ar[arsize];
    10     int n;
    11     n = fill_array(ar, arsize);    // 数组调用,将数组的首地址作为实参
    12     //cout << n<<endl;
    13     show_array(ar, n);                
    14 }
    15 
    16 // 输入数组
    17 int fill_array(double ar[], int limit) 
    18 {
    19     double res;
    20     int i;
    21     for ( i = 0; i < limit; i++)
    22     {
    23         cout << "Enter value #" << i + 1 << ": ";
    24         while (!(cin >> res))        // 判断是否正确读入数字,如果没有,进入循环
    25         {
    26             cin.clear();            // 重置输入,如果省略,程序将拒绝继续读取输入
    27             while (cin.get() != '
    ')        // 清除输入流中所有的错误输入到'
    '
    28                 continue;
    29             cout << "wrong! please enter number: 
    "
    30                 << "Enter value #" << i + 1 << ":";
    31         }
    32         if (res < 0)                // 负值输入将提前结束数组的输入
    33             break;
    34         ar[i] = res;
    35     }
    36     return i;
    37 }
    38 // 显示数组
    39 void show_array(const double ar[], int n)
    40 {
    41     for (int i = 0; i < n; i++)
    42         cout << ar[i] << endl;
    43 }

    自下而上的程序设计:

       通过数据类型和设计适当的函数来处理数据,然后将这些函数组合成一个程序;

       适合于OOP——它首先强调的数据表示和操纵

    使用数组区间的函数:

       对于处理数组的C++函数,必须将处理数组中的种类、数组的起始位置和数组中元素数量交给函数:

        1. 将数组的起始处的指针作为一个参数,将数组的长度作为第二个参数;

        2. 指定元素区间,通过传递两个指针完成,一个标识数组开头,一个标识数组尾部

       eg: 

        sum = sum_arr ( arr, arr+3 );                       // 函数调用,实参传入地址区间 

        int sum ( const int* begin,const int* end );// 函数头,形参为两个指向数组类型的指针(int*)

    指针和 const:

       可以使用两种不同的方式将 const 关键字用于指针:

        1. 让指针指向一个常量对象,防止使用该指针修改所指向的值;

        2. 将指针本身声明为常量

       声明一个指向常量的指针:

        int age = 39;

        const int * pt = &age;

        声明中 pt 指向一个 const int 因此不能使用 pt 修改这个值—— *pt 为常量不能修改

       还可以将 const 变量的地址赋给指向const的指针,不能将 const 的地址赋给常规的指针

       记住:如果数据类型不是指针,可以将 const 数据或非 const 数据的地址指向 const 指针

          不能将 const 数据赋给非 const 指针

        int * const finger = &sloth:

        指针 finger 本身被声明为 const,使得 finger 只能指向 sloth,但允许使用 finger 来修改 sloth 的值

    函数和二维数组:

       数组作为参数的函数,数组名被视为地址,相应的形参应为一个指针;

       int data[3][4] = { {1,2,3,4},  {9,8,7,6},  {2,4,6,8} };  // 声明

       int tatal = sum(data, 3);                                 // 调用

       两种函数原型(形参的形式):

         int sum (int (*ar2) [4],int size );    // 声明一个由4个指向 int 的指针组成的数组,括号不能省

         int sum (int ar2[ ][4],int size);       // 可读性更强

       在函数定义中使用二维数组,最简单的办法是将 ar2 看作一个二维数组的名称

       ar2 实际上是一个指针,必须对 ar2 执行两次解除引用才能得到数据:

        最简单的方式:ar2[r][c];

        ar2[r][c] = *(*(ar2 + r) + c);    // same thing

    函数和C-风格字符串:

       将字符串作为参数时意味着传递的是地址;

       表示字符串的方式有3种:

        1. char 数组

        2. 用引括号起的字符串常量

        3. 被设置为字符串的地址的 char 指针

       将字符串作为参数来传递,实际传递的是字符串的第一个字符的地址,形参声明应为 char*:

        int c_in_str (const char * str,char ch); // 使用指针表示法

        int c_in_str (const char str[],char ch); // 也可以使用数组表示法

       处理字符串中字符的标准方式:

    1 while (*str)        // until *stt == ''
    2 {
    3     statement;
    4     str++      // 将指针增加一个字节 
    5 }

    返回C-风格字符串的函数:

       函数无法返回一个字符串,但是可以返回字符串的地址;

       char * buildstr ( char c,int n )

    函数和结构:

       为结构编写函数比为数组编写函数简单,结构变量相比于数组更接近于单值变量;

       函数可以使用原始结构的拷贝,也可返回结构(因为结构可以互相赋值);

       结构名只是结构的名称,要获得结构的地址,必须使用地址操作符 &;

    处理结构的函数例程:

     1 #include<iostream>
     2 #include<cmath>
     3 using namespace std;
     4 
     5 struct polar {
     6     double distance;
     7     double angle;
     8 };
     9 struct rect {
    10     double x;
    11     double y;
    12 };
    13 polar rect_to_polar(rect xypose);
    14 void show_polar(polar rrpose);
    15 int main()
    16 {
    17     polar rppose;
    18     rect xypose;
    19     cout << "Enter pose x and y or type 'q' to quiz: ";
    20     while (cin>>xypose.x>>xypose.y)
    21     {
    22 
    23         rppose = rect_to_polar(xypose);
    24         show_polar(rppose);
    25         cout << ("Continue Enter x and y or type 'q' to quiz: ");
    26 
    27     }
    28     return 0;
    29 }
    30 
    31 polar rect_to_polar(rect xypose)
    32 {
    33     polar rppose;
    34     rppose.distance = sqrt(xypose.x*xypose.x + xypose.y*xypose.y);
    35     rppose.angle = atan2(xypose.y, xypose.x);
    36     return rppose;
    37 }
    38 
    39 void show_polar(polar rppose)
    40 {
    41     const double rad_to_deg = 57.29577951;
    42 
    43     cout << "distance = " << rppose.distance << endl;
    44     cout << "angle = " << rppose.angle*rad_to_deg << " degrees
    ";
    45 
    46 }

     传递结构地址例程:

       与传递结构本身不同之处:

        1. 调用函数时,将结构地址(&pplace)而不是结构本身(pplace);

        2. 将形参声明为指向 polar 的指针,即 polar* 类型;

        3. 形参指针而不是结构,因此应使用间接成员操作符(->)而不是(.);

        4. 传递地址而不是复制,函数可能不在需要返回值,使用 void

     1 #include<iostream>
     2 #include<cmath>
     3 using namespace std;
     4 
     5 struct polar {
     6     double distance;
     7     double angle;
     8 };
     9 struct rect {
    10     double x;
    11     double y;
    12 };
    13 void rect_to_polar(const rect * xypose, polar* rppose);
    14 void show_polar(const polar * rppose);
    15 int main()
    16 {
    17     polar rppose;
    18     rect xypose;
    19     cout << "Enter pose x and y or type 'q' to quiz: ";
    20     while (cin >> xypose.x >> xypose.y)
    21     {
    22 
    23         rect_to_polar( &xypose, &rppose );
    24         show_polar( &rppose );
    25         cout << ("Continue Enter x and y or type 'q' to quiz: ");
    26 
    27     }
    28     return 0;
    29 }
    30 
    31 void rect_to_polar(const rect* xypose, polar * rppose)
    32 {
    33     rppose->distance = sqrt(xypose->x*xypose->x + xypose->y*xypose->y);
    34     rppose->angle = atan2(xypose->y, xypose->x);
    35 }
    36 
    37 void show_polar(const polar * rppose)
    38 {
    39     const double rad_to_deg = 57.29577951;
    40 
    41     cout << "distance = " << rppose->distance << endl;
    42     cout << "angle = " << rppose->angle*rad_to_deg << " degrees
    ";
    43 
    44 }

     函数和 string 对象:

       C++如果需要多个字符串,可以声明一个 string 对象数组,而不是二维 char 数组;

       以下例程声明了一个 string 对象数组,并将该数组传递给一个函数以显示其内容:

     1 #include<iostream>
     2 #include<string>
     3 using namespace std;
     4 const int SIZE = 5;
     5 void display(const string list[], int n);
     6 
     7 int main()
     8 {
     9     string list[SIZE];    // 声明 string 数组,每一个元素为一个 string 对象
    10     cout << "Enter your " << SIZE << " favotite astronomical sights: 
    ";
    11     for (int i = 0; i < SIZE; i++)
    12     {
    13         cout << i + 1 << ": ";    
    14         getline(cin, list[i]);       // 读取一个字符串     
    15     }
    16 
    17     cout << "Your list: 
    ";
    18     display(list, SIZE);
    19 
    20     return 0;
    21 }
    22 
    23 void display(const string list[], int n)
    24 {
    25     for (int i = 0; i < n; i++)
    26         cout << list[i] << endl;
    27 }

        该例程中,除了函数 getline() 外,程序像对待内置类型(int)一样对待 string 对象

    递归:

       函数调用自己成为递归;

       每个递归都创建自己的一套变量;

    函数指针:

       可以编写将另一个函数的地址作为参数的函数;

       这种方法与调用函数相比,允许在不同的时间传递不同的函数地址;

    函数指针基础知识:

       获取函数地址;

       声明函数的指针;

       使用函数指针来调用函数

       1. 获取函数地址

        只要使用函数名即可,如果 think() 是一个函数,则 think 就是该函数的地址

        要区分函数的地址和函数的返回值:

          process ( think );  // 参数为函数地址,使得函数 process 能够在函数内部调用 think() 函数

          thought ( think() );     // 参数为函数的返回值,先调用 think() 函数,其返回值传给 thought

       2. 声明函数指针

        声明函数指针时,必须指定指针指向的函数类型:

          double pam ( int );      // 原型

          double ( *pf ) ( int ); // 指针类型声明,将 pam 替换为了 (*pf),(*pf)是函数,pf 就是函数指针

          pf = pam;      // 将相应的函数地址赋给指针

        提示: 要声明指向特定类型的函数指针,可以先编写这种函数的原型,然后用(*pf)替换函数名

        注意: 函数地址赋给函数指针时,特征标和返回返回类型必须相同

       3. 使用指针来调用函数

        void estimate ( int lines,double (*pf) (int) );   // 函数原型

        estimate ( 50, pam);            // 让 estime() 使用 pam() 函数

        (*pf) 扮演的角色与函数名相同,使用(*pf)时,只需要将它看成函数名

          double pam ( int );

          double (*pf) (int);

          pf = pam;       // 函数指针指向函数 pam()

          double x = pam (4);  // 使用函数名调用函数pam()

          double y = (*pf) (5);  // 使用函数指针调用函数pam()

          double y = pf(5);    // C++允许像使用函数名那样使用 pf

    复习题:

     函数 judge() 的返回值为 int,他将这样一个函数地址作为参数:将 const char 指针作为参数,返回一个 int 值,编写函数原型:

        int judge ( int (*pf) ( const char * ) )

      

        

           

     

     

      

              

         

      

        

     

       

          

  • 相关阅读:
    困扰多年的eclipse项目编码问题!
    什么是专注?什么是执行力?
    关于图表的理解
    去重与替换
    pandas 文本操作
    pandas 数值计算
    DatetimeIndex 时间序列
    Datatime 时间模块
    Numpy 常用方法
    Python迭代器 Iterator
  • 原文地址:https://www.cnblogs.com/kidycharon/p/9689357.html
Copyright © 2011-2022 走看看