c++入门学习3
- char型指针的使用
- p
- *p
- *p++与p++
- 与[整型指针指向整型数组]的区别
- 指针与函数的使用
- 指向函数的指针
- 空指针调用函数
- 从函数中返回指针
- 一维数组和二维数组的类比
- CHAR型指针数组
- 关于&a
char型指针的使用
char型指针可以直接指向一个字符串,如下
char s[]={'a','b','c'};
char *p=s;
------------------------------
char *p="abc";
--------------------------------
string s="abc";
char *p=s;
//在指针p指向s之后,我们可以直接把p想象成一个内容为“abc”的字符串,方便我们理解
p
对于一个整型的数组来说
int *p=a;
cout<<p; //输出的是第一个元素的地址;
但是对于字符型数组来说
char *p=s;
cout<<p; //输出的却是一个字符串
【样例1】 输出:
abcde
bcde
cde
de
e
可以用如下方式:
char s[]={'a','b','c','d','e','\0'};
char *p=s;
for(int i=0;i<5;i++)
cout<<p+i<<endl;
-----------------------------------------------------------
for(int i=0;i<5;i++)
cout<<&p[i]<<endl;
*p
*p是当前名为p的字符串的首字母:
【样例2】遍历字符串:
char s[]={'a','b','c','d','e','\0'};
char *p=s;
for(int i=0;i<5;i++)
cout<<*(p+i)<<endl; //依次输出字符串的每个字母
-------------------------------------------------------------------------------
for(int i=0;i<5;i++)
cout<<*(&p[i])<<endl;
*p++与p++
char *p=s;
p++;
*p++;
这两条语句在这种情况下是完全等效的,都是将指针p的指向向右移动一位:
值得一提的是
*p++其实等价于 *(p++)
在使用时一定要注意和 (*p)++进行区分,一个是对指针进行操作,另一个是对实际元素进行操作
这里不管是整型数组还是字符数组都是一样的
与[整型指针指向整型数组]的区别
int a[];
char s[];
-----------------------------------------------------------------
对于整型数组来说:
a是数组名,也是第一个元素的地址
同时&a[0],也是第一个元素的地址
*a和*(&a[0])是第一个元素的实际值
------------------------------------------------------------------
对于字符数组来说:
s是数组名,输出的是整个字符串,
&s[0],输出的也是整个字符串;
*s和*(&s[0])是字符串的第一个字符
不管是整型数组还是字符数组
a,a+1,a+2,a+3,a+4 a+n 等价于 &a[0],&a[1],&a[2],&a[3],&a[4],&a[n]
指针与函数的使用
常见的指针传参题目:
【样例3】用指针将字符串传入一个参数是指针的函数中
#include<iostream>
using namespace std;
int cnt(char *p)
{
int i=0;
int sum=0;
while(p[i])
{
sum++;
i++;
}
return sum;
}
int main()
{
char s[]={'a','b','c','d','e','\0'};
char *p=s;
cout<<cnt(p);
}
这段代码的功能就是统计字符串中字符的个数
先定义个了一个指针指向字符串s,然后把指针传入函数中
在这个函数cnt中,你可以把指针p就想象成一个名为p的字符串即可
中间函数的部分也可以这样写:
int cnt(char *p)
{
int i=0;
int sum=0;
while(*(p+i))
{
i++;
sum++;
}
return sum;
}
//运用了上面 *(p+i)遍历字符串的知识
指向函数的指针
一个函数在被编译时也会被分配给一个入口地址,这个入口地址成为函数的指针
int sum(int x,int y); //定义一个函数
int *p(int ,int ); //定义一个指向函数的指针
p=sum; //让指针指向函数
int c,d;
(*p)(c,d); //将参数c,d传入函数sum中
空指针调用函数
我们可以定义一个类型为空的指针,这个指针也可以起到指向函数的功能,但是在使用时,必须根据函数的返回类型和参数类型进行强制转化!
int plus(int x); //定义一个函数,返回类型为int,参数类型为Int
void *p=NULL;
p=plus; //指向函数
ans=( ( int (*)(int) ) p )(10); //int (*)定义返回类型,(int)定义参数类型
从函数中返回指针
我们可以将指针传入函数中,然后让其指向一个函数内的变量,函数返回指针类型的值
这样虽然可以让一个指针正确的等于一个函数内变量的地址,但是函数结束后,函数内的变量会被销毁,虽然指针的值是一个正确的地址,但是地址的内容已经被销毁了,当输出地址所指的内容时,输出的是一个随机数
指针数组
int *p[4];
指向指针的指针
int *(*p);
------------------------
int **p;
一维数组和二维数组的类比
【样例4】:遍历所有的单词:
#include<iostream>
using namespace std;
int main()
{
char s[5][10]={"i","am","a","good","student"};
for(int i=0;i<5;i++)
{
cout<<*(s+i)<<endl;
}
}
我们可以联想,在一维数组中
s+i,是字符串的递减,每次减去前面一位!
*(s+i)是遍历字符串
那么放到二维数组中
*(s+i)是不是就变成了遍历所有单词了呢!
如果先对一个二维数组进行 *(s+i),在对其进行 *(s+i),是不是就变成了遍历每个单词的每个字符了!
CHAR型指针数组
一个普通的char 型指针就可以指向一个字符串,
char *p="good";
--------------------------------------------------------------------------
那么一个指针数组的使用通过类比就可以知道:
char *p[]={"i","am","a","good","student"};
//在这种情况下,p[0],p[1],p[2],p[3],p[4],都分别是一个字符串
【样例5】使用指针数组对单词进行排序:
#include<iostream>
using namespace std;
void sort(char *p[],int n)
{
char *temp;
int i,j,k;
for(int i=0;i<n-1;i++)
{
k=i;
for(int j=i+1;j<n;j++)
{
if(strcmp(p[k],p[j])>0)
k=j;
}
if(k!=i)
{
temp=p[i];
p[i]=p[k];
p[k]=temp;
}
}
}
int main()
{
char *p[]={"i","a","am","student","good"};
int n=4;
sort(p,4);
for(int i=0;i<5;i++)
{
cout<<p[i]<<endl;
}
}
关于&a
int a[]={1,2,3};
char b={'a','b','c'};
-------------------------------
不管是在字符数组中,还是在整型数组中
int *p=&a; 和 char *p=&b;
这样的操作都是报错的,没办法编译,因为二者的维度不一样
--------------------------------------------
但是在一些题目中会使用强制转化的方式强行赋值:
char *p=(char *)(&a+1);
不管是对于整型还是字符型
(char *)(&p)都等价于 p ,等价于 &a[0];
但是当对其在内部进行+1时,指针并不是向后移动1个单位,而是向后移动n位(n为数组的大小)
所以 如果char * p=(char * )(&a+1),那么指针p的位置其实是在数组最后一个元素的下一位
如果 char * p=(char * )(&a+2),那么指针p的位置其实是在数组最后一个元素的下(n+1)位
【样例6】&a的使用:
输出: