0.展示PTA总分
1.本章学习总结
1.1 学习内容总结
指针与指针变量的概念
- 指针:内存中的一个存储单元的地址,即内存单元的编号
- 指针变量:声明一个变量并使用地址作为该变量的值,即一个能存放地址值的变量,通过它存放的地址值能间接访问它所指向的内容
指针变量的定义、使用方法、初始化
- 定义:类型名 指针变量名。例如 : char p;int *p ; 指针变量的类型应与其所指向内容类型一致
- 使用方法:使指针变量指向某个变量,(即将某变量的地址值赋给指针变量)。例如:int x; int *p=&a;使用指针变量时必须先赋值后引用,没有被赋值的指针是野指针,它所指向的内容无法确定
- 初始化:int a;int *p; p=&a; 指针变量不能被赋值,不能直接让指针指向整型数据,指针代表的是一个变量的地址。(可以将0或者NULL赋给指针,但是有的系统不支持赋0)
指针运算的优先级与结合性
- &a等同于a,均代表内容; &p等同于&a,均代表地址。(单目运算符优先级是相同的,但从右向左结合。)
- p++等同于(p++),代表的是内容。
- (p)++与(p++)的区别:前者是指针p所指向的内容自增相当于a++,而后者是运算完p所指向的内容后将指针向下移了一个位置
指针与动态内存分配
我们以往的定义如 :int a[10]; int b等等都是系统的静态内存分配,这些内存在程序运行前就分配好了,不可改变。但是如果我们不知道所输入的内存是多大时,我们定义内存的大小就不能够符合题目的输入,这时我们就应该使用动态申请内存。
malloc动态申请内存
int n;//记录输入总个数 int *p; scanf("%d",&n); p=(int *)malloc(n * (sizeof(int));
calloc动态申请内存
int n;//记录输入总个数 int *p; scanf("%d",&n); p=(int *)calloc(n , (sizeof(int));
realloc动态申请内存
int n;//记录输入总个数 int **p=NULL; scanf("%d",&n); p=(int **)calloc(p , n * (sizeof(int *));
动态内存释放
free();
动态申请内存后都要释放内存,避免数据泄漏和碎片化问题。一个动态申请对应一个释放函数。
malloc、calloc、realloc区别
- 相同点:都是从堆上申请空间;都需要类型转化(这三个函数返回值类型都是void);都需要用户free释放;
- 不同点:三个函数传入的参数不同;calloc会对申请空间初始化,并且初始化为0,而其他两个不会;realloc是对已经存在的空间进行调整,当第一个参数传入NULL的时候和malloc一样;
指针做循环变量做法
int a[20]; int n; int *p; p=a; //一维数组的数组名就是代表数组的首地址,一般不轻易改变原来的地址,引入一个新的指针变量去遍历 fgets(a,20,stdin) for(p=a;*p&&*p!='\n';p++) printf("%d",*p);
字符指针如何表示字符串
字符数组,指针遍历
char str[]="Hello,World"; char *ptr; for(ptr=str;*ptr&&*ptr!='\n';ptr++) printf("%c",*ptr);
指针指向字符串
char *str="Hello,World" char *st; st=str; for(;*st&&*st!='\n';st++) printf("%c",*st);
数组形字符串存放在全局数据区或栈区,可读可写。指针字符串存放在常量区,只读不能写
指针数组及其应用
定义:int *p1[]
int i; char *pch[6]={"妹","妹","你","坐","船","头"}; for(i=0;i<6;i++) printf("%s",pch[i]);
二级指针、行指针
二级指针
int i; char *color[]={"red","blue","yellow","green","black"}; char **pc; for(i=0;i<5;i++) printf("%s",*(pc+i));
行指针
int i; char color[6][7]={"red","blue","yellow","green","black"}; char (*p)[7]; for(i=0;i<5;i++) printf("%s",*(p+i));
函数返回值为指针
查找子串
返回子串第一个字符所在位置用指针表示
char *match() { char ch,str[80],*s=str; scanf("%s",str); getchar(); ch=getchar(); while(*s!='\0') { if(*s==ch) return s; else s++; } return (NULL); }
1.2 本章学习体会
学习感受
指针类型的题集,我几乎都是用数组做的,因为数组先入为主,掌握基本的知识比之前做数组的题目要上手一些。我对指针的了解也只是皮毛,运用的不是得心应手。很多时候用数组可以处理的问题,用指针我反而不会了。何时使用指针会简化PTA的题目,而何时用指针反而使题目复杂化,对于这样的使用指针的一个程度我还没有把握到。指针的使用是有一个限度的,学习它就要找到那个限度才能算是真正的征服了指针,不然就是指针碾压我们。后续要再多练习,仍旧不能对指针有松懈,林老师说下周一指针测试的时候我的内心慌的不行。总感觉指针这一章,我什么都没学到,而且一直想知道明明学了数组,为什么还要再学指针(在我心里觉得指针和数组是等价的)!!!最明显的感受是这两周代码量明显降低了,而且学C的热情也有所降低,没有之前的关注了,之前一道题目我可以调试一个小时两个小时的,现在调半个小时我就烦了,会把问题拖到明天,之前是今天的问题今天一定要解决。因为心态发生变化了,积极性也降低了,后果就来了,上一次数组的小测,直接爆炸。这次的事情给了我提醒,要想学好一门语言,不拿出百分之二百的热情对待它根本学不好,中途也不能开小差,不能有任何的侥幸心理。坚持下去......一路走到底,未来仍可期。有一句话,要时时刻刻放在心上,铭记在心里。不忘初心,方得始终。想想当初学习IT的那份决心,万不可松懈。学习如逆水行舟,不进则退。可能是因为长时间的写博客作业,加上我们理科生对文字并不敏感,在完成博客作业上,我感觉到了逐渐的松懈,但是博客作业对我们来说是一种总结,我们不能把它当成作业来完成,而是要享受这个过程,这是一个自我复习、自我巩固的过程,也能帮助我们自我完善,改观疲倦心态,不忘初心!
代码量
2.PTA实验作业
2.1 题目名1-7-4 说反话-加强版
2.1.1 伪代码
定义一个字符指针char *str用来储存输入字符 定义一个整型变量int min用来储存第一个单词最后一个字符所在位置 动态申请字符指针的内存大小str = (char*)malloc(500005 * sizeof(char))防止栈溢出,所以在堆里申请 输入字符串 int len=strlen(str)-1; int p=len;//每次输出最后一个单词后,长度要对应减少用p来储存 for int i=0 to len do i++ if(str[i]!=' ') 把此时的i储存在min中 break end if end for for i=len-1 to 0 do i-- if (str[i] == ' ' && ((str[i + 1] >= 'a' && str[i + 1] <= 'z') || (str[i + 1] >= 'A' && str[i + 1] <= 'Z')))//找到最后一个单词的首字符 for int j=i+1 to p do j++ if (str[j] == ' ') break; end if 输出字符str[j] end for if((j-1)!=min)//防止最后一个单词多输出空格 输出空格 end if p=i; end if end for for i=0 to min+1 do i++ 输出字符str[i] end for 释放动态申请的空间free(str)
2.1.2 代码截图
2.1.3 总结本题的知识点
定义指针字符串,更能动态了解当初字符及其位置 如果头文件包括#include<string.h> 可以直接使用strlen函数 没有#include<string.h> 的头文件,就直接最字符串进行扫描让指针指到最后一个字符 while(*str&&*str!='\n') str++ 找到字符串中第一个空格的位置,防止最后输出时字符串后面多了一个空格。 while(str[min]!=' ') min++; 找到子字符串的首字符,当前字符是空格下一个字符为字母就是子字符串的首字符 if (str[i] == ' ' && ((str[i + 1] >= 'a' && str[i + 1] <= 'z') || (str[i + 1] >= 'A' && str[i + 1] <= 'Z')))
2.1.4 PTA提交列表及说明
Q1:两个测试点没过,最大字符长度还有最后一个单词有空格 A1:重新写所有的代码,提交。 Q2:多种错误所有测试点都没有过,总感觉自己写的没毛病,可是它就是不按照我预期的输出 A2:有一个循环进入进入了死循环,而且有好几个循环即使满足了条件也不会进入,然后对这些问题进行修改,再提交 Q3:代码没有救了,各种测试点,各种错误,卡着,不给你过。 A3:没有办法了,只能去百度搜这道题目了。 Q4:运行我写的代码还是不能正确的输出,百度上的代码还使用了一个我之前没有见过的函数strtok,尽管是这样还是错了很多 A4:这个时候,代码的可读性已经很低了,参杂了自己的代码,还加入了百度上面的代码。我就决定在纸上重新整理一下自己的思路。 Q5:明明样例输出和我运后的结果是一样的,可是PTA这个测试点sample没给我过 A5:因为空格不好看出错误,我就把空格用#来代替,果然就发现了,输出后的字符在末尾都多加了一个空格,用一个变量储存第一个空格的位置,这样在输出空格时加一条判断语句,就可以末尾不输出空格 Q6:最后一个测试点,最长长度的字符串输出没过 A6:灵机一闪,把字符串长度比题目的要求加5,果然就过了
2.2 题目名2-6-9 合并两个有序数组
2.2.1 伪代码
定义一个整型指针*temp 动态申请空间temp = (int*)malloc((m + n) * sizeof(int)) for int k=0 to do k++ if(a[int i=0]<b[int j=0] 把a[i]储存在temp[k]中 i++ else 把b[j]储存在temp[k]中 j++; ende if end for while(i<m) do 依次把a数组中剩余的元素赋值给temp end while(j<n) do 依次把b数组中剩余的元素赋值给temp end for i=0 to m+n do i++ 把temp中的元素依次赋值给a数组 释放内存free(temp)
2.2.2 代码截图
2.2.3 总结本题的知识点
使用指针扫描两个有序数组并有序储存,运行时间少于先合并两个数组再将合并数组进行排序 两个数组长短不一样时,for循环结束时不能扫描完全,要继续用循环将没有扫描到的数组元素放入到temp中
2.2.4 PTA提交列表及说明
Q1:程序不能运行 A1:错误太多了,改一个又错一个,只能重新写程序了 Q2:写了一个新的代码,先合并两个数组再将合并数组进行排序 A2:部分正确,当两个数组的长度都达到极限时,运行超时。 Q3:上面那种情况我不知道怎么处理,就去向助教请教了.... A3:助教说,用一个新的数组存放两个数组元素较小的那一个数,又重新写过了代码 Q4:答案错误,数组储存不完整,没有把所有的元素都放进去 A4:用两个while循环,将没有遍历的元素放进新数组中去
2.3 题目名3- 删除字符串中的子串
2.3.1 伪代码
定义一个数组str1[83]用来储存主串 定义一个数组str2[83]用来储存子串 定义一个变量k用来储存当前主串所在位置 输入主串 输入子串 int len1=strlen(str1)-1 int len2=strlen(str2)-1 for int i=0 to len1 do i++ k=i int j=0 while(str1[k] == str2[j]&&str1[k + 1]&&str2[j + 1]) do k++;j++ end if(str2[j] == '\0' ||str2[j] == '\n') for int m=0 to len2 do m++ for int t=i to len1 do t++ 将数组str1[]往前移,达到删除子串的目的 end for 给数组最后一个字符赋0 end for len1=len1-len2 i=-1 end if end for 输出数组str1[]
2.3.2 代码截图
2.3.3 总结本题的知识点
运用指针,判断主串里面是否含有子串,储存子串首字符在主串中的位置然后将主串向前移动len2次 主串删除子串后,长度减少len2,所有每一次删除后,都要对len1进行减法运算 len1=len1-len2 每删除一次子串后,让循环位置回到0,从头开始进行扫描,这样就能解决嵌套子串的问题 i=-1
2.3.4 PTA提交列表及说明
Q1: A1: Q2: A2: Q3: A3: Q4: A4: Q5: A5: