6-1 輸出月份英文名
PTA提交列表:
1.設計思路
(1)主要描述題目算法
第一步:將十二個月的名稱分別賦值給一維數組指針,定義用於返回的數據類型。
第二步:遍歷數組,滿足若n在1-12范圍則將month第n-1行的首元素的地址賦給一開始定義的數據。
第三步:返回變量的地址值。
2.實驗代碼
char *getmonth( int n ) {
char *month[12] = {"January","February","March","April","May","June","July","August","September","October","November","December"};
char *pc = '\0';
if(n>0 && n<=12){
pc = *(month+n-1);
}
return pc;
}
3.本題調試過程碰到問題及解決辦法
錯誤點1:* pc未等於' \0 ',導致當輸入的月份不為1-12范圍內時,則停止工作。
解決方法:在注意到題目中“返回空指針NULL”后,將返回的指針型pc賦初值為'\0'。
錯誤點2:pc寫成等於month+n-1
解決方法:在單步調試時,查看了(month+n-1)的值,加上 * (month+n-1)后結果為正確,然而上課時並沒有很注意老師說的這個知識點,所以有一點疑惑,在詢問了二班的李伍壹同學后,並觀看了老師的ppt並自己手動調試后,最終解決了問題: * (month+n-1)是第n-1行首元素的地址,** (month+n-1) 是第n-1行首元素的值。 李伍壹同學認真的程度真的很值得我去學習,同時自己也需要自我批評,課上一定要高度集中注意力。
6-2 查找星期
PTA提交列表:
1.設計思路
(1)主要描述題目算法
第一步:將一個星期每天的英文分別賦值給一維數組指針,定義一個整型變量,賦初值為-1。
第二步:遍歷一維數組,用strmcp函數比較數組中每行元素與輸入的字符串是否相同,若相同,則令此時的行數等於一開始定義的整型變量,且跳出循環。
第三步:返回整型變量值。
2.實驗代碼
int getindex( char *s ) {
int k=-1,i=0;
int *day[7] = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
for(i=0;i<7;i++) {
if(strcmp(*(day+i),s)==0) {
k = i;
break;
}
}
return k;
}
3.本題調試過程碰到問題及解決辦法
錯誤點1:將strcmp((day+i),s)==0直接寫成 *(day+i) == *s。
解決方法:在第一題了解了之后,明白 * (day+i) 指的是第i行元素的首元素的地址,而 * s則表示的是首字母的值;且想起數組比較是否相等的話,必須要一個一個字母進行比較,只能用for循環或者是比較strcmp((day+i),s)的值,若為0則相等。
strcmp函數:對兩個字符串進行自左至右逐個字符相比,按ASCII值的大小比較,全部相等值則為0,出現不相等的字符,則以第一個不相同的字符比較為准,若前者大於后者,函數值為正整數,反之為負整數。
6-3 計算最長的字符串長度
PTA提交列表:
1.設計思路
(1)主要描述題目算法
第一步:遍歷s數組,運用strlen函計算出每行元素的長度。
第二步:在for循環中進行比較,定義int型max,賦初值為0,當行元素的長度大於max,則將長度的值賦給max。
第三步:返回max的值。
(2)流程圖
2.實驗代碼
int max_len( char *s[], int n ) {
int max = 0,i=0,len;
for(i=0;i<n;i++) {
len = strlen(*(s+i));
if(len > max) {
max = len;
}
}
return max;
}
3.本題調試過程碰到問題及解決辦法
無
6-4 指定位置輸出字符串
PTA提交列表:
1.設計思路
(1)主要描述題目算法
第一步:先遍歷s字符數組,找到與ch1相同時s的下標,並將下標值賦給一個整型變量,定義為j。
第二步:在確定下標后,定義一個指針字符temp,將&s[i]賦給temp,后跳出循環。
第三步:從上面的j開始,循環字符數組s,在循環中分情況,若s[i] != ch2,則輸出s[i],反之則輸出s[i]加換行,且返回temp。
第四步:循環結束后,輸出換行及返回temp。
(2)流程圖
2.實驗代碼
/*
char *match( char *s, char ch1, char ch2 ) {
int i,j=strlen(s),k = 0,m=0;
char temp1[j+1];
char temp2[j+1];
for(i=0;s[i] != '\0';i++) {
if(s[i] == ch1) {
j = i;
break;
}
}
for(i=0;s[i] != '\0';i++) {
if(s[i] == ch2) {
k = i;
break;
}
}
if(k==0) {
k = strlen(s);
}
for(i=j;i<=k;i++) {
temp1[m] = s[i];
m++;
}
printf("%s\n",temp1);
m=0;
for(i=j;s[i] != '\0';i++) {
temp2[m] = s[i];
m++;
}
return temp2;
}
*/
char *match( char *s, char ch1, char ch2 ) {
int i,j=strlen(s),k = 0,m=0;
char *temp;
for(i=0;s[i] != '\0';i++) {
if(s[i] == ch1) {
temp = &s[i];
j = i;
break;
}
}
for(i=j;s[i] != '\0';i++) {
if(s[i] != ch2) {
printf("%c",s[i]);
} else {
printf("%c\n",s[i]);
return temp;
}
}
printf("\n");
return temp;
}
3.本題調試過程碰到問題及解決辦法
錯誤點1:在dev中運行正確,卻在pta全部答案錯誤。
解決方法:將temp2字符數組改成指針變量后,則為部分正確,猜測為pta中此題不支持字符數組的形式,最后將temp1舍去,按照滿足條件則輸出對應單個字符的思路重新構思代碼,最后正確。
一道編程題:
#include <stdio.h>
int main ()
{
int m=20,n=970;
//int型變量范圍為-32768-32767,int n[10000]是不行的,因為這樣定義的數組用的是棧
//內存,系統默認值為最大1Mb,一個int型占4字節這樣最大可以申請1024*1024/4=264144
//個,如果考慮到系統自身的占用最大值為25000個。
int *p = (int *)malloc((m*n) *sizeof(int));
int *q = (int *)malloc((m*n) *sizeof(int));//用的是堆內存,只要內存中有那么多的連續空間就可以。
int i=0,j;
for(i=0;i<(m*n);i++) {
p[i] = i+1;
}
for(i=0;i<(m*n);i++) {
for(j = i+1;j<=(m*n);j++) {
if(p[i] !=1&&p[j] != 1) {
if(p[j]%p[i] ==0) {
p[j] = 1;
}
}
}
}
j=0;
for(i=0;i<(m*n);i++) {
if(p[i] != 1) {
printf(" %d",p[i]);
j++;
}
if(j == 5) {
printf("\n");
j=0;
}
}
}
然而上面的代碼是存在bug的,當數字過大時,最終系統會一直加載不出來,例:當輸入的數字是20970時,最后答案是可以的,然而變成201970時則不可以。而在老師講授完此課程的時候,自己又將自己的代碼進行了一次修改,最后答案可以輸出。
#include <stdio.h>
#define N 201
#define M 970
int a[N][M];
int del(int s[N][M],int x) {
int n,m;
for(n=0;n<N;n++) {
for(m=1;m<M;m++) {
if(s[n][m]==0) continue;
if(s[n][m]!=x && (s[n][m]%x)==0) {
s[n][m]=0;
}
}
}
return 0;
}
int main()
{
int n=0,m=0,number=1,i=0;
for(n=0;n<N;n++) {
for(m=0;m<M;m++) {
a[n][m]=number++;
}
}
for(n=0;n<N;n++) {
for(m=1;m<M;m++) {
if(a[n][m]!=0) {
del(a,a[n][m]);
}
}
}
for(n=0;n<N;n++) {
for(m=1;m<M;m++) {
if(a[n][m]!=0) {
printf(" %d",a[n][m]);
i++;
}
if(i==5) {
printf("\n");
i=0;
}
}
}
return 0;
}
6-1 奇數值結點鏈表
PTA提交列表:
1.設計思路
(1)主要描述題目算法
第一步:在readlist函數中,將輸入的值存儲在鏈表里,且用while循環時條件為輸入的值不為-1,在while循環內對p進行動態分配內存,切記在完全輸入以后,末尾結點的next為空,最后返回鏈表的頭結點。
第二步:在getodd函數中,根據題目要求的條件對鏈表結點中date的值進行分類判斷,將數值為偶數的date存儲在一個新的鏈表中,另將為奇數的存儲在一個新的列表中。
第三步:需考慮若最后新建鏈表有可能為空的情況。
第四步:最后按照要求返回要求鏈表的頭結點。
(2)流程圖
2.實驗代碼
struct ListNode *readlist() {
int number;
struct ListNode *p = NULL,*head = NULL,*tail = NULL;
scanf("%d",&number);
while(number!=-1&&number>0 ) {
p = (struct ListNode*)malloc(sizeof(struct ListNode));
p->data = number;
if(head == NULL) {
head = p;
} else {
tail->next = p;
}
tail = p;
scanf("%d",&number);
}
if(head == NULL) {
return NULL;
}
tail->next = NULL;
return head;
}
struct ListNode *getodd( struct ListNode **L ) {
struct ListNode *p = *L,*head1 = NULL,*r = NULL,*L1 = NULL,*r1 = NULL;
while(p!=NULL&&p->data>0) {
if(p->data%2!=0) {
if(head1 == NULL) {
head1 = p;
} else {
r->next = p;
}
r = p;
} else {
if(L1 ==NULL) {
L1 = p;
} else {
r1->next = p;
}
r1 = p;
}
p = p->next;
}
if(head1==NULL){
return NULL;
} else {
r->next = NULL;
}
if(L1==NULL) {
*L = NULL;
} else {
r1->next = NULL;
*L = L1;
}
return head1;
}
3.本題調試過程碰到問題及解決辦法
錯誤點1:未在readList子函數中加上tail->next = p.
解決方法:在dev中運行沒有結果且調試會出錯,在多次單步運行后發現若最后不加tail->next = p,最后的p->next不會為空,傳下去則會造成getodd函數中的p值在最后仍不為空,最后造成系統的報錯。
錯誤點2:在getodd函數中while的條件寫成p->next!=NULL。
解決方法:在單步調試后發現,若寫成p->next!=NULL,最后一個結點會不滿足while的條件,直接跳過循環,進入下一步,最終導致答案錯誤。
6-2 學生成績鏈表處理
PTA提交列表:
1.設計思路
(1)主要描述題目算法
第一步:在createlist函數中將輸入的學號,姓名和分數存儲到鏈表中,while循環的條件為學號不為0,因當學號為0時不需要輸入姓名及分數,即結束,因此需明確必須在判斷學號不為0的情況下才可以輸入姓名和成績,返回鏈表的頭結點。
第二步:在deletelist函數中遍歷鏈表的結點,若結點中的分數小於規定的值則釋放此結點的內存,需注意若最終結點全被釋放完內存,即返回的頭結點為空的情況。
第三步:將判斷后鏈表的頭結點返回主函數。
(2)流程圖
2.實驗代碼
struct stud_node *createlist() {
int num,score;
char name[20];
struct stud_node *p,*head=NULL,*tail=NULL;
p = (struct stud_node*)malloc(sizeof(struct stud_node));
scanf("%d",&num);
while (num != 0)
{
p = (struct stud_node *)malloc (sizeof (struct stud_node));
scanf ("%s %d", p->name, &p->score);
p->num = num;
if (head == NULL)
head = p;
else
tail->next = p;
tail = p;
scanf ("%d", &num);
}
return head;
}
struct stud_node *deletelist( struct stud_node *head, int min_score ) {
struct stud_node *L=head,*head1=NULL,*tail1=NULL;
while(L!=NULL) {
if(L->score>=min_score)
{
if(head1==NULL) {
head1 = L;
} else {
tail1->next = L;
}
tail1 = L;
} else {
free(L);
}
L=L->next;
}
if(head1==NULL) {
return NULL;
} else {
tail1->next =NULL;
}
return head1;
}
3.本題調試過程碰到問題及解決辦法
錯誤點1:在判斷輸入的成績小於規定值后,並沒有將此時的結點內存釋放。
解決方法:在看了PTA調試錯誤的類型后,重新仔細思考了自己的代碼結合老師上課所講的用free可以釋放內存的知識點,最終解決問題。
錯誤點2:在函數deletelist中while循環的結束后,忘記加tail1->next =NULL,導致第一個測試點答案錯誤。
解決方法:在調試及各種值的帶入都找不出錯誤原因后,仔細思考了此測試點沒錯的同學的代碼,最終發現問題。
6-3 鏈表拼接
PTA提交列表:
1.設計思路
(1)主要描述題目算法
(2)流程圖
2.實驗代碼
struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2) {
struct ListNode *p1=list1;
int length=0;
int array[100];
for(p1=list1;p1!=NULL;p1=p1->next) {
array[length] = p1->data;
length++;
}
p1=list2;
for(;p1!=NULL;p1=p1->next) {
array[length] = p1->data;
length++;
}
int i,j,t;
for(i=0;i<length-1;i++) {
for(j=i+1;j<length;j++) {
if(array[j]<array[i]) {
t =array[j];
array[j]=array[i];
array[i] = t;
}
}
}
struct ListNode *q,*head1 = NULL,*tail1=NULL;
i=0;
while(i<length) {
q = (struct ListNode *)malloc(sizeof(struct ListNode));
q->data = array[i];
if(head1 == NULL) {
head1 = q;
} else {
tail1->next = q;
}
tail1 = q;
tail1->next = NULL;
i++;
}
return head1;
}
3.本題調試過程碰到問題及解決辦法
遇到的問題1:將函數最后的tail1->next=q與tail1=q位置放反,導致系統崩壞。
解決方法:單步調試后發現順序的問題,最后改正。
遇到的問題:一開始自己的思路為,新建一個鏈表,將之前兩個鏈表的值統合到此一個列表中,在定義一個一維數組,最后將新建鏈表中date的值賦給此一維數組,然后用選擇法進行數組元素的排序,最終將排好序的數組賦值給一個新的鏈表,最終返回新的鏈表頭結點
,但在pta中會導致最后結果全為段錯誤,即超出內存。
最后在網上搜尋答案后,簡化代碼,即直接將合並的兩個鏈表的值直接賦給一維數組,然后進行選擇法排序,將排好的值賦給新建鏈表即可,最后返回新建列表的頭結點。
struct ListNode *p1=list1,*head1=NULL,*tail1=NULL;
for(;p1!=NULL;p1=p1->next) {
if(head1==NULL) {
head1 = p1;
} else {
tail1->next=p1;
}
tail1 = p1;
}
p1 = list2;
for(;p1!=NULL;p1=p1->next) {
tail1->next = p1;
tail1 = p1;
}
tail1->next=NULL;
int length=0;
int array[100];
for(p1=head1;p1!=NULL;p1=p1->next) {
array[length] = p1->data;
length++;
}
學習總結和進度
1、總結兩周里所學的知識點,回答下列問題?
1)如何理解指針數組,它與指針、數組有何關系?為何可以用二級指針對指針數組進行操作?
答:指針數組是存放指針的數組,即是數組的形式,但數組中的元素為指針,而指針又叫指針變量是存放指針的變量,即存放地址的變量;用二級指針指向指針數組的第一個元素,此時二級指針中存放指針數組第一個元素的地址,若定義二級指針為int ** p,指針數組為 int * num[]里面存儲着int a[]的地址,則p表示num[0]的值,指向a[0],值為a[0]的地址, p+i指向數組元素a[i],且 * (*p+i)表示數組元素a[i]。
2)將C高級第三次PTA作業(1)任何一個題目改為使用二級指針對指針數組進行操作。
6-1 輸出月份英文名改為使用二級指針對指針數組進行操作,代碼如下:
char *getmonth( int n ) {
char *month[12] = {"January","February","March","April","May","June","July","August","September","October","November","December"};
char **p = &month[0];
char *pc = '\0';//*pc未等於'\0'
if(n>0 && n<=12){//n寫成>=0
pc = *(p+n-1);//pc寫成等於month+n-1
}
return pc;
}
3)用指針數組處理多個字符串有何優勢?可以直接輸入多個字符串給未初始化的指針數組嗎?為什么?
答:如果用二維數組保存多個字符串比較浪費內存空間,每個字符串必須要占用同樣的字節數,從而浪費了一定的空間,而指針數組的話,可以通過初始化字符串由編譯器自動決定數組的長度,從而節約內存;不可以,因為若未將指針初始化的話,指針會指向一個不確定的地址,而此地址中有可能存儲着有用的數據,會破壞系統的正常工作情況。
2、將PTA作業的源代碼使用git提交到托管平台上,要求給出上傳成功截圖和你的git地址。
git地址:(https://git.coding.net/exo07/disizhouzuoye.git)
3、點評3個同學的本周作業(在作業中給出被點評同學博客的鏈接),並邀請3名同學點評你的作業
史澤文:(http://www.cnblogs.com/shilcz/p/8906128.html)
高立彬:(http://www.cnblogs.com/gao628526/p/8781936.html)
董欣:(http://www.cnblogs.com/dx2017/p/8781858.html)
4、請用表格和折線圖呈現你本周(4/9 8:00~4/23 8:00)的代碼行數和所用時間、博客字數和所用時間