C博客作业--指针
一、PTA实验作业
题目1:判断回文字符串
1. 本题PTA提交列表(要提交列表,不是结果)
2. 设计思路(伪代码或流程图)
伪代码:
函数传入数组名即地址,给形参s
定义ij为循环变量
for i=0 to s【i】!='\0'
end
i--
j=0
while (1)
如果s【i】==s【j】首尾字符相等
如果比较的字符相遇则停止循环
i--
j++
否则 返回0 结束循环
end
返回1
流程图:
3.代码截图(注意,截图,截图,截图。不要粘贴博客上。不用用···语法去渲染)
4.本题调试过程碰到问题及PTA提交列表情况说明。
答案错误
第一次没有考虑到奇数和偶数字符串的关系,结束循环的条件只写了ij时的情况,导致答案错误
解决方法:加了ji+1的结束条件就可以了
题目2:求子串在母串中最后一次出现的地址
1. 本题PTA提交列表(要提交列表,不是结果)
2. 设计思路(伪代码或流程图)
传入数组s
定义循环变量i,j,mark用于比较子串,mark2记录地址,flag判断是否为子串
for i=0 to s【i】!=‘\0’
mark=i记录比较开始的位置
for j=0 to s【j】!=‘\0’
如果该位置的字符与子串第一个相同比较下一个字符,都相同flag=0
如果不相同flag=1
如果flag==0,mark2记录i
end
如果mark2没有变化返回null
否则返回s【mark2】的地址
3.代码截图(注意,截图,截图,截图。不要粘贴博客上。不用用···语法去渲染)
4.本题调试过程碰到问题及PTA提交列表情况说明。
答案错误
1.刚开始未有设计返回空指针,导致答案一直错误
解决方法:如果mark2没有被改变,表明没有找到过子串,所以这个时候就要返回空指针
2.只找到第一个出现子串的地址
解决方法:将程序设为反复查找,并写再一次找到的地址会覆盖掉第一次查找的地址,最后的结果就是最后的地址
3.返回地址的问题:刚开始习惯直接返回数组名,但是显然不行
解决方法:用&,取出s【mark】的地址
题目3:字符串串动变化
1. 本题PTA提交列表(要提交列表,不是结果)
2. 设计思路(伪代码或流程图)
传入数组p
定义循环变量i,max存最大ASCII码最大的字符,t由于交换,code存最大码的下标
max先取p【0】code取0
for i=1 to p【i】!=‘\0’
if p【i】>max 将p【i】写入max,code保存i
end
先用t存p【code】即找到最大的字符
for i=code to 1
code的字符右移
end
t存的字符给第一个字符
3.代码截图(注意,截图,截图,截图。不要粘贴博客上。不用用···语法去渲染)
4.本题调试过程碰到问题及PTA提交列表情况说明。
问题如图,字符e消失,而A多了一个,明显是交换时发生的错误
解决方法:最后t的值不应该给p【i-1】,因为上一轮循环,i最后跳出时有发生了递减,所以,我的做法是直接交给p【0】
二、截图本周题目集的PTA最后排名。
三、阅读代码
- 猴子选大王
让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。
#include<stdio.h>
int main()
{
int i, j, k, temp;
int monkey[1001];//总数不能大于1000
unsigned int n;
scanf("%d", &n);//输入猴子总数
for (i = 0; i < n; i++){
monkey[i] = i + 1;//给猴子排序,站成一排
}
for (i = n - 1; i >= 0; i--){
for (k = 1; k <= 3; k++){
temp = monkey[0];
for (j = 0; j < i; j++){
monkey[j] = monkey[j + 1];
}
monkey[i] = temp;
}
}
printf("%d", monkey[0]);//数组头就是猴王
return 0;
}
功能:选出猴王
优点:通常的思路是考虑下标移动和删除第三个位置,但是改代码思路新颖,不去考虑下标移动和删除,而是简单的做数组数字移动,巧妙的将数到3这个步骤替换成数组数据的移动3次,第3个数就会刚好排到数组尾,再在剩下的数之间移动,第3的数就会渐渐排到后面,最后数组头就是“猴王”。当初做这道题时感觉题目会很复杂,想了好久,一点思路都没有,关键是围成一个圈,数到最后还要接到数组头,然后上网查了很多很长的代码,直到找到这个代码,原来十几行就可以了。
- 最大公共子串
求两个串的所有子串中能够匹配上的最大长度是多少。
比如:"abcdkkk" 和 "baabcdadabc",
可以找到的最长的公共子串是"abcd",所以最大公共子串长度为4。
下面的程序是采用矩阵法进行求解的,这对串的规模不大的情况还是比较有效的解法。
#include <stdio.h>
#include <string.h>
#define N 256
int f(const char* s1, const char* s2)
{
int a[N][N];
int len1 = strlen(s1);
int len2 = strlen(s2);
int i,j;
memset(a,0,sizeof(int)*N*N);
int max = 0;
for(i=1; i<=len1; i++){
for(j=1; j<=len2; j++){
if(s1[i-1]==s2[j-1]) {
a[i][j] =a[i-1][j-1]+1;
if(a[i][j] > max) max = a[i][j];
}
}
}
return max;
}
int main()
{
printf("%d\n", f("abcdkkk", "baabcdadabc"));
return 0;
}
题目思路:
动态规划的思想,a[i][j]表示到字符串s1的i位置和s2的j位置的最大公共子串的长度 ,数组初始化为0。为了方便理解,我们这么想,如果s1的字符串的第一个字符和s2的第一个字符相同,那么a[1][1] = 1;如果两个字符串的第二个字符也相同,那么,到第二个位置的最长公共子串就等于1+1 = 2,也就是到第一个字符的公共子串的个数+1。即a[i][j] = 1+ a[i-1][j-1]。因此,我们可以从第一个位置开始递推求出到任意一个位置的公共子串,在递推过程中记录最大的结果即可。
优点:巧妙的运用二维数组,通过遍历,对每个位置子串长度做了统计和比较,大大节省了时间,同时具有极高的效率。
四、本周学习总结
1.自己总结本周学习内容。
1.使用指针基本应用
利用指针的移动,代替数组下标法提高程序效率
例:
冒号排序函数用指针代替
void bubble(int *a,int n)
{
int *i,*j,t;
for(i=1+a;i<a+n;i++){
for(j=a;j<a+n-1;j++){
if(*j>*(j+1)){
t=*j;*j=*(j+1);*(j+1)=t;
}
}
}
}
数组名即地址,定义两个指针,遍历数组只需指针的移动即可,下标法需要交换数组的数,指针则只要交换地址即可,效率远比下标法搞得多
2.数组与指针是相通的,数组就是const 类型的指针,不能随意修改,但是指针就可以
3.字符型指针,指针类型都是指向变量的类型,所以字符指针指向字符,当字符指针指向字符数组时,指针名即数组的首字符的地址,即p【0】等价于*str,p【i】等价于*(str+i)
4.字符串再C语言中会自动生成地址保存它们,所以字符串可以直接赋值给指针变量,即char *p=“string”;这个字符串叫做字符串常量。
2.罗列本周一些错题。
6-11 报数(20 分)
报数游戏是这样的:有n个人围成一圈,按顺序从1到n编好号。从第一个人开始报数,报到m(<n)的人退出圈子;下一个人从1开始报数,报到m的人退出圈子。如此下去,直到留下最后一个人。
本题要求编写函数,给出每个人的退出顺序编号。
void CountOff( int n, int m, int out[] ){
int i=0,j=0,k=0,cnt=0,a[MAXN];
for(i=0;i<n;i++)
a[i] = i+1;
i=0;
while(cnt < n){
if(a[i]!=0) k++;
if(k==m){
j++;
out[i]=j;
k=0;
cnt++;
a[i]=0;
}
i++;
if(i==n) i=0;
}
}
这道题想了很久都没有思路,上网查了一下,居然只有这么短。后来理解了这题,通过in时,i0将数组连成一个圈,将数到的数变成0而做到可以跳过这个数。