• C++——指针---指向数组的指针---指向字符串的指针--指向函数的指针--指针的指针--指针的引用


    一、指向数组的指针

    • 代码示例1:
      • 1 int main()
        2 {
        3     int a[10]={0,2,4,6,8,10,12,14,16,18};
        4     int *p;
        5     for(p=&a[0];p<&a[0]+10;p++)
        6         printf("%d ",*p);
        7 }
    • 代码示例2:
      • int a[10]={0,2,4,6,8,10,12,14,16,18};
        int *p;
        p=a;
        printf("%d
        ",*(a+5));//注意加括号,否则就是输出“a指向的值加5”了
        
        
        int sum(int *a,int n)
        {
            int ans=0;
            for(int i=1;i<=n;i++)
                ans+=a[i];
            return ans;
        }



    二、指向字符串的指针

    • 示例代码:
      • 1 char *pstr=”C++ is a object_oriented language”; 
        2 cout<<pstr<<endl;//直接打印整个字符串而不是字符串第一个字母的地址
        3 //将字符串常量的第一个字符的地址赋给指针。字符串常量存储在字符串常量区。
        4 //区分指针常量与常量指针。这里是一个常量指针,即指针指针指向的内容不可以改变,但指针本身可以改变,可以指向其他变量。



    三、指向函数的指针

      1、指向函数的指针:

    一个函数的函数名就是一个指针,它指向函数的代码。一个函数的地址就是该函数的进入点。函数的调用可以通过函数名,也可以通过指向函数的指针来调用。

      2、指向函数的指针的定义:

    • int (*p)(int i,int j);//p是一个指针,他指向一个函数,该函数有两个整形参数,返回值为int类型。p首先与*结合,表明p是一个指针。然后再与()结合,表明这个指针指向的是一个函数。指向函数的指针也称为函数指针。
    • 需要与返回值是指针的函数进行区别:int *fun(int i,intj);
    • 函数指针需要将一个函数的地址赋给它,有以下两种写法:
      • int (*fun)(int x,int y);
        fun=&Function;
        fun=Function;//这里取地址运算符&不是必须的,因为函数名本身就表示函数的地址。
    • 函数指针的调用:
      • x=(*fun)();
        x=fun();
        //两种调用方式都可以,尽量使用第一种调用方式,因为可以清楚地指明这时通过指针的方式来调用函数。

    • 指向函数的指针的应用:1:菜单选择的实现(通过函数指针的数组) 2:函数指针作为函数的参数
      • 函数指针的数组:菜单选择的实现
        • 在一个工资管理系统中有如下功能:1.添加员工。2.删除员工。3.修改员工信息。4.打印工资单。5.打印汇总表。6.退出。设计中一般把每个功能设计成一个函数。如add,delete,modify,printslary,printreport。主程序是一个循环,显示所有功能和他的编号。根据输入的编号调用相应的函数。
        • 代码1:不使用函数指针实现时:
          •  1 int main()
             2 { int select;
             3   while(1) {     
             4    cout << "1--add 
            ";
             5    cout << "2--delete
            ";
             6    cout << "3--modify
            ";
             7    cout << "4--print salary
            ";
             8    cout << "5--print report
            ";
             9    cout << "0--quit
            ";
            10    cin >> select;
            11 
            12   switch(select) 
            13   {
            14   case 0: return 0;
            15   case 1: add(); break;
            16   case 2: erase(); break;
            17   case 3: modify(); break;
            18   case 4: printSalary(); break;
            19   case 5: printReport(); break;
            20   default: cout << "input error
            ";
            21   }
            22  }
            23 }

             代码太长,如果功能有一万个就要写很长。

        • 代码2:使用函数指针实现:
          •  1 int main()
             2 { int select;
             3   void (*func[6])() = {NULL, add, erase, modify, printSalary, printReport};//定义函数指针的数组,注意写法!
             4   while(1) { 
             5   cout << "1--add 
            ";
             6   cout << "2--delete
            ";
             7   cout << "3--modify
            ";
             8   cout << "4--print salary
            ";
             9   cout << "5--print report
            ";
            10   cout << "0--quit
            ";
            11   cin >> select;
            12   if (select == 0) return 0;
            13   if (select > 5) 
            14   cout << "input error
            "; 
            15   else func[select]();
            16     }
            17 }

             代码第3行定义了一个函数指针的数组。

      • 函数指针作为函数参数:
        • 设计一个通用的冒泡排序函数,可以排序任何类型的数据。如何表示要排序的数据:将快速排序设计成一个函数模板,将待排序的数据类型设计成模板参数,不同的数据类型有不同的比较方式:向排序函数传递一个比较函数来解决。
        • 代码示例1:冒泡排序:
          •  1 void sort(int a[], int size)
             2 {   bool flag;//用于冒泡中提前结束冒泡
             3     int i, j;
             4     for (i = 1; i < size; ++i) {
             5         flag = false;
             6         for (j = 0; j <size - i; ++j)   
             7         if (a[j+1] < a[j])  {   
             8            int tmp = a[j];
             9            a[j] = a[j+1];
            10            a[j+1] = tmp;
            11            flag = true;
            12         }
            13            if (!flag) break;    
            14     }
            15 }
            上述代码的缺点是只能用于整形数的排序,现在写一个可以适用于任意类型不符合排序规则的,并把排序规则写在函数里边。
        • 示例代码2:适合任意类型的排序函数,不符合排序规则的写在排序规则里
          •  1 template <class T>//使用函数模板
             2 void sort(T a[], int size, bool (*f)(T,T))
             3 bool flag;//用于冒泡中提前结束冒泡
             4 int i, j;
             5 for (i = 1; i < size; ++i) {
             6         flag = false;
             7         for (j = 0; j <size - i; ++j)   
             8         if (f(a[j+1],a[j]))  //用函数f(T,T)来表示排序规则
             9         {   
            10            int tmp = a[j];
            11            a[j] = a[j+1];
            12            a[j+1] = tmp;
            13            flag = true;
            14         }
            15            if (!flag) break;    
            16     }
            17 }
            18 //排序规则
            19 bool decreaseInt(int x, int y) {return y<x;}
            20 bool increaseString(char *x, char *y)  {return strcmp(x,y)<0;}
            21 int main()
            22 {
            23        int a[] = {3,1,4,2,5,8,6,7,0,9}, i;
            24        char *b[]= {"aaa","bbb","fff","ttt","hhh","ddd","ggg","www","rrr","vvv"};
            25  
            26        sort(a, 10,  decreaseInt);
            27        for ( i = 0; i < 10; ++i) cout << a[i] << "	";
            28        cout << endl;  
            29  
            30             sort(b, 10, increaseString );
            31        for (i = 0; i < 10; ++i) cout << b[i] << "	";
            32        cout << endl;
            33 
            34       return 0;
            35 }

             附上作者原文:长见识了。原文:https://blog.csdn.net/Wu_qz/article/details/81274158 


        


    • 指向函数的指针的应用示例:
    • 示例代码1:
      •  1 #define  GET_MAX     0
         2 #define  GET_MIN     1
         3  
         4 int get_max(int i,int j)
         5 {
         6     return i>j?i:j;
         7 }
         8  
         9 int get_min(int i,int j)
        10 {
        11     return i>j?j:i;
        12 }
        13  
        14 int compare(int i,int j,int flag)
        15 {
        16     int ret;
        17  
        18     //这里定义了一个函数指针,就可以根据传入的flag,灵活地决定其是指向求大数或求小数的函数
        19     //便于方便灵活地调用各类函数
        20     int (*p)(int,int);
        21  
        22     if(flag == GET_MAX)
        23         p = get_max;
        24     else
        25         p = get_min;
        26  
        27     ret = p(i,j);
        28  
        29     return ret;
        30 }
        31  
        32 int main()
        33 {
        34     int i = 5,j = 10,ret;
        35  
        36     ret = compare(i,j,GET_MAX);
        37     printf("The MAX is %d
        ",ret);
        38  
        39     ret = compare(i,j,GET_MIN);
        40     printf("The MIN is %d
        ",ret);
        41  
        42     return 0 ;
        43 }
    • 示例代码2:
      •  1 #include <stdio.h>
         2 #include <string.h>
         3  
         4 void check(char *a,char *b,int (*cmp)(const char *,const char *));
         5  
         6 main()
         7 {
         8     char s1[80],s2[80];
         9     int (*p)(const char *,const char *);
        10  
        11     //将库函数strcmp的地址赋值给函数指针p
        12     p=strcmp;
        13  
        14     printf("Enter two strings.
        ");
        15     gets(s1);
        16     gets(s2);
        17  
        18     check(s1,s2,p);
        19 }
        20  
        21 void check(char *a,char *b,int (*cmp)(const char *,const char *))
        22 {
        23     printf("Testing for equality.
        ");
        24     //表达式(*cmp)(a,b)调用strcmp,由cmp指向库函数strcmp(),由a和b作调用strcmp()的参数。
        25     //调用时,与声明的情况类似,必须在*cmp周围使用一对括号,使编译程序正确操作,
        26     //同时这也是一种良好的编码风格,指示函数是通过指针调用的,而不是函数名。
        27     if((*cmp)(a,b)==0)
        28         printf("Equal
        ");
        29     else
        30         printf("Not Equal
        ");
        31 }
    • 示例代码3:
      •  1 #include <stdio.h>
         2 #include <ctype.h>
         3 #include <stdlib.h>
         4 #include <string.h>
         5 //check()函数的第3个函数是函数指针,就可以根据具体情况传入不同的处理函数
         6 void check(char *a,char *b,int (*cmp)(const char *,const char *));
         7  
         8 //自定义的比较两个字符串的函数
         9 int compvalues(const char *a,const char *b);
        10  
        11 main()
        12 {
        13     char s1[80],s2[80];
        14  
        15     printf("Enter two values or two strings.
        ");
        16     gets(s1);
        17     gets(s2);
        18  
        19     //如果是数字,则用函数指针传入数字比较函数进行处理
        20     if(isdigit(*s1)){
        21         printf("Testing values for equality.
        ");
        22         check(s1,s2,compvalues);
        23     }
        24     //如果是字符串,则用函数指针传入库函数strcmp进行处理
        25     else{
        26         printf("Testing strings for equality.
        ");
        27         check(s1,s2,strcmp);
        28     }
        29 }
        30  
        31 void check(char *a,char *b,int (*cmp)(const char *,const char *))
        32 {
        33     if((*cmp)(a,b)==0)
        34         printf("Equal.
        ");
        35     else
        36         printf("Not Equal.
        ");
        37 }
        38  
        39 int compvalues(const char *a,const char *b)
        40 {
        41     if(atoi(a)==atoi(b))
        42         return 0;
        43     else
        44         return 1;
        45 }



    四、指针的指针与指针的引用

      1、指针的指针地引入:

    当我们把指针作为一个参数传给一个函数的时候,其实是把指针(即实参)复制给函数的形参,传递的是一个副本。也可以说传递指针是指针的值传递。

    当我们在函数内部修改指针时会出现问题。在函数里修改指针只是修改指针的copy即副本,而不是指针本身。原来的指针还保留着原来的值。详见下边的代码。


    • 指针作为实参传递给函数形参。代码示例如下:
      •  1 int m_value = 1;
         2 
         3 void func(int *p)
         4 {
         5     p = &m_value;
         6 }
         7 
         8 int main(int argc, char *argv[])
         9 {
        10     int n = 2;
        11     int *pn = &n;
        12     cout << *pn << endl;
        13     func(pn);
        14     cout << *pn <<endl;
        15     return 0;
        16 }
        17 //输出结果为2,2   而不是想象中的2,1,
    • 指针的指针作为实参传递给函数的形参。代码示例如下:
      •  1 void func(int **p)
         2 {
         3      // 也可以根据你的需求分配内存
         4     *p = new int;
         5     **p = 5;
         6 }
         7 
         8 int main(int argc, char *argv[])
         9 {
        10     int n = 2;
        11     int *pn = &n;
        12     cout << *pn << endl;
        13     func(&pn);
        14     cout << *pn <<endl;
        15     return 0;
        16 }
      • 输出结果:2,5,
      • 对于func(int **p)这个函数
        • p是一个指针的指针,在这里不对它进行修改,一旦修改将会丢失这个指针指向的指针地址
        • *p是一个被指向的指针,是一个地址。如果修改它,修改的便是被指向的指针的内容。
        • **p则是main()函数中*pn的内容
    • 指针的引用作为实参传递给函数的形参
      •  1 int m_value = 1;
         2 
         3 void func(int *&p)
         4 {
         5     p = &m_value;
         6 
         7     // 也可以根据你的需求分配内存
         8     p = new int;
         9     *p = 5;
        10 }
        11 
        12 int main(int argc, char *argv[])
        13 {
        14     int n = 2;
        15     int *pn = &n;
        16     cout << *pn << endl;
        17     func(pn);
        18     cout << *pn <<endl;
        19     return 0;
        20 }
      • 输出结果为2,5
        • p是指针的引用,main()函数里的*pn
        • *p:main函数中pn指向的内容。

    • 需要注意的是指针的初始化与指针的赋值及*运算符的区别:int *p =&a;这里的*不是取内容运算符。*p=2;这里的*则是取内容。

  • 相关阅读:
    头部尾部始终处于两端(适用于pc端和移动端)
    运用active和hover实现导航栏的页面切换
    POJ1423-阶乘的位数-Big Number
    大数阶乘
    n皇后
    4103:踩方格
    2815:城堡问题
    特殊回文数
    十六进制转十进制
    十六进制转八进制
  • 原文地址:https://www.cnblogs.com/southcyy/p/10262289.html
Copyright © 2020-2023  润新知