{C++善于利用指针与引用(3)}菜大学生C++笔记21

第6章 善于利用指针与引用


6.4 字符串与指针
1 存放字符串的三种方式。(字符数组,字符串变量,字符指针)
#include< iostream>
using namespace std;
int main()
{
char str[]=“I love CHINA!”;
cout<<str<<endl;
return 0;
}

#include < iostream>
#include < string>
using namespace std;
int main()
{
string str=“I love CHINA!”;
cout<<str<<endl;
return 0;
}

#include < iostream>
using namespace std;
int main()
{
char *str=“I love CHINA!”;
cout<<str<<endl;
return 0;
}
在这里没有定义字符数组,在程序中定义了一个字符指针变量str,用字符串常量"I love CHINA!"对它初始化。对字符指针变量str的初始化,实际上是把字符串中第1个字符的地址赋给str。程序第4行定义str的语句等价于下面两行:
char =*str;
str=“I love CHINA!”;
在输出时,系统先输出str所指向的第1个字符数据,然后使str自动加1,使之指向下一个字符,然后再输出一个字符……如此直至遇到字符串结束标志’\0’为止。

2 每种存储方式存储一个字符串占用内存大小相同吗?
字符数组
与字符串长度有关
字符串变量
是固定值(是一个类,面向对象)
字符指针
是一个指针变量(所有的指针变量占用内存大小相同)

3 如何给字符数组赋值,可以更改其中的某个字符吗?可以赋值更长的字符串吗?可以直接赋值其他字符串吗?
数组名是常量
#include < iostream>
#include < cstring>
using namespace std;
int main()
{
char str[10]=“abcde”;
cout<<str<<endl;
str[0]=‘A’;
cout<<str<<endl;
strcpy(str,“123456789012345”);//危险
cout<<str<<endl;
//str=“I love you”;//语法错误
cout<<str<<endl;
return 0;
}

4 如何给字符指针赋值,可以更改其中的某个字符吗?可以赋值更长的字符串吗?
#include < iostream>
#include < cstring>
using namespace std;
int main()
{
char *str=“abcde”;
cout<<str<<endl;
//str[0]=‘A’;//此处出错
cout<<str<<endl;
str=“I love you”; //合法但不是在原地改
cout<<str<<endl;
return 0;
}

5 如何给字符串变量赋值,可以更改其中的某个字符吗?可以赋值更长的字符串吗?
#include < iostream>
#include < string>
using namespace std;
int main()
{
string str=“abcde”;
cout<<str<<endl;
str[0]=‘A’;
cout<<str<<endl;
str=“I love you”;
cout<<str<<endl;
return 0;
}

6 将字符数组str1复制给字符数组str2 (模拟系统函数strcpy)
#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;
}
在这里插入图片描述

6.5 函数与指针(指向函数的指针变量,为指针赋值为函数名,通过指针调用函数)
#include< iostream>
using namespace std;
int main()
{
int max(int x,int y); //函数声明
int a,b,m;
cin>>a>>b;
m=max(a,b); //调用函数max,求出最大值,赋值给m
cout<<“max=”<<m<<endl;
return 0;
}
int max(int x,int y)
{
int z;
if(x>y)z=x;
else z=y;
return(z);
}

可以用一个指针变量指向max函数,然后通过该指针变量调用此函数。定义指向max函数的指针变量的方法是: int (*p)(int,int);
p是指向函数的指针变量
指向函数的指针变量的一般定义形式为
函数类型 (*变量名)(函数形参表);

#include< iostream>
using namespace std;
int main()
{
int max(int x,int y); //函数声明
int min(int x,int y); //函数声明
int(*p)(int,int); //定义指向函数的指针变量p
int a,b,m;
cin>>a>>b;
p=max;
m=p(a,b); //调用函数max,求出最大值,赋值给m
cout<<“max=”<<m<<endl;
p=min;
m=p(a,b); //调用函数min,求出最小值,赋值给m
cout<<“min=”<<m<<endl;
return 0;
}
int max(int x,int y)
{
int z;
if(x>y)z=x;
else z=y;
return(z);
}
int min(int x,int y)
{
int z;
if(x>y)z=y;
else z=x;
return(z);
}

6.7 有关指针的数据类型和指针运算的小结
1 有关指针的数据类型
变量定义
类型
含义

int i;
int
定义整型变量i

int *p;
int *
定义p为指向整型数据的指针变量

int a[5]
int [5]
定义整型数组a,有5个元素

int *p[4]
int *[4]
定义指针数组,有4个元素,p[0],p[1],p[2],p[3].每个元素都是一个整型指针

int (p)[4]
int (
)[4]
P为指向包含4个元素的一维数组的指针变量。当使用列为4的二维数组名作为实参时。形参处即是此种类型

#include< iostream>
using namespace std;
void dispArr2(int x[][3],int n);
int main()
{
int a[2][3]={{1,2,3},{4,5,6}};
int (*p)[3];
p=a;//合法
int i,j;
for(i=0;i<2;i++)
{
for(j=0;j<3;j++)
{
cout<<p[i][j]<<" ";
}
cout<<endl;
}
dispArr2(a,2);
return 0;
}
//void dispArr2(int (*x)[3],int n)
void dispArr2(int x[][3],int n)

{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<3;j++)
{
cout<<x[i][j]<<" ";
}
cout<<endl;
}
}

int f();
int ()
F为返回整型的函数

int *p();
int *()
P为返回整型指针的函数

int (p)()
int (
)()
P为指针变量,可指向返回值为整型,参数为空的函数。

int **p
int **
二级指针,当实参为指针数组时,形参为二级指针。

#include< iostream>
using namespace std;
void dispAll(int **p,int n);
int main()
{
int a=1,b=2,c=3,d=4;
int *p[4]={&a,&b,&c,&d};
int i;
for(i=0;i<4;i++)
{
cout<<*p[i]<<endl;
}
dispAll(p,4);
return 0;
}
void dispAll(int **p,int n)
{
int i;
for(i=0;i<n;i++)
{
cout << **p<<endl;
p++;
}
}

2 指针运算加减 p++ p-- p+=I p+i
一个指针加减一个整数是将指针变量的原值(是一个地址)和它指向的变量所占内存单元字节数相加减。
#include< iostream>
using namespace std;
int main()
{
int a[3]={1,2,3};
double d[5]={1,2,3,4,5};
int *p=a;
double *q=d;
cout <<“p :”<<p<<endl;
cout <<“p+1:”<<p+1<<endl;
cout <<“q :”<<q<<endl;
cout <<“q+1:”<<q+1<<endl;
return 0;
}
在这里插入图片描述

3 指针变量赋值 (要注意类型)
int a,*p;
p=&a;
正确
int a[5],*p;
p=a;
正确

int a;
double *p=&a;
错误
double a[5];
int *p;
p=a;
错误

函数指针要赋值为 同类型的 函数名。
两个同类型的指针可互相赋值。

4 指针变量赋值为空值 p=NULL
如果有一个指针未赋值时,是一个“野指针”,直接使用有风险。可赋值为NULL。表明有值为0

5 两个指针变量相减 (指向同一个数组时才有意义)
#include< iostream>
using namespace std;
int main()
{
int a[3]={1,2,3};
int *p=a,*q=&a[2];
cout<<“p:”<<p<<endl;
cout<<“q:”<<q<<endl;
cout<<“q-p:”<<q-p<<endl;
return 0;
}
在这里插入图片描述
在这里插入图片描述
6 两个指针比较 (只有在指向同一个数组才有意义)
int a[8]={1,2,3,4,5,6,7,8};
int *p=a,*q=&a[7];
while(p<=q)
{
cout<<*p++<<endl;
}

6.8 引用
1 对一个数据可以建立一个“引用”,它的作用是为一个变量起一个别名。这是C++对C的一个重要扩充,假如有一个变量a,想给它起一个别名b,可以这样写:
int a;//定义a是整型变量
int &b=a;
以以后的代码中a就是b,b就是a; 占用的是同一个地址。
不会再为b申请另外的空间。
#include< iostream>
using namespace std;
int main()
{
int a;//定义a是整型变量
int &b=a;//定义b为a的引用,是a的别名
a=5;
cout<<b<<endl;
b=7;
cout<<a<<endl;
cout<<&a<<endl;
cout<<&b<<endl;
return 0;
}
在这里插入图片描述

&是引用声明符,并不代表地址。不要理解为“把a的值赋给b的地址”。
在数据类型名后面出现的&是引用声明符,
在其他场合出现的都是地址符,
如 char &d=c; //此处的&是引用的声明符
int *p=&a; //此处的&是地址符
(1) 引用不是一种独立的数据类型。对引用只有声明,没有定义。必须先定义一个变量,然后声明对该变量建立一个引用(别名)。
(2) 声明一个引用时,必须同时使之初始化,即声明它代表哪一个变量。当引用作为函数形参时不必在声明中初始化,它的初始化是在函数调用时的虚实结合实现的,即作为形参的引用是实参的别名。
(3) 在声明一个引用后,不能再使之作为另一变量的引用。比如声明了b是变量a的引用后,在其有效作用范围内,b始终与其代表的变量a相联系,不能再作为其他变量的引用(别名)。
(4) 不能建立引用数组。如int a[5];
int &b[5]=a; //错误,不能建立引用数组
int &b=a[0]; //可以作为数组元素的别名(书中有误)
(5)两个引用作为同一个变量的别名(P167有误)

int a=1;
int &b=a;
int &c=b;
cout<<a<<b<<c<<endl;
a++;
cout<<a<<b<<c<<endl;
b++;
cout<<a<<b<<c<<endl;
c++;
cout<<a<<b<<c<<endl;

(6) 可以取引用的地址。如已声明b是a的引用,则&b就是变量a的地址&a。
int *pt;
pt=&b; //把变量a的地址&a赋给指针变量pt
int a=5;
int &b=a;
int *p=&b;
cout<<a<<b<<*p<<endl;
a++;
cout<<a<<b<<*p<<endl;
b++;
cout<<a<<b<<*p<<endl;
(*p)++;
cout<<a<<b<<*p<<endl;

例:
#include< iostream>
#include< iomanip>//用输出格式函数setw需要用iomanip头文件
using namespace std;
int main()
{
int a=10;
int &b=a; //声明b是a的引用
a=a*a; //a的值变化了,b的值也应一起变化
cout<<a<<setw(6)<<b<<endl;
b=b/5; //b的值变化了,a的值也应一起变化
cout<<b<<setw(6)<<a<<endl;
return 0;
}

重要应用,引用作为函数的参数
创建函数交换两个变量。
1使用指针2使用引用
#include< iostream>
using namespace std;
void swap1(int *p1,int *p2);
int main()
{
int a=5,b=3;
swap1(&a,&b);
cout<<“a=”<<a<<endl;
cout<<“b=”<<b<<endl;
return 0;
}
void swap1(int *p1,int *p2)
{
int t;
t=*p1;
*p1=*p2;
*p2=t;
}

#include< iostream>
using namespace std;
void swap2(int &p1,int &p2);
int main()
{
int a=5,b=3;
swap2(a,b);
cout<<“a=”<<a<<endl;
cout<<“b=”<<b<<endl;
return 0;
}
void swap2(int &p1,int &p2)
{
int t;
t=p1;
p1=p2;
p2=t;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C0ntr01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值