这个作业属于哪个班级 | C语言--网络2011/2012 |
---|---|
这个作业的地址 | C博客作业05--指针 |
这个作业的目标 | 学习指针相关内容 |
姓名 | 李兴果 |
0.展示PTA总分
1.本章学习总结
1.1 指针定义、指针相关运算、指针做函数参数。
指针的定义:
指针是一个变量,用来存放地址的变量
* 指针的值:是某个变量的地址
p=&a:把a的值取给p,即p指向a;
**指针变量的类型和它所指向变量的类型一致**
*p:直接对内存单元操作,改变变量的数据
&:取地址,*:取内
&*p与&a相同,为地址
*&a与a相同,是变量
(*p)++相当于a++:将p所指向的变量值加一;
*p++等价于*(p++):先取*p,然后p自加,此时p不再指向a;
&a的含义:
pointre_1=
先对a取地址,之后为a所指向的变量,即&a与a等价;
指针变量的初始化:
(1)指针变量必须先定义,然后地址赋值
int a;intp;p=&a;
(2)定义指针的变量时,可同时对对它赋初值
int a;int *p=&a;
(3)不能用数值作为指针变量的初值,可将指针变量初始化为一个空指针
p=0;p=NULL
注:
相同类型的指针才能相互赋值
指针实现交换:
- swap1(a,b),在swap函数中会改变形参的值,但不会影响实参的值
不能改变main()中实参的值 - swap2(&a,&b),定义swap(int p1,int p2)将p1和p2交换值之后,主调函数的ab,值也会跟着其变化
注:
传地址可以返回多个变量值
形参:指针变量 int *p
实参:地址&a,某个指针
数组和地址间的关系:
(1) 数组名代表一个地址,它的值是数组首元素的地址
a+i是数组a基地址的第i个偏移量
&a[i]=a+i;a[i]=*(a+i)
(2) 指针与数组的关系:
p=a or p=a[0]
- 指针做循环变量时候条件
for(p=a;p<a+n;i++)
指针的运算:
(1)指针+或者-一个数,表示指针加减这个数的类型所占内存的整数倍
(2)指针减去一个指针,表示两个指针之间所差的内存单元或者元素个数,两个指针相加没有意义
(3)关系运算,如果定义了两个指针变量p和q,并且都已经初始化了
p-q:两者之间相差的元素
(int)p-(int)q:两者之间相差的字节数
*和&两个符号优先级是相同的,运算时自右向左
int arr[5] = { 1,3,5,7,9 };
int *p = arr;
*++p:p先自+,然后*p,最终为3
++*p:先*p,即arr[0]=1,然后再++,最终为2
*p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
(*p)++:先*p,即arr[0]=1,然后1++,该语句执行完毕后arr[0] =2
*(p++):效果等同于*p++
指针作为函数参数:
实参和形参之间的数据传输是单向的,实参可以影响形参,而形参不能影响实参。指针但是可以改变实参指针变量所指向的变量的值
1.2 字符指针
(1) const:
- 定义变量,相当于常量
- 只读变量,必须在定义时就给之赋值
(2)不要引用未赋值的指针
- 定义指针时,先将它的初值置为空
char*s=NULL;
(3)常用字符串处理函数
- 函数原型在stdio.h或string.h中给出
输入:scanf or fgets
输出:printf or puts
(4)
-
字符串复制:strcpy(str1,str2)
-
字符串连接:strcat(str1,str2)
-
字符串比较:strcmp(str,str2)
比较字符串的内容:
if(strcmp(str1,str2)>0)
if(strcmp(str1,str2)<0)
if(strcmp(str1,str2)==0) -
字符串长度:strlen(str)
计算字符串长度,不包括' ',fgets()会包括' ' -
strcpy与strcat问题
源字符串需要足够,否则会出现溢出现象
char *strcpy(char *a,const char *b,size_t n)
将b中所指向的字符串复制到a当中,最多复制n个字节,当b中字节少于n个字节时,a中剩余部分将用空字节填充
char *strcat(char *a,const char *b,size_t n)
将b中所指向的字符串追加到a所指向字符串的结尾,追加最多n个字符
-
strpbrk(str1,str2)
char *strpbrk(const char *str1,const char *str2)
检索字符串str1中第一个匹配str2中字符串的字符 -
strrchr()
char *strrchr(const char *str,int c)
参数str所指向字符串中最后一次出现字符c的位置 -
strstr()
char *strstr(const char *haystack,const char *needle)
字符串haystack中寻找第一次出现字符串needle的位置 -
引用数组元素:
指针法:*(a+i)or *(p+i)//a为第一个元素的地址,+i指向第i个元素,若为int类型,则i为四个字节
三目运算符
对于条件表达式b ? x : y,先计算条件b,然后进行判断。如果b的值为true,计算x的值,运算结果为x的值;否则,计算y的值,运算结果为y的值。一个条件表达式绝不会既计算x,又计算y。条件运算符是右结合的,也就是说,从右向左分组计算
1.3 指针做函数返回值
- 具体格式:
char *fun()
{
char *;
.......
return p;
}
- 要求设计函数match(s,ch),在字符串s中查找字符ch,如果找到,返回第一次找到的该字符在字符串中的位置(地址),否则,返回空指针NULL
1.4 动态内存分配
为什么要动态内存分配,堆区和栈区区别。动态内存分配相关函数及用法。举例为多个字符串做动态内存要如何分配。
(1)
- 优点:能够根据实际输入数据的多少来申请和分配内层空间,从而提高内存使用率
(2) - 堆区和栈区区别:
1.申请方式不同
栈:有系统自动分配
注意:系统首先会去查看栈上是否有足够的区域去开辟该空间,如果有就直接开辟,如果没有则栈溢出
堆:自己申请开辟,并且指明大小
2.底层不同
栈:是连续的空间
堆:不是连续的空间
(3)
-
molloc函数:malloc 函数的返回值是一个地址,这个地址就是动态分配的内存空间的起始地址。如果此函数未能成功地执行,如内存空间不足,则返回空指针 NULL。
有molloc也要有free,申请后要释放,解放内存 -
free函数:无返回值,它的功能是释放指针变量 p 所指向的内存单元。此时 p 所指向的那块内存单元将会被释放并还给操作系统,不再归它使用。操作系统可以重新将它分配给其他变量使用。
1.5 指针数组及其应用
多个字符串用二维数组表示和用指针数组表示区别?
一维数组定义的一般格式:类型名 *数组名[数组长度]
指针可以相互转换(时间空间更优化)
1.6 二级指针
定义:指向指针的指针
类型名 **变量名
int a=10;
int *p=&a;
int **p=&p;
1.p变了,pp也跟着变
2.地址加数值还是地址
3.二级地址,一个后是一级地址,2
个后才是内容
a+i=a[i],二级指针
*(a+i):a[i],表示第i行首元素地址,一级指针
*(a+i)+j:a[i]+j=&a[i][j],第i行第j个地址,一级地址
**(a+i):a[i][0]
((a+i)+j):a[i][j]
a+i+j:第i+j行二级地址
1.7 行指针、列指针
定义格式、主要用法。
行指针:
int (*p)[n]
- 含义:p为指向含有n个元素的一维数组的指针变量,二级指针
- 行指针p是行地址性质的指针,p+i=a+i!=a[i]二级指针
(p+i)=(a+i)=a[i]一级指针 - 行指针可以和数组名互相使用,p[i][j]=a[i][j]
二级指针:
一个*,表示地址
两个**,表示元素
*(*(p+i)+j)=a[i][j]
- 列指针:
int
*p;
p=a[0];
*(p+i),表示离a[0][0]第i个位置的元素
- 行指针:
p+i:表示第i行的首地址a[i],二级指针
a[i][j]=*(*(p+i)+j)=(*(p+i))[j]=p[i][j]
指针数组:
int *p[n],int **p;p=pp;
p[i]为指针
p为二级指针
2.PTA实验作业
2.1 题目名1
2.1.1 伪代码
定义初始化变量s1,s2
定义 i, num
输入
strstr(s1, s2)当s1寻找到在s2中第一次出现的词
长度为s1中找到的
char* p = strstr(s1, s2)返回在s1中找到的第一个s2字符串地址
定义cnt = strlen(p) cnt等于所找到的当前s2字符串地址之后所有的字符串个数
当i != strlen(s2)
对p中的s2字符串置' ',并将p移至下一个地址
往前移位,即num-cnt为当前s1字符串的字符个数
num = strlen(s1)
输出
2.1.2 代码截图
2.1.3 找一份同学代码
2.2 题目名2
2.2.1 伪代码
定义i = m - 1//i为a数组下标
定义j = n - 1//b数组下标
定义 k = m + n - 1//为新数组a的下标
当i,j值都大于0
如果(a[i] >= b[j])
将两数组当中最大的值赋给新数组a中最大的位置
i--
j--
当其中一组数排列完毕,剩下一组数则放置新数组a的前面位置
a[k--] = b[j];
j--
2.2.2 代码截图
2.2.3与同学代码区别
-
我的代码:
从下标开始,定义合并后数组下标
从最后一个数开始遍历
比较大小,移动数的位置 -
同学的代码:
采用动态内存分配
循环条件直到数组读取结束
分别存储a结束后存b/b存完存a
2.3 题目名3
(本题没有做出来)
2.3.1 伪代码
无
2.3.2 代码截图
无
2.3.3 请说明和超星视频做法区别,各自优缺点。
老师的代码
知识点
定义指针指字符串,更能动态了解当前字符及位置
while (* endPtr&&* endPtr != '
') endPtr++;
逆向扫描字符串
while (p != beginPtr) { p--; };
寻找字符串中单词,即当前一个字符为空格时候
if(* p != ' '&&* (p-1) == ' ');//当前字符非空格而前一个字符是空格
输出指定长度字符printf("%.s",len,str);