1,二级指针:
二维数组?---》数组的数组
二级指针?---》指针的指针
概念:二级指针存储的是一级指针的地址
(定义意味着有空间
有空间就会有地址)
格式:
定义一级指针的格式:
存储类型 数据类型 * 指针变量名;
定义二级指针的格式:
存储类型 数据类型 **指针变量名;
分析:
存储类型:二级指针自身的存储类型
数据类型**:二级指针的数据类型
数据类型*:二级指针所指向的类型
指针变量名:见名知义
--------------------------------------------------------
总结:
(1)什么时候需要定义一个二级指针出来?----》当需要该一级指针的值时
(2)如何确定指针的类型?
-----》去掉[变量名] ,剩余的就是该指针自身的类型
eg:
int *p; int *
int **pp; int **
(3)如何确定指针所指向的类型?
----》去掉[* 指针变量名] ,剩余的就是该指针所指向的类型
(4)如何分析一个指针一次性访问空间的大小?
----》依赖于所指向的类型
char **pp; pp一次性访问空间的大小为4个
char *p; p一次性访问的空间为1个
int ****pppp;pppp一次性可以访问空间为4个
-
#include <stdio.h>
-
int main(int argc, const char *argv[])
-
{
-
int a = 90;
-
int b = 78;
-
int *p = &a;
-
printf("*p = %d\n",*p);
-
//*p = 56;
-
//p = &b;
-
int **pp = &p;
-
*pp = &b;
-
printf("*p = %d\n",*p);
-
return 0;
-
}
-----------------------------------------------------------------------------------------------------
指针和数组的结合:
指针和一维数组的关系:
指针的算术运算:(+ - * / % ++ --)
假设以p和q为例(注意:p和q是同类型的指针变量)
p + N:代表p向地址增大方向移动N个数据类型的大小(p + sizeof(数据类型) * N)
p - N:代表p向地址减小方向移动N个数据类型的大小(p - sizeof(数据类型) * N)
p++:代表p向地址增大方向移动1个数据类型的大小(p + sizeof(数据类型) * 1)
p--:代表p向地址减小方向移动1个数据类型的大小(p - sizeof(数据类型) * 1)
p-q:代表两个指针之间相隔元素的个数( p - q / sizeof(数据类型))
-
#include <stdio.h>
-
int main(int argc, const char *argv[])
-
{
-
//定义三个指针变量
-
int *p;
-
short *q;
-
char *s;
-
int *r = p+4;
-
printf("r-p = %d\n",r-p);
-
/*
-
p++;
-
printf("p = %p\n",p);
-
printf("p = %p\t p + 1 = %p\n",p,p+3);
-
printf("q = %p\t s + 1 = %p\n",q,q+1);
-
printf("s = %p\t s + 1 = %p\n",s,s+1);
-
*/
-
return 0;
-
}
p++和p+1的区别:
p++《===》 p = p+1;因此,p++会引起指针指向的改变
p+1不会引起指针指向的改变
数组名:
(1)作为数组名,可以代表整个数组
(2)也可以代表数组的首地址
打印输出数组元素的方式:
arr[i] <===> *(arr+i) <===> *(p+i) <===> *(p++) <===> p[i] <===> i[arr] <===> i[p]
-
-
#include <stdio.h>
-
int main(int argc, const char *argv[])
-
{
-
int arr[5] = {1,2,3,4,5};
-
printf("sizeof(arr) = %d\n",sizeof(arr));
-
//定义一个指针,指向该一维数组的首元素
-
int *p = arr;
-
//printf("arr = %p\n",arr);
-
//printf("&arr[0] = %p\n",&arr[0]);
-
int i;
-
for(i=0;i<5;i++)
-
{
-
//printf("%d ",arr[i]);
-
//printf("%d ",*(arr+i));
-
//printf("%d ",*(p+i));
-
//printf("%d ",*(p++));
-
//printf("%d ",p[i]);
-
//printf("%d ",i[arr]);
-
printf("%d ",i[p]);
-
}
-
printf("\n");
-
return 0;
-
}
-
分析:可以使用p[i]这种方式来遍历数组的原因是:编译器会自动将p[i]编译成*(p+i)
总结:
对于数组名:arr[i]
对于指针:*(p+i) / *(p++)
练习:
(1)从键盘获得一个字符串,利用指针实现求该字符串中空格的个数
-
-
#include <stdio.h>
-
#define N 20
-
int main(int argc, const char *argv[])
-
{
-
//定义一个字符数组
-
char str[N] = {'\0'};
-
//定义一个字符指针指向该数组的首元素
-
char *p = str;
-
printf("请输入一个字符串:\n");
-
gets(p);
-
int count = 0;
-
//遍历该字符串
-
while(*p != '\0')
-
{
-
if(' ' == *p)
-
{
-
count++;
-
}
-
p++;
-
}
-
printf("count = %d\n",count);
-
return 0;
-
}
-
(2)利用指针实现冒泡(改变指针指向/ 不改变指针指向)
-
#include <stdio.h>
-
#define N 5
-
int main(int argc, const char *argv[])
-
{
-
//利用指针实现排序
-
int arr[N] = {0};
-
//定义一个整形指针变量指向该数组首元素
-
int *p = arr;
-
printf("请输入:\n");
-
int i,j;
-
for(i=0;i<N;i++)
-
{
-
//scanf("%d",&arr[i]);
-
scanf("%d",p+i);
-
}
-
printf("排序之前为: \n");
-
for(i=0;i<N;i++)
-
{
-
//printf("% ",arr[i]);
-
printf("%d ",*(p+i));
-
}
-
printf("\n");
-
for(i=0;i<N-1;i++)
-
{
-
p = arr;//让p重新指向首元素
-
for(j=0;j<N-1-i;j++)
-
{
-
if(*p > *(p+1))
-
{
-
int temp;
-
temp = *p;
-
*p = *(p+1);
-
*(p+1) = temp;
-
}
-
p++;
-
}
-
}
-
printf("排序之后为: \n");
-
p = arr;
-
for(i=0;i<N;i++)
-
{
-
//printf("% ",arr[i]);
-
printf("%d ",*(p+i));
-
}
-
printf("\n");
-
return 0;
-
}
冒泡排序:从左至右,两两依次进行比较
注意:冒泡按照数据找位置
选择排序:
假设有N个数:
第一趟:找出最大的数,将该数与位置为0的数字进行交换
第二趟:从总个数减1的人数中,再找出最大的时钟与位置为1的数字进行交换。。
。。。。。。。。。。。。
注意:选择按照位置找数据
-
#include <stdio.h>
-
#define M 5
-
int main(int argc, const char *argv[])
-
{
-
int arr[M] = {0};
-
int i;
-
for(i=0;i<M;i++)
-
{
-
scanf("%d",&arr[i]);
-
}
-
int j;
-
//int index;
-
//选择排序
-
for(i=0;i<M-1;i++)
-
{
-
//index = i;
-
for(j=i+1;j<M;j++)
-
{
-
/*if(arr[index] > arr[j])
-
{
-
index = j;
-
}
-
*/
-
if(arr[i] > arr[j])
-
{
-
int temp;
-
temp = arr[i];
-
arr[i] = arr[j];
-
arr[j] = temp;
-
}
-
}
-
/*
-
//交换
-
int temp;
-
temp = arr[i];
-
arr[i] = arr[index];
-
arr[index] = temp;
-
*/
-
}
-
printf("排序之后为:\n");
-
for(i=0;i<M;i++)
-
{
-
printf("%d ",arr[i]);
-
}
-
putchar('\n');
-
return 0;
-
}
作业:
1,指针实现,定义一个字符串,实现字符串的倒置 "break" ---> "kaerb"
-
#include<stdio.h>
-
#include<string.h>
-
#define M 5
-
int main(int argc, const char *argv[])
-
{
-
//指针实现,字符串的倒置
-
char arr[M] = {'\0'};
-
printf("请输入字符串:\n");
-
//定义指针
-
char *p = arr; // p = &arr[0]
-
gets(p);
-
//使用strlen来测出arr数组的有效字节
-
int l;
-
l = strlen(arr);
-
//p(首地址) + l -1 就是末地址
-
p = p + l - 1;
-
int i;
-
for(i = 0;i < M;i++)
-
{
-
printf("%c",*(p-i));
-
}
-
putchar('\n');
-
return 0;
-
}
2,利用指针实现strcat功能
-
#include<stdio.h>
-
#include<string.h>
-
#define M 15
-
#define N 20
-
char *mystrcat(char *p,char*q,int n)
-
{
-
if(NULL == p || NULL == q)
-
{
-
printf("NULL_ERROR!\n");
-
return NULL;
-
}
-
while(*p)
-
{
-
p++;
-
}
-
//n代表连接arr2的n位
-
while(n--)
-
{
-
*p++ = *q++;
-
}
-
*p = '\0';
-
return q;
-
}
-
int main(int argc, const char *argv[])
-
{
-
//使用指针实现strcat的前n位
-
char arr1[M] = {'\0'};
-
char arr2[N] = {'\0'};
-
printf("请输入两个字符串:\n");
-
//gets输入字符串
-
gets(arr1);
-
gets(arr2);
-
/*定义指针,指向数组的首地址
-
char *p= &arr1[d];
-
char *q= &arr2[0];*/
-
//定义数组arr1和arr2的有效字符长度
-
int l1,l2;
-
l1 = strlen(arr1);
-
l2 = strlen(arr2);
-
if( M < l1 + l2 + 1)
-
{
-
printf("error!!!\n");
-
return -1;
-
}
-
/*while(*p)
-
{
-
p++;
-
}*/
-
/*遍历arr2
-
while(*q)
-
{
-
*p++ = *q++;
-
}*/
-
char *s;
-
s = mystrcat(arr1,arr2,2);
-
printf("连接之后:%s\n",arr1);
-
return 0;
-
}