本文共 6027 字,大约阅读时间需要 20 分钟。
int *p,q //表示p是指针,q是int;
int *p,*q //表示p和q都是指针 (*是和变量在一起的,是用来声明指针)
void swap(int* ,int* );
交换值 虽然没有返回值,但是利用指针可以实现 如果是传进两个整型,那就必须要有返回值,不然函数内部的交换只是拷贝,对外界无影响。于是就很麻烦啊; 使用场景特点:像swap()
这样的函数,函数返回有多个值,于是就要用到指针节省力气void maxmin();
要找数组中的最大值和最小值,于是有两个输出量,于是就用到指针int devide();
返回一个ret来判断除数是否为0,如果除数不是0,则还要返回相除的结果,于是要用指针存放结果送出去。 (这个也是有多个输出)int sum(int *ar,int n);
int sum(int ar[],int n); 上面两种函数原型等价,就算定义指针,下面也还是可以用[],当作数组来处理
min=2;
int *p=&min;
这时,有*p=2
p[0]=2
,因为这时把min认为是数组,即int min[1];
因为int a[100];
相当于int * const a;
(数组变量是const的指针,所以不能被赋值)
int *q=a;
int * const q=&i;
i=20
,但不能做*p=20
) const int *p=&i;
(你给我一个变量的指针,我保证不通过这个指针去改变它所指的变量的值!) (比如将常数指针传到函数中时,就可以有效避免它所指的变量值被更改,相当于让函数发誓!↑)※eg.区分以下含义
int i; const int* p1=&i; 所指变量 int const* p2=&i; 所指变量 int const p3=&i; 指针 判断依据:const在的前面还是后面 思路:从左到右,碰到就判定为指针的定义,再往右就是指针变量,如果后碰到const那肯定是对指针作用的了
const int a[]={1,2,3,4,5,6,7,8,9};
如果是int a[]={1,2,3,4,5,6,7,8,9};
那么a数组本来就已经是个const指针了; 虽然整体不能进行赋值,但是单个单元还是可以进行修改,如a[0]=2;
这时候再加一个const
,那么则代表数组的每个单元都是const int
(比如在函数中使用,传进一个const int a[10]参数,可以有效保护数组不被修改,安全)int number;
int a; printf(“输入数量:”); scanf("%d",&number); //int a [number]; a=(int)malloc(number*sizeof(int));
(eg.若是直接a=malloc(number*sizeof(int));
那么得到的【默认】是void*
类型,如果是a=(int*)malloc(number*sizeof(int))
就得到了int*类型)
※常见问题:
区别:字符数组不能用字符串运算方式进行运算
前者只是一个个字符 后者再最后有一个’\0’ 这个\0表示字符串结束了,但它不是字符串的一部分char *str="Hello";
虽然只有五个单词,但却占留个位置,因为编译器会自动显示一个’\0’ "Hello"会被编译器变成一个字符数组放在某处,这个数组的长度是6 因为结尾还是表示结束的’\0’,两个相邻的字符串常量会被自动连接起来 字符串常量:
char *s="Hello,world!";
char *s2="Hello,world!";
于是会发现两个指针指向同一个位置,而且是个小地址 而且为常量,不能改; 如果你想修改某个值,则必须写成字符数组: `char s[]=“Hello,world!”; 那么为什么呢?有什么区别呢? char *s=“Hello,world!”;(我是一个指针,我指向那个重要的地方!只读!)
char s[]=“Hello,world!”;(我是一个数组,东西就在我这里!)
不一定,可能是单个字符,也可能是字符数组
char *a={'H','e','l','l','o'};
这个时候表示字符数组; char *a={'H','e','l','l','o','\0'};
这个时候表示字符串**(字符数组后有\0)**; char string[8];
scanf("%s",string); printf("%s",string);
scanf();
读入一个单词(到空格、tab或回车为止)
/
"123456"等价于{‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,’\0’} 它表示一个字符串常量,虽然表面看上去有六位,但是实际上却又七位 这是因为它独特的字符串血统,最后会自动有一个\0; //
char a[7]中是由a[0] a[1] a[2] a[3] a[4] a[5] a[6] 其中的**'7’是指一共有7个元素** 然而事实上,由于"1234567"赋值给数组得到的是字符串数组,最后有一个’\0’ 所以啊,"1234567"其实是有8位的!! 于是,如果让a[7]="1234567";
数组会溢出!! / /
那么如何规避这种情况呢? 可以在scanf()
的时候做手脚 scanf("%6s",word);
** 在%后面加一个’6’就可以只拿前面6位了!!** 一共有7个元素,于是最后一个元素位置拿来放'\0'
这就完美了~ / /
空字符串:char buffer[100]="";
意思:这是一个空的字符串,buffer[0]=='\0'
他是个有效的字符串 但是 char buffer[]="";
意思:这个数组的长度只有1!而且只有一个元素,buffer[0]='\0';
于是可以得出结论:
自己定义数组长度常常有浪费(冗余) 但是若是空着给编译器定义长度,他就很小气地帮你卡死 即你右边有多少,他就给多少空间你 //
字符串中的套娃:二维数组和多重指针 定义有效的二维数组:a[][]={“Hello”,“World”};(错误)
a[][10]={“Hello”,“World”};(正确)(这个时候,a[0]=char [10]
)
即一定要给定每个元素的长度(第二个框里面要有内容):如"Hello"和"World"的长度
但是啊,我很恶心,给它scanf()
了一个很长的字符串,超过了它的定义长度,那怎么办呢??
char a[][10]
写成char *a[]
,这个时候啊,a[0]
就变成了char *
,这不就没有长度限制了嘛? (ps.char *a[]
就表示指针数组,数组里面都是指针(可以理解为很多不限长度的字符串~)) / /
1.初始化赋值,char a[]="Hello,World!";
scanf()
总结:想要一次性修改数组的值?不可能,它在定义的时候才可以直接一次性赋值 其他情况必须使用循环!!一个一个改!! / 上面这个Try to understand??
(代码原理没看懂???)int getchar(int )
和int putchar(int )
都是int类型
,如果是字符的话就取ASCII码
; int
而不是char
呢?因为char
的范围太小,而EOF
在stdio
中默认为-1
,于是就用int
才能取到;getchar
明明是得到一个字符,为什么能复读字符串呢?(本质是因为我按一个键,它提取一个键) getchar()
是实时的,碰到它,它就等着用户按键,【并且把所有的操作存放在stdin流中】 (首先有一个缓冲区shell
,它为中间商**,我们对键盘的所有操作都被保存在那里) getchar()
函数就是小弟,给shell
【一个一个】地送东西,我们按什么他就送什么 当我们按下回车的时候,getchar()
知道是最后一个货物 然后让putchar()
一个个从shell
这个仓库中输出,把自己运过去地一件件**小物品***(每一个字符)***送到我们看得到地界面上输出;strlen(“Hello”)==5;
sizeof(“Hello”)==6; (另外:若char a[100]=“Hello,World!”,那么strlen(a)=12,因为它是根据’\0’判断的 此时sizeof(a)=100,因为它是看空间的)
如何写一个strlen函数
?
※思路:传入一个指针(即字符串),从第一个开始遍历,一直到'\0'
int strcmp(const char *s1,const char *s2);
比较两个字符串,返回规则: 0:s1==s2 1:s1>s2 -1:s1<s2
理解:
char s1[]=“abc”; char s2[]=“abc”; 那么s1==s2吗?NO!因为这个时候比的是地址!地址当然不一样 那么strcmp(s1,s2);得到什么的?得到0,因为字符串一样! 所以判断两个字符串是否相等,不能直接比较,一定要用函数strcmp strcmp()函数是用ASCII码比 (ps.比较"abc"和"abc “,出现的结果是-1,因为第二个字符串有空格” ")
※区分:
定义数组char s1[]=“abc”; 这时,s1表示数组的【首地址】; 定义指针char *s1=“abc”; 这时,*s1表示数组中第一个元素的值;这时可以通过s1++来遍历噢`具体使用方法:
注意函数中的两个参数,是先找一个盒子,然后再把东西抄袭进去 最后返回的是到盒子里面找抄到的东西那么什么叫不能重叠呢?
因为strcpy
的功能抄作业*** 所以我们经常用它来复制一个字符串:先malloc一块地址(具体多大要思考噢),然后strcpy抄作业*
具体形象解释:(右侧)
(小声BB:·strlen·测量的是字符串常量长度,不包括’\0’,所以要+1) 这里的功能是先申请一块动态内存,让dst指针指向这片区域 然后用函数抓住dst这个空盒子,往里面塞src 之后函数完事就把盒子送出去(返回)具体使用:
形象表现:
strcpy
和strcat
的对比:
strcpy
是抄作业***,它里面的第一个参数是空的(它是白卷!太不努力了啊!) 而strcat
则是自己写到一半,发现题目不会做,再去抄别人的答案 strcpy
是从dst[0]
开始抄src
; strcat
则是从dst[strlen(dst)]
开始抄src; ※共同点:操作者(学渣)都是函数里面的第一个参数(即第一个字符串指针),第二个参数(即第二个字符串指针)都是学霸* But,因为第二个参数太长,可能会超出第一个参数的界限,于是就会出现安全问题!!
(即学霸的答案太详细,学渣发现自己字太大抄不下了??) 那该怎么办呢??不慌,下面有安全版本的函数,可以限制抄作业的量,以保证不会超过界限 船新版本!比原来函数多了一个n,而且函数多了一个参数,来限制抄作业的数量 对于strcmp
,它变成strncmp
之后,多了个参数n,可以把两个字符串从左到右限制为n个参赛选手的个数
功能是查找
前者是从左往右找 后者多了个r
,是从右往左找 第一个参数是字符串 第二个参数是要找的字符(注意是int类型
啊!!不是char
,比如'l'
) 返回的是指针,指向要找的字符 如上图,怎么在"Hello"中找到第二个’l’呢? 啊可恶,当然是找两次啊!!!
第一次指针p返回第三个字符'l'
的地址,这个时候指针p
是返回"llo"
,那么p+1
就是"lo"
接下来,再来一次p=strchr(p+1,'l');
这样返回的指针p
就指向第二个'l'
,其实也就是指向'lo'
(后面有\0
) 就找到了第二个'l'
的位置了!! 妙啊~~ 那么我们已经会取"llo"
了
p指针
指向第一个'l'
char c
用于存放这个'l'
,最后要复原字符串用啊!! 然后通过*p=’\0’把’l’替换掉 于是字符串变成了"He\0lo\0"
这里其实变成了两个字符串,一个是"He"
,一个是"llo"
又因为s
是数组名,代表数组的首地址
,所以字符串s就是第一个字符串"He"
然后指派一个指针t
用strcpy
去抄s
的作业就行了 最后的最后,复原字符串,把"He\0lo\0"
变回"Hello\0"
就用*p='l'
就OK了 图解: 真的是非常的Amazing啊!!!
字符串中找一个字符串(返回的是一个指针)
strstr
就是在字符串中找一个字符串 strcasestr
功能相同,就是**【忽略大小写】**!! 转载地址:http://ortki.baihongyu.com/