回顾:
交换p q指向的值,让p指向j,q指向i
要交换的两个变量是什么类型,中间变量(t)就是什么类型
指针的主要作用就是实现在被调函数中修改主调函数,前提是在调用函数时要把要修改的参数的地址传给被调函数
指针比较大小
比较大小是关系运算,结果是一个逻辑值0或1
数组遍历
迭代器:
在主函数中调用传参时,可以直接传a+1,a+len-i-2
迭代器的应用
一、快速排序(qsort)
1、要先找一个基准数,一般是begin对应的数
2、然后从右往左找,第一个比基准数小的数,
3、然后从左往右找,第一个比基准数大的数,
4、然后让2,3所指向的数交换
5、重复步骤234,直到两数重叠
void qSort(int *begin,int *end)
{
if(begin >= end)
{
return;
}
int *p = begin;
int *q = end;
int t = *begin;
while(p < q)
{
while(p < q && *q >= t)
{
--q;
}
while(p < q && *p <=t)
{
++p;
}
swapNumbers(p,q);
}
swapNumbers(begin,p);
qSort(begin,p - 1);
qSort(p + 1,end);
}
(两个指针之间不能求和,因为指针中存放的是地址值。但是能求差,差值表示两个地址之间差了几个基类型,两个指针之间求差,基类型必须是一样的)
二、用迭代器实现二分查找
1、常规实现
int *binaryFind(int *begin,int *end,int a)
{
int *mid;
while(begin <= end)
{
mid = (end - begin) / 2 + begin;
if(*mid > a)
{
end = mid - 1;
}
else if(*mid < a)
{
begin = mid + 1;
}
else
{
return mid + 1;
}
}
return NULL;
}
2、迭代器实现二分查找(递归实现)
int *binaryFind(int *begin,int *end,int a)
{
int *mid;
if(begin > end)
{
return NULL;
}
else
{
mid = (end - begin) / 2 + begin;
if(*mid > a)
{
binaryFind(begin,mid - 1,a);
}
else if(*mid < a)
{
binaryFind(mid + 1,end,a);
}
else
{
return mid;
}
}
}
字符型指针
基类型为char型
const的用法
1.const修饰变量,即常量。
int a = 5;
const int b = 5;//修饰int类型,该变量的值不能修改。
2.const 指针
const char * p或 char const *p;p指向的内容(*p)不能修改;
另外:char* const p;//表示p不能改变,但是p指向的内容(*p)可以改变。
const char * const p;//表示p不能改变,p指向的内容(*p)也不可以改变。
3.const修饰函数
const int func(const int & hh)const;
a.const 修饰返回值(放在最前),表示返回的值不能修改;
b.const 修饰形参(中间位置),表示在函数体内,该形参不能修改;
c.const 修饰函数(放在最后),该形式只用于成员函数,表示函数内,成员变量不能修改;
匿名数组
“hello”在字符串常量区,只能读,不能写,不能通过指针修改其中的值
无符号long型,表个数
n指的是字节数,sizeof(数组名)
如果不加这个强制类型转换,在编译时,编译器会报警。原因是传的函数类型和被调函数类型不匹配
解决这个不匹配的问题,可以引用万能指针
万能指针void *:
可以接受任何类型的指针
万能指针不能进行指针运算:c语言中不允许出现任何void型的东西
万能指针的作用就是用来在被调函数中实现强转
练习:
1、在一个字符串中査找某个字串首次出现的位置int subStr(const char *s,co
nst char *sub)
int subStr(const char *s,const char *sub)
{
int i;
for(i = 0;i < strlen(s) - strlen(sub);++i)
{
if(strncmp(s + i,sub,strlen(sub)) == 0)
{
return i;
}
}
return -1;
}
返回值为指针的函数
一般形式:基类型 * 函数名(参数列表)
在主函数调用fn时,i其实已经被销毁了,拿到的地址其实是一个野指针的地址
动态内存分配
Dynamic:动态的
malloc:要包一个头文件<stdlib.h>malloc(申请的空间不在栈上,在堆上)将你申请的大小的内存空间的首字节的地址返回 malloc可以保证你所申请的内存空间一定是连续的
用malloc有可能申请不到,若申请到内存,则返回申请到的内存的首地址,若申请不到,则返回一个空指针
malloc申请的空间使用完之后,要记得释放
但是不能释放两次,第一次释放以后,p已经相当于一个野指针
练习:
在堆空间申请一个长度为10的一维整型数组,并在其中填入斐波拉契数列的前10项
int main(void)
{
int n = 10;
int *a = malloc(n * sizeof(int));
if(a)
{
int i;
*a = 1;
*(a + 1) = 1;
for(i = 2;i < 10;++i)
{
*(a + i) = *(a + i - 1) + *(a + i - 2);
}
}
int j;
for(j = 0;j < 10;++j)
{
printf("%d\n",*(a + j));
}
free(a);
a = NULL;
return 0;
}