C++字符串与指针
在C++中可以用3种方法访问一个字符串(在第5章介绍了前两种方法)。
用字符数组存放一个字符串
【例】定义一个字符数组并初始化,然后输出其中的字符串。
#include <iostream> using namespace std; int main( ) { char str[]="I love CHINA!"; cout<<str<<endl; return 0; }</div>
运行时输出:
I love CHINA!</div>
用字符串变量存放字符串
【例】定义一个字符串变量并初始化,然后输出其中的字符串。
#include <string> #include <iostream> using namespace std; int main( ) { string str="I love CHINA!"; cout<<str<<endl; return 0; }</div>
用字符指针指向一个字符串
【例】定义一个字符指针变量并初始化,然后输出它指向的字符串。
#include <iostream> using namespace std; int main( ) { char *str="I love CHINA!"; cout<<str<<endl; return 0; }</div>
对字符串中字符的存取,可以用下标方法,也可以用指针方法。
【例】将字符串str1复制为字符串str2。
定义两个字符数组str1和str2,再设两个指针变量p1和p2,分别指向两个字符数组中的有关字符,通过改变指针变量的值使它们指向字符串中的不同的字符,以实现字符的复制。
#include <iostream> using namespace std; int main( ) { char str1[]="I love CHINA!",str2[20],*p1,*p2; p1=str1;p2=str2; for(;*p1!='\\0';p1++,p2++) *p2=*p1; *p2='\\0'; p1=str1;p2=str2; cout<<"str1 is: "<<p1<<endl; cout<<"str2 is: "<<p2<<endl; return 0; }</div>
运行结果为:
str1 is: I love CHINA! str2 is: I love CHINA!</div>
这个例子用来说明怎样使用字符指针。其实,对例6.13来说,用string变量来处理是十分简单的:
string str1=″I love CHINA!″,str2; //定义string变量 str2=str1; //将str1复制到str2</div>
C++数组与指针
指向数组元素的指针
一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组元素(把某一元素的地址放到一个指针变量中)。所谓数组元素的指针就是数组元素的地址。
int a[10]; //定义一个整型数组a,它有10个元素 int *p; //定义一个基类型为整型的指针变量p p=&a[0]; //将元素a[0]的地址赋给指针变量p,使p指向a[0]</div>
在C++中,数组名代表数组中第一个元素(即序号为0的元素)的地址。因此,下面两个语句等价:
p=&a[0]; p=a;</div>
在定义指针变量时可以给它赋初值:
int *p=&a[0]; //p的初值为a[0]的地址</div>
也可以写成
int *p=a; //作用与前一行相同</div>
可以通过指针引用数组元素。假设p已定义为一个基类型为整型的指针变量,并已将一个整型数组元素的地址赋给了它,使它指向某一个数组元素。如果有以下赋值语句:
*p=1; //对p当前所指向的数组元素赋予数值1</div>
如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素。
如果p的初值为&a[0],则:
1) p+i和a+i就是a[i]的地址,或者说,它们指向a数组的第i个元素,见图6.12。
2) *(p+i)或*(a+i)是p+i或a+i所指向的数组元素,即a[i]。
可以看出,[]实际上是变址运算符。对a[i]的求解过程是: 先按a+i×d计算数组元素的地址,然后找出此地址所指向的单元中的值。
3) 指向数组元素的指针变量也可以带下标,如p[i]与*(p+i)等价。
根据以上叙述,引用一个数组元素,可用以下方法:
下标法,如a[i]形式;
指针法,如*(a+i)或*(p+i)。其中a是数组名,p是指向数组元素的指针变量。如果已使p的值为a,则*(p+i)就是a[i]。可以通过指向数组元素的指针找到所需的元素。使用指针法能使目标程序质量高。
【例】输出数组中的全部元素。假设有一个整型数组a,有10个元素。要输出各元素的值有3种方法:
1) 下标法。
#include <iostream> using namespace std; int main( ) { int a[10]; int i; for(i=0;i<10;i++) cin>>a[i]; //引用数组元素a[i] cout<<endl; for(i=0;i<10;i++) cout<<a[i]<<" "; //引用数组元素a[i] cout<<endl; return 0; }</div>
运行情况如下:
9 8 7 6 5 4 3 2 1 0↙ (输入10个元素的值) 9 8 7 6 5 4 3 2 1 0 (输出10个元素的值)</div>
2) 指针法。
将上面程序第7行和第10行的“a[i]”改为“*(a+i)”,运行情况与(1)相同。
3) 用指针变量指向数组元素。
#include <iostream> using namespace std; int main( ) { int a[10]; int i,*p=a; //指针变量p指向数组a的首元素a[0] for(i=0;i<10;i++) cin>>*(p+i); //输入a[0]~a[9]共10个元素 cout<<endl; for(p=a;p<(a+10);p++) cout<<*p<<" "; //p先后指向a[0]~a[9] cout<<endl; return 0; }</div>
运行情况与前相同。请仔细分析p值的变化和*p的值。
对3种方法的比较:
方法(1)和(2)的执行效率是相同的。第(3)种方法比方法(1)、(2)快。这种方法能提高执行效率。
用下标法比较直观,能直接知道是第几个元素。用地址法或指针变量的方法都不太直观,难以很快地判断出当前处理的是哪一个元素。在用指针变量指向数组元素时要注意: 指针变量p可以指向有效的数组元素,实际上也可以指向数组以后的内存单元。如果有
int a[10], *p=a; //指针变量p的初值为&a[0] cout<<*(p+10); //要输出a[10]的值</div>
在使用指针变量指向数组元素时,应切实保证指向数组中有效的元素。
指向数组元素的指针的运算比较灵活,务必小心谨慎。下面举几个例子。
如果先使p指向数组a的首元素(即p=a),则:
1) p++(或p+=1)。使p指向下一元素,即a[1]。如果用*p,得到下一个元素a[1]的值。
2) *p++。由于++和*同优先级,结合方向为自右而左,因此它等价于*(p++)。作用是: 先得到p指向的变量的值(即*p),然后再使p的值加1。例6.5(3)程序中最后一个for语句:
for(p=a;p<a+10;p++) cout<<*p;</div>
可以改写为
for(p=a;p<a+10;) cout<<*p++;</div>
3) *(p++)与*(++p)作用不同。前者是先取*p值,然后使p加1。后者是先使p加1,再取*p。若p的初值为a(即&a[0]),输出*(p++)得到a[0]的值,而输出*(++p)则得到a[1]的值。
4) (*p)++表示p所指向的元素值加1,即(a[0])++,如果a[0]=3,则(a[0])++的值为4。注意: 是元素值加1,而不是指针值加1。
5) 如果p当前指向a[i],则
*(p--) 先对p进行“*”运算,得到a[i],再使p减1,p指向a[i-1]。
*(++p) 先使p自加1,再作*运算,得到a[i+1]。
*(--p) 先使p自减1,再作*运算,得到a[i-1]。
将++和--运算符用于指向数组元素的指针变量十分有效,可以使指针变量自动向前或向后移动,指向下一个或上一个数组元素。例如,想输出a数组100个元素,可以用以下语句: