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而做到可以跳過這個數。