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;这里的*则是取内容。