我是靠谱客的博主 光亮牛排,最近开发中收集的这篇文章主要介绍C++回炉之_C++PrimerPlus_第七章 函数 -- C++的编程模块(二),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

函数和二维数组

  • 使用二维数组作为参数, 必须指定第二维的维数 – 元素的类型

    • 表示arr为一个数组名,而数组的每一个元素也是一个数组, 由2个int组成
    • 即arr的类型是指向由2个int组成的数组的指向
    • 其中的括号必不可少,因为 int *arr[2]表示由2个指向int的指针组成的数组 – 函数参数不能为数组
    • 另一种格式 – int sum(int arr[][2], int n);二者含义相同
    • 两个原型都指出, arr是指针而非数组,这是至关重要的一点
    int sum(int (*arr)[2], int n) {
    int res = 0;
    for(int i = 0; i < n; ++i)
    for(int j = 0; j < 2; ++j) res += arr[i][j];
    return res;
    }
    int a[3][2] = { {1, 2}, {3, 4}, {5, 6} };
    cout << sum(a, 3) << endl;
    

函数和C风格字符串

  • 将字符串作为参数

    • 使用 char* (指向char类型的指针) – void show_str(const char* str);
    • 也可使用 void show_str(const char str[]);
    void show_str(const char* str) {
    while (*str) {
    cout << *str;
    ++str;
    }
    cout << endl;
    }
    char str[] = "hello world";
    show_str(str);
  • 将字符串作为返回值

    • 返回字符串的地址即可
    
    #include <iostream>
    using namespace std;
    char* build_str(char ch, int n) {
    char* p_str = new char[1+n];
    // 虽然p_str在函数结束时会被释放
    p_str[n] = '';
    while(n-- > 0) p_str[n] = ch;
    return p_str;
    // 但 new 的内存还在
    }
    int main() {
    char* str = build_str('d', 10);
    cout << str << endl;
    delete [] str;
    // 所以需要手动delete此内存块
    }
    

函数和结构体

  • 像对待基本数据类型一样对待结构体即可

    
    #include <iostream>
    using namespace std;
    struct pos {
    int x, y;
    };
    pos sum_pos(pos a, pos b) {
    pos res;
    res.x = a.x + b.x;
    res.y = a.y + b.y;
    return res;
    }
    int main() {
    pos m{1, 2};
    pos n = {3, 4};
    pos r = sum_pos(m, n);
    cout << r.x << " " << r.y << endl;
    }
    
  • 传递结构体的地址 – 以节省时间和空间

    pos* sum_pos(const pos* a, const pos* b) {
    pos* res = new pos;
    res->x = a->x + b->x;
    res->y = a->y + b->y;
    return res;
    }
    pos* r = sum_pos(&m, &n);
    cout << r->x << " " << r->y << endl;
    delete r;
    
    • 传递地址的话可以将结果作为指针直接放在参数中,而不用返回值
    void sum_pos(const pos* a, const pos* b, pos* res) {
    res->x = a->x + b->x;
    res->y = a->y + b->y;
    }
    pos r;
    sum_pos(&m, &n, &r);
    cout << r.x << " " << r.y << endl;
  • string对象, array对象 等,都可看作基本类型, 像结构体一样在函数中使用

递归函数

  • 除了main函数外,函数都可以调用自身
  • 一个递归函数必须有递归调用的终点,否则将会无限调用下去
  • 每一个递归过程中的函数都是独立的
  • 递归的过程与普通函数调用的过程类似
  • 只需将函数里对自己本身的调用也看作是对其他函数的调用(只不过功能相同)即可

    // 求n的阶乘
    int factorial(int n) {
    if(n == 1) return 1;
    // 循环终止条件
    return n * factorial(n-1);
    // 递归
    }
    // 快速排序 -- O(nlogn)
    void quick_sort(int a[], int L, int R) {
    //[L, R]
    if(L >= R) return;
    // 循环终止条件
    int x = L, y = R, p = a[L];
    while(x < y) {
    //最后找到的x即为划分地
    while(x < y && a[y] >= p) --y; a[x] = a[y];
    //y向左到比p小的,移到左边去
    while(x < y && a[x] <= p) ++x; a[y] = a[x];
    //x向右到比p大的,移到右边去
    }//end 划分
    a[x] = p;
    quick_sort(a, L, x-1); quick_sort(a, x+1, R);
    // 递归
    }
    int a[] { 5, 3, 2 ,1, 4};
    quick_sort(a, 0, 4);
    for(int i = 0; i < 5; ++i) cout << a[i] << endl;

函数指针初探

  • 函数的地址 – 函数名即为函数的地址(不带括号)
  • 声明函数指针 – 使用(*pf) 替代函数名

    bool cmp(int a, int b);
    bool (*p_cmp)(int a, int b);
    • 由于 (*p_cmp)cmp 等价,所以 (*p_cmp) 也是函数,则 p_cmp 就是函数指针了
    • 不加括号的话 bool *p_cmp(int a, int b); 为一个返回bool*的函数,而非函数指针
  • 给函数指针赋值

    • 赋值的条件是函数参数和返回类型与指针都一致
    p_cmp = cmp
  • 使用函数指针调用函数

    • 可以使用(*pf)调用,也可以直接使用指针名作为函数名调用 – amazing
    cout << (*p_cmp)(1, 2) << endl;
    cout << p_cmp(1, 2) << endl;
  • 一个短而有力的例子

    
    #include <iostream>
    using namespace std;
    bool cmp(int a, int b) { return a > b; }
    bool cmp_2(int a, int b) { return a <= b; }
    //返回两个数的较大值 -- 自定义比较规则
    int max_i(int a, int b, bool (*p_cmp)(int a, int b)) {
    if(p_cmp(a, b)) return a;
    else return b;
    }
    int main() {
    cout << max_i(1, 2, cmp) << endl;
    cout << max_i(1, 2, cmp_2) << endl;
    }
    

    输出结果为

    2
    1

  • 更复杂的用法

    • 函数指针的数组

      int (*p_s[3])(int, int);
      • [] 的优先级高于 *, 故(*p_s[3])表示一个包含三个指针的数组
    • 指向 函数指针数组 的指针

      int (*(*p_ps)[3])(int, int);
      // 有些小变态
      • p_s替换成 (*p_ps)即可
      • 加括号表示p_ps是一个指针,它指向一个包含3个元素的数组
    • 可使用auto 或typedef简化代码

      • auto 只能用于单值初始化,而不能用于初始化表
      • 使用typedef 可声明函数指针的别名 – 使代码更容易理解
      typedef int (*p_fun)(int, int);
      p_fun p1 = s1;
      p_fun pa[3] = {s1, s2, s3};
      p_fun (*pd)[3] = &pa;
    • 一个短而有力例子

      
      #include <iostream>
      using namespace std;
      int s1(int a, int b) { return a + b + 0; }
      int s2(int a, int b) { return a + b + 1; }
      int s3(int a, int b) { return a + b + 2; }
      int main() {
      // 函数指针的数组
      int (*p_s[3])(int, int) = { s1, s2, s3};
      for(int i = 0; i < 3; ++i) {
      cout << p_s[i](1, 2) << " ";
      // 等价于 cout << (*p_s[i])(1, 2) << endl;
      }
      // 指向 函数指针数组 的指针
      // 也可用 auto p_ps = &p_s; 简化
      int (*(*p_ps)[3])(int, int) = &p_s;
      for(int i = 0; i < 3; ++i) {
      cout << (*p_ps)[i](1, 2) << " ";
      // 等价于 cout << (*(*p_ps)[i])(1, 2) << endl;
      }
      }
      

最后

以上就是光亮牛排为你收集整理的C++回炉之_C++PrimerPlus_第七章 函数 -- C++的编程模块(二)的全部内容,希望文章能够帮你解决C++回炉之_C++PrimerPlus_第七章 函数 -- C++的编程模块(二)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部