C博客作业--指针
一、PTA实验作业
题目1:6-7 过滤字符串只保留串中的字母字符
1. 本题PTA提交列表(要提交列表,不是结果)
2. 设计思路
3.代码截图
4.本题调试过程碰到问题及PTA提交列表情况说明。
- 答案错误:忘记在最后面加上‘\0’导致出现错误
- 反思:字符型数组一定一定要记得结尾有‘\0’~~
题目2:6-8 使用函数实现字符串部分复制
1. 本题PTA提交列表(要提交列表,不是结果)
2. 设计思路(伪代码或流程图)
定义i代表循环变量,j代表s数组下标
定义flag=1代表m小于字符串长度的情况
定义count来代表字符串的长度
并赋初值为0
for(i=0;*(t+i)!='\0';i++)
count++ 来计算字符串的长度
如果m大于字符串长度
则*s='\0';
flag=0;
如果m不大于字符串长度
for(i=m-1,j=0;*(t+i)!='\0';i++,j++)
*(s+j)=*(t+i); //把字符串*t中从第m个字符开始的全部字符复制到字符串*s中
最后给字符串*s末尾加上'\0'
3.代码截图
4.本题调试过程碰到问题及PTA提交列表情况说明。
- 这题思路其实并不复杂,但是我代码写着写着,到最后的时候把数组s和数组t的认识有点晕了,于是乎某个条件就不小心出现了差错:第二个for循环的终止条件是
但是我不小心把它写成了‘*(s+i)!='\0’ ,再加上这题没法用dev调试可以说是很气人.....
反思:出现这个问题的原因有自己的逻辑不够严密还有就是深深意识到老师强调变量名字要起得贴切适当的重要性,因为像a,b,s,t根本就不直观而且没有含义就容易出现我犯的那个愚蠢的错误
题目3:6-9 求子串在母串中最后一次出现的地址
1. 本题PTA提交列表(要提交列表,不是结果)
2. 设计思路(伪代码或流程图)
定义整数型变量len1,len2分别代表字符数组s和t的长度
定义整数i代表循环次数,
定义字符型变量temp来充当中间变量,*p来存放在字符串中最后一次出现的子字符串的地址
for(i=0;*(s+i)!='\0';i++)
len1++; //计算s数组的长度
for(i=0;i<len1/2;i++)
前后对应位置字符交换来实现s数组的逆序
for(i=0;*(t+i)!='\0';i++)
len2++;//计算t数组的长度
for(i=0;i<len2/2;i++)
前后对应位置字符交换来实现t数组的逆序
p=strstr(s,t); //利用函数strstr寻找子串t在s中出现的首地址并把地址传给p
若没有子串
则返回NULL
*(p+len2)=0; //目标字符的逆序串即逆序数组s加上结束符
清空len1的值
for(i=0;*(s+i)!='\0';i++)
len1++; //计算逆序数组s的长度
for(i=0;i<len1/2;i++)
前后对应位置字符交换来使逆序数组s倒序回来
最后返回数组s的地址
3.代码截图
4.本题调试过程碰到问题及PTA提交列表情况说明。
- 1.一开始拿到这道题的时候的第一想法就是把它们都逆序过来,然后寻找第一次出现的位置会更简单一些,但是一开始逆序的循环条件误写成i<len1,导致逆序完以后又逆序回来,然后就并没有实现逆序啊...
- 2.不知道可以在函数定义的时候在开头再加上
- 3.不会灵活利用函数strstr和对这个函数具体的功能不够了解和熟悉,于是乎下面有各种常用函数的总结~~
二、截图本周题目集的PTA最后排名。
三、阅读代码
char *fun (char *s, char *t ){
int i,u,index=-1;
for(i=0; *(s+i) ;i++){
if(*(s+i)==*t) {
for(u=1;*(t+u);u++) if(*(s+i+u)!=*(t+u)) break;
if(!*(t+u)) index=i;
}
}
for(u=index,i=0 ; *(s+u) ; u++,i++) *(t+i)=*(s+u);
*(t+i)='\0';
if(index==-1) return NULL;
return t;
}
- 这段代码实现的功能是:找到最后一次出现子串的位置并输出后续的子串……(PTA 6-9)
很明显这段代码与我上述的设计思路相比要简洁明了许多,直接利用找子串的思路来一直找下去,唯一的区别就是定义一个整数型变量index来记录最后一次出现子串位置的下标……然后直接从index位置开始把s数组中的字符赋值给t数组…… 然后返回即可……而我却把问题想复杂化了……一开始是思考怎么判断前面有子串后面没有……然后又想出新的思路想把数组倒过来碰到第一次就行了还以为自己的思路是比较明确的简便的……但是看到别的同学的代码后发现其实思路可以更加简便……只需要比平时的问题多引入一个变量就解决的问题却被我复杂化…… - 反思: 我的编程思维还是不好…会把问题复杂化而不是巧妙解决它……归根到底还是编程量不够和代码阅读量不够……需要后续继续多编程然后多阅读课堂派和同学的优秀代码……
#include<stdio.h>
int main (void){
char s[81],sub[81];
gets(s);
gets(sub);
int j,i,u;
do{
for(i=0,j=0;s[i]!='\0';i++){
if(s[i]==sub[0]){
for(u=1;sub[u]!='\0';u++){
if(s[i+u]!=sub[u]) break;
}
if(sub[u]=='\0'){
i=i+u-1;
continue;
}
}
s[j++]=s[i];
}
s[j]='\0';
}while(j!=i);
puts(s);
return 0;
}
- 这段代码实现的功能是:删除母串中所有的子串;
- 优点:这段代码以非常清晰明了的思路来寻找子串:利用判断是否为子串和巧妙利用s[j++]=s[i]进行删除后的数组重构……其中找到子串后便i=i+u是个很巧妙的点,利用跳过子串来实现删除子串……而且这里的continue是我自己的一个小改变...我觉得会提高代码的执行效率~
- 反思: 这个巧妙的解题思路最开始在课堂派便有与之相关的代码,而我在做这题的时候竟然是在纠结何时才结束删除:即若删除后又出现新的子串那又得再删,而且得判断新数组是否有子串,然后又把新数组讨论一遍是否有子串,如果有再一次循环……显然我的思路就显得太复杂和不清晰,而这段代码直接利用简单一句 j!=i 就完成了有子串这种情况的判断,这种思路是我还不能及需要更多的编程和代码阅读量来学习的…而且值得注意的是:好的编程思路似乎更偏向去总结归纳某类的特征,然后利用循环把其简洁明了解决,比如上次的左移右移和IP地址转换等等...革命道路还很长,我还需要努力.....
四、本周学习总结
1.自己总结本周学习内容。
一.字符串操作函数和指针
- 1.字符串操作函数
-
- 指针的运算
(1)取地址运算符&:求变量的地址
(2)取内容运算符*:表示指针所指的变量
(3)赋值运算
·把变量地址赋予指针变量
·同类型指针变量相互赋值
·把数组,字符串的首地址赋予指针变量
·把函数入口地址赋予指针变量
(4)加减运算
对指向数组,字符串的指针变量可以进行加减运算
对指向同一数组的两个指针变量可以相减。对指向其它类型的指针变量作加减运算是无意义的。
(5)关系运算
指向同一数组的两个指针变量之间可以进行大于、小于、 等于比较运算。指针可与0比较,p==0表示p为空指针。
- 指针的运算
-
- 与指针有关的各种说明和意义见下表。
- 与指针有关的各种说明和意义见下表。
- 4.指针数组
二.结构体
-
结构体类型的定义
struct 结构体名
{
类型1 成员名1;
类型2 成员名2;
类型3 成员名3;
类型n 成员名n;
} -
结构体变量的定义
方法1:定义结构体类型的同时定义变量
struct Person
{
int age; // 年龄
double height; // 身高
char *name; // 姓名
} p;
方法2:先定义结构体类型,再定义变量
struct Person
{
int age; // 年龄
double height; // 身高
char *name; // 姓名
};
struct Person p;
方法3:直接定义结构体变量,忽略类型名
struct
{
int age; // 年龄
double height; // 身高
char *name; // 姓名
} p;
注意:
1 末尾的‘;’不可以省略!
2 在结构体里面不能对数据进行初始化 原因:结构体在没有实例化的时候只是一个概念,相当于一个类型(int 等),在内存中不占有空间,所以不能进行赋值操作。
3 在结构体中不能使用static关键字定义变量
4 结构体类型不能重复定义
5 结构体内可以包含别的结构体
2.罗列本周一些错题。
课堂派错题
情景再现:其实做题的时候还是挺明白这题的思路的,但是做到最后一空的时候实在不知道要填啥啊(有两题的最后这空是一样的),这不是该完成的都完成了吗....然后就,,,没法下手
正确做法:公布答案后茅舍顿开! n代表长度数组长度啊,那你插入一个数以后,n可不就得增加一吗!!!
错误分析:这题主要是对※n++和(※n)++的区别不够清晰