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\n",*(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 \n";
           5    cout << "2--delete\n";
           6    cout << "3--modify\n";
           7    cout << "4--print salary\n";
           8    cout << "5--print report\n";
           9    cout << "0--quit\n";
          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\n";
          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 \n";
           6   cout << "2--delete\n";
           7   cout << "3--modify\n";
           8   cout << "4--print salary\n";
           9   cout << "5--print report\n";
          10   cout << "0--quit\n";
          11   cin >> select;
          12   if (select == 0) return 0;
          13   if (select > 5) 
          14   cout << "input error\n"; 
          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] << "\t";
          28        cout << endl;  
          29  
          30             sort(b, 10, increaseString );
          31        for (i = 0; i < 10; ++i) cout << b[i] << "\t";
          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\n",ret);
      38  
      39     ret = compare(i,j,GET_MIN);
      40     printf("The MIN is %d\n",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.\n");
      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.\n");
      24     //表达式(*cmp)(a,b)调用strcmp,由cmp指向库函数strcmp(),由a和b作调用strcmp()的参数。
      25     //调用时,与声明的情况类似,必须在*cmp周围使用一对括号,使编译程序正确操作,
      26     //同时这也是一种良好的编码风格,指示函数是通过指针调用的,而不是函数名。
      27     if((*cmp)(a,b)==0)
      28         printf("Equal\n");
      29     else
      30         printf("Not Equal\n");
      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.\n");
      16     gets(s1);
      17     gets(s2);
      18  
      19     //如果是数字,则用函数指针传入数字比较函数进行处理
      20     if(isdigit(*s1)){
      21         printf("Testing values for equality.\n");
      22         check(s1,s2,compvalues);
      23     }
      24     //如果是字符串,则用函数指针传入库函数strcmp进行处理
      25     else{
      26         printf("Testing strings for equality.\n");
      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.\n");
      35     else
      36         printf("Not Equal.\n");
      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;这里的*则是取内容。

 

 

 

 

 

posted @ 2019-01-13 12:34  long_ago  阅读(629)  评论(0编辑  收藏  举报