目录
例题:输出字符串“abcdefgabcdeabc”,这26个字母中小写字母出现的次数
一、指针与数组
1.1、指针与数组
指针用于存储地址,它和数组名紧密地联系在一起。
1.2、指针与字符串
- 上图为一个grade的数组,里面有5个元素,每个元素占4个字节
- 访问数组元素,可以使用下标来实现。
- 上面数组已知grade[0]的地址,可以通过增减偏移量,得到grade[3]的地址,从而访问到grade[3]的元素值。
表达式"&grade[3]=&grade[0]+3*4"的含义是gradep[3]的地址等于grade[0]的地址加上12
数组中的下标为N元素的地址= 数组的首地址+N*sizeof(DataType)
- int grade[5]; // 定义grade 为包含5个整数数据的数组
- int *p; // 定义p为指向整型变量的指针变量
- p=&grade[0];
1.3、数组名作为指针
对于每个创建的数组,数组名就成为编译器为这个数组所创建的指针常量名称,存储的是数组第1个元素的起始地址,也就是数组的首地址。因此就多了一种获取数组元素的手段,如:p=&grade[0]; 可以写成 p=grade。
p是指针变量,它的初始值是grade数组的首地址
#include "stdio.h"
int main(void)
{
int array[10];
int i,j,n,m,arrayend;
int *p;
printf("输入共有多少个数字:\n");
scanf("%d",&n);
printf("需要后移多少位:");
scanf("%d",&m);
printf("请依次输入%d个数:\n",n);
for(i=0;i<n;i++) // 输入数据
scanf("%d",&array[i]);
for(i=0;i<m;i++)
{
arrayend=*(array+n-1); // 保存指针
p=array+n-1; // 指针赋值
for(j=n-1;j>0;j--) // 循环移动
{
*p=*(p-1);
p--;
}
*p=arrayend; // 回复指针
}
printf("输出移动后的%d个数:\n",n);
for(i=0;i<n;i++)
printf("%d",array[i]);
printf("\n");
return 0;
}
二、指针与多维数组
二维数组array[2][3](这6个数据在内存中按照z型排列),在内存中的存储形式
多维数组的数组名也被编译创建为常量,用来存储该数组的首地址
数组名array存储的是array[0][0]元素地址,存储的值位&array[0][0]
多维数组和指针的关联:首地址加偏移量,可使指针指向该数组中任何一个元素
三、指针与数组参数
第一种情况:实参是数组,形参也是数组
主调函数:int arr[10]; function(arr); // arr实参
被调函数:function(int arr[]){} // arr[]形参
第二种情况:实参是数组,形参是数组指针
主调函数:int arr[10];function(arr); // arr 实参
被调函数:function(int *p){} // p形参
第三种情况:实参是数组指针,形参是数组指针
主调函数:int arr[10]; int *p=arr; function(p); // 实参 p
被调函数:function(int *q){} //形参q
第四种情况:实参是数组指针,形参是数组
主调函数:int arr[10]; int *p=arr; function(p); // 实参 p
被调函数:function(int arr[]){} // 形参 arr[]
例题:输出字符串“abcdefgabcdeabc”,这26个字母中小写字母出现的次数
实参是数组,形参是指针+数组
三、指针与字符串
3.1、使用指针创建字符串
定义message1[10];为10个字符串声明存储空间,并自动地创建一个包含指针的常量message1,存储的是message1[0]的地址。与常量一样指针常量指向是明确的,不能被修改。
使用指针创建字符串
char *message2="hello world!"
char message1= "hello world!" 此种形式的定义,有固定的数组存储空间,该数组一旦被初始化就不可再修改。
如:char message1 = "are you ok?" 修改成这样,显然是错误的。
#include "stdio.h" int main(void) { char *p,s[6]; // 定义一个字符型的指针与数组 int n; // 定义变量 n=0; // 初始化变量 p=s; // 指针p指向数组s,本质是指向数组s[0]的首地址 printf("输入你要转换的八进制:\n"); // 输出函数 同printf gets(p); // 输入函数 同scanf while(*(p)!='\0') // 检测指针是否都是以字符串数组结尾 { n=n*8+*p-'0'; // 八进制转化为十进制的公式 p++; // 指针后移 } printf("转换的十进制是:\n%d\n",n); return 0; return system("pause") }
3.2、使用指针处理字符串
3.2.1、字符串复制
3.2.2、字符串连接
3.2.3、删除字符串中的#符号
注意事项:
- 保留当前地址,代码中p=arr,t=p,这样写的目的是用于恢复到当前位置
- 指针连续出现“#”的解决办法,采用先向前移动,然后重新检查该位置字符,p--
- strarrange函数返回的arr指针,该指针始终指向s字符串的首地址
3.3、指针的指针
- 指针可以字符串
- 指针的指针可以指向一组字符串
3.4、指针数组与数组指针
3.4.1、指针数组
- 数组由指针类型的元素组成 (存储相同类型指针的数组) int *p[10] 该数组p由10个指向整型元素的指针组成
- ()优先级高
- p+1是错误的执行 p=b也是错误的执行 因为不知道p表示的是什么
- 但可以执行*p=&b 因为*p表示数组的(p[0]的地址)的首地址,b首地址的值
- p[0]是一个指针变量
- 指针数组用法同指针一样,这些指针的名字相同(都是p),靠下标区分
3.4.2、数组指针(行指针)
- int (*p)[10]
- []优先级高
- p是一个整型指针指向一个数组元素为10的数组
- p+1的执行要跨过10个整型数据的长度
二维数组的赋值方式
四、案例
#include <stdio.h>
/*有个人围成一圈,顺序排号,从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的哪位是原来的第几号*/
#define nmax 50
int main(void) {
int i,k,m,n,num[nmax],*p;
printf("请输入总人数:\n");
scanf("%d",&n);
p = num;
for(i=0; i<n; i++)
*(p+i)=i+1;
i=0;
k=0;
m=0;
while(m<n-1) {
if(*(p+i)!=0)
k++;
if(k==3) {
*(p+i)=0;
k=0;
m++;
}
i++;
if(i==n)
i=0;
}
while(*p==0)
p++;
printf("%d号留下来了",*p);
return 0;
return system("puase");
}