這個做業屬於哪一個課程 | C語言程序設計Ⅱ |
---|---|
這個做業要求在哪裏 | 第十一週做業 |
我在這個課程的目標是 | 可以使用c語言實現基本的程序設計,以致最後可以設計出較大的項目 |
這個做業在哪一個具體方面幫助我實現目標 | 學習遞歸程序設計,宏的基本定義以及文件包含等內容 |
參考文獻 | C語言程序設計(第3版); C Primer Plus (第6版) |
漢諾塔是一個源於印度古老傳說的益智玩具。聽說大梵天創造世界的時候作了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞着64片黃金圓盤,大梵天命令僧侶把圓盤移到另外一根柱子上,而且規定:在小圓盤上不能放大圓盤,每次只能移動一個圓盤。當全部圓盤都移到另外一根柱子上時,世界就會毀滅。
請編寫程序,輸入漢諾塔圓片的數量,輸出移動漢諾塔的步驟。
輸入格式
圓盤數 起始柱 目的柱 過分柱
輸出格式
移動漢諾塔的步驟
每行顯示一步操做,具體格式爲:
盤片號: 起始柱 -> 目的柱
其中盤片號從 1 開始由小到大順序編號。
輸入樣例html
3 a c b
輸出樣例c++
1: a -> c 2: a -> b 1: c -> b 3: a -> c 1: b -> a 2: b -> c 1: a -> c
#include<stdio.h> void hanio (int n, char op1, char op2, char op3); int main () { int n; char op1,op2,op3; char p,q; scanf ("%d%c",&n,&p); scanf ("%c%c%c%c%c",&op1,&q,&op2,&q,&op3); hanio (n,op1,op2,op3); return 0; } void hanio (int n, char op1, char op2, char op3) { if (n==1) printf ("%d: %c -> %c\n",n,op1,op2); else { hanio (n-1,op1,op3,op2); printf ("%d: %c -> %c\n",n,op1,op2); hanio (n-1,op3,op2,op1); } }
如圖,在最開始寫的時候,程序中第21行 printf
語句後面輸出的是n-1的值,致使結果中全部圓盤編號都小了一,再仔細讀了一遍程序後,發現問題,將n-1改成n便可。編程
以上圖片來自新浪微博。
本題要求你實現一個稍微更值錢一點的 AI 英文問答程序,規則是:
不管用戶說什麼,首先把對方說的話在一行中原樣打印出來;
消除原文中多餘空格:把相鄰單詞間的多個空格換成 1 個空格,把行首尾的空格所有刪掉,把標點符號前面的空格刪掉;
把原文中全部大寫英文字母變成小寫,除了 I
;
把原文中全部獨立的 can you
、could you
對應地換成 I can
、I could
—— 這裏「獨立」是指被空格或標點符號分隔開的單詞;
把原文中全部獨立的 I
和 me
換成 you
;
把原文中全部的問號 ?
換成驚歎號 !
;
在一行中輸出替換後的句子做爲 AI 的回答。
輸入格式:
輸入首先在第一行給出不超過 10 的正整數 N,隨後 N 行,每行給出一句不超過 1000 個字符的、以回車結尾的用戶的對話,對話爲非空字符串,僅包括字母、數字、空格、可見的半角標點符號。
輸出格式:
按題面要求輸出,每一個 AI 的回答前要加上AI:
和一個空格。
輸入樣例:數組
6 Hello ? Good to chat with you can you speak Chinese? Really? Could you show me 5 What Is this prime? I,don 't know
輸出樣例:markdown
Hello ? AI: hello! Good to chat with you AI: good to chat with you can you speak Chinese? AI: I can speak chinese! Really? AI: really! Could you show me 5 AI: I could show you 5 What Is this prime? I,don 't know AI: what Is this prime! you,don't know
代碼參考博客數據結構
#include<stdio.h> #include<string.h> char a[1050]; char b[1050]; int ac(char t) { if((t-'a')>=0&&(t-'a')<26||(t-'A')>=0&&(t-'A')<26||(t-'0')>=0&&(t-'0')<=9) return 1; return 0; } int main() { int i,t,n,m; scanf("%d",&t); getchar(); while(t--) { gets(a); printf("%s\n",a); memset(b, 0, sizeof b); n=strlen(a); printf("AI:"); m=0; int o=0; for(i=0;i<n;i++) { if(a[i]==' ') { o=1; } else { if(o==1||i==0) { b[m++]=' '; o=0; } if((a[i]-'A')<26&&(a[i]-'A')>=0) { if(a[i]!='I') { b[m++]=a[i]+32; } else { b[m++]=a[i]; } } else if(a[i]=='?') { if(b[m-1]!=' ') { b[m++]=' '; } b[m++]='!'; } else if(ac(a[i])==1) { b[m++]=a[i]; } else { if(b[m-1]!=' ') { b[m++]=' '; } b[m++]=a[i]; } } } b[m++]=' '; printf(" "); for(i=1;i<m-1;i++) { if(b[i]==' ') { if(ac(b[i+1])==1) { printf(" "); } else { } } else if((b[i]-'a')>=0&&(b[i]-'a')<26) { if(b[i]=='c'&&b[i-1]==' '&&b[i+1]=='a'&&b[i+2]=='n'&&b[i+3]==' '&&b[i+4]=='y'&&b[i+5]=='o'&&b[i+6]=='u'&&b[i+7]==' ') { printf("I can"); i+=6; } else if(b[i]=='c'&&b[i-1]==' '&&b[i+1]=='o'&&b[i+2]=='u'&&b[i+3]=='l'&&b[i+4]=='d'&&b[i+5]==' '&&b[i+6]=='y'&&b[i+7]=='o'&&b[i+8]=='u'&&b[i+9]==' ') { printf("I could"); i+=8; } else if(b[i]=='m'&&b[i-1]==' '&&b[i+1]=='e'&&b[i+2]==' ') { printf("you"); i+=1; } else { printf("%c",b[i]); } } else if(b[i]=='I'&&b[i-1]==' '&&b[i+1]==' ') { printf("you"); } else { printf("%c",b[i]); } } printf("\n"); } return 0; }
查的這個答案還算看得懂一點點,其餘的要麼是用c++,要麼是用Java,要麼是Python......其實原理就是按照題目要求去實現就行,只是很繁瑣,很麻煩。雖然我如今也不是很懂(由於這段代碼中還有部分代碼看不懂)。除此以外,在這道題的代碼中,我認識了一個新函數,之後可能會用上。0.0函數
memset()的函數,它能夠一字節一字節地把整個數組設置爲一個指定的值。 memset()函數在mem.h頭文件中聲明,它把數組的起始地址做爲其第一個參數,第二個參數是設置數組每一個字節的值,第三個參數是數組的長度(字節數,不是元素個數)。其函數原型爲:void memset(void,int,unsigned);學習
在國際象棋中,皇后是最厲害的棋子,能夠橫走、直走,還能夠斜走。棋手馬克斯·貝瑟爾 1848 年提出著名的八皇后問題:即在 8 × 8 的棋盤上擺放八個皇后,使其不能互相攻擊 —— 即任意兩個皇后都不能處於同一行、同一列或同一條斜線上。
如今咱們把棋盤擴展到 n × n 的棋盤上擺放 n 個皇后,請問該怎麼擺?請編寫程序,輸入正整數 n,輸出所有擺法(棋盤格子空白處顯示句點「.」,皇后處顯示字母「Q」,每兩格之間空一格)。
輸入格式
正整數 n (0 < n ≤ 12)
輸出格式
若問題有解,則輸出所有擺法(兩種擺法之間空一行),不然輸出 None。
要求:試探的順序逐行從左往右的順序進行,請參看輸出樣例2。
輸入樣例1ui
3
輸出樣例1this
None
輸入樣例2
6
輸出樣例2
. Q . . . . . . . Q . . . . . . . Q Q . . . . . . . Q . . . . . . . Q . . . Q . . . . . . . . Q . Q . . . . . . . . Q . Q . . . . . . . . Q . . . . . Q . . Q . . . . . . . . . Q . . Q . . . . . . . . . Q . . Q . . . . . . . Q . . . Q . . . Q . . . . . . . . . . Q . . . Q . . . Q . . . .
沒怎麼看懂,不會畫....
該種解法是經過一個較簡單的例子:n個數的全排列,所造成的剪枝函數稍加修改(改爲判斷這一行,這一列,斜線有沒有皇后),就變成了八皇后問題。
例如,若是想將二維數組賦給指針,則能夠
int b[3][4]; int(*pp)[4]; //定義一個數組指針,指向含4個元素的一維數組 pp = b; //將該二維數組的首地址賦給pp,也就是b[0]或&b[0],二維數組中pp=b和pp=&b[0]是等價的 pp++; //pp=pp+1,該語句執行事後pp的指向從行b[0][]變爲了行b[1][],pp=&b[1]
例如,如要將二維數組賦給一指針數組,能夠
int *p[3]; int a[3][4]; for(i=0;i<3;i++) p[i]=a[i];
來實現,這裏int *p[3] 表示一個一維數組內存放着三個指針變量,分別是p[0]、p[1]、p[2],因此要分別賦值。
詳情參考:博客1,博客2。
例如,int *fun(int x,int y); 就是一個簡單的自定義的一個指針函數的聲明寫法。它的定義能夠根據本身的目的去定義。其返回值是一個 int 類型的指針,是一個地址。
詳情參考:博客1,博客2
例如,int (fun)(int x,int y); 就是一個函數指針的聲明格式。函數指針是須要把一個函數的地址賦值給它,有兩種寫法:fun = &Function;fun = Function; 取地址運算符&不是必需的,由於一個函數標識符就表示了它的地址,若是是函數調用,還必須包含一個圓括號括起來的參數表。能夠用x = (fun)(); 的方式調用函數指針。
詳情參考:博客1,博客2
例如,
void buf ( int **a ) { ( *a) = ( int* )malloc ( sizeof ( int ) ); ( **a )= 1; printf ( "%d",**a ); } int main( int argc, char *argv[] ) { int *a; buf ( &a ); //printf ( "%d",*a ); }
當你要給*a賦值的時候,發現他是一個指針,沒有內存空間來存儲值,不能直接給他賦值,要給他先建立一個內存空間。固然你能夠直接的malloc ()在主函數裏。這個就不說了。可是,若是你想要在調用一個函數實現呢?你能夠這樣想,若是我有一個東西,能接受個人這個指針的地址,這樣就能夠在調用的函數裏面經過他的地址,就能夠在調用的函數裏面,進行malloc (),而這個能存儲地址的就是二級指針。
詳情參考:博客。
單向鏈表鏈表是鏈表的一種。
鏈表是什麼? 鏈表是一種常見而重要的動態存儲分佈的數據結構。能夠將一條鏈表想象成環環相扣的結點,就如日常所見到的鎖鏈同樣。鏈表內包含不少結點(固然也能夠包含零個結點)。其中每一個結點的數據空間通常會包含一個數據結構(用於存放各類類型的數據)以及一個指針,該指針通常稱爲next,用來指向下一個結點的位置。因爲下一個結點也是鏈表類型,因此next的指針也要定義爲鏈表類型。
鏈表的結構
例如:
typedef struct LinkList { int Element; LinkList * next; }LinkList;
就定義了一種鏈表的結構類型。
詳情參考:鏈表;C語言程序設計(第3版) P285 。
單向鏈表的組成以下圖,
詳情參考:單向鏈表的創建,可參考:C語言程序設計(第3版) P286;博客。
用鏈表代替數組進行數據的存儲與操做有兩優勢:1、不須要事先定義存儲空間大小,能夠實時動態分配,內存使用效率高;2、能夠方便地插入新元素(結點),是信息庫保持排序狀態,操做效率高。
周/日期 | 這周所花的時間 | 代碼行數 | 學到的知識點簡介 | 目前比較迷惑的問題 |
---|---|---|---|---|
3/2-3/8 | 三天六小時 | 50 | 一、定義、運用文件指針;二、如何打開、關閉文件三、如何讀出指定文件中的數據;四、如何向指定文件中寫入數據; | 字符、字符串有什麼區別?兩者輸入、輸出有沒有很大不一樣?什麼纔算字符串?什麼算字符?在文件中兩者有沒有差異? |
3/9-3/15 | 四天三小時 | 180 | 一、運用二維數組解決問題,矩陣的判斷;二、對一組數的全部子數組求和 | 如何在輸出時利用數組的性質 |
3/16-3/22 | 三天八小時 | 210 | 一、二維數組加深理解,二維數組與矩陣;二、選擇排序法解決問題;三、二分查找法 | 二分查找法這周沒練習,只是看看書上例題大體懂了,不知道真正應用時可否掌握。 |
3/23-3/29 | 三天兩小時 | 120 | 一、判斷回;文二、字符數組的概念及其簡單運用;三、一些簡單的與字符數組相關的暫時沒接觸補充知識,一些函數,用法等。 | 在做業運用文件指針時,一開始老是出現從文件裏輸不出來結果,打印不出來,後來發現可能與本身輸入時格式未搞好,原本不該該出現的空格出現了,致使打印不出來結果。文件指針還不是很熟練 |
3/30-4/5 | 兩天 | 150 | 一、指針的含義,變量、地址、指針變量等間的關係;二、指針變量的初始化,運用指針作一些簡單運算;三、指針與數組之間的關係 | 在用指針處理字符串時,應怎樣定義指針變量 |
4/6-4/12 | 三天 | 200 | 一、更深一步掌握指針與數組間的關係;二、懂得指針能夠實現數組的一些功能;三、指針在碰到字符數組時的應用 | 在代碼中,若是遇到要輸出單個字符,%s與%c有什麼區別? scanf()與 getchar 兩種輸入方式有區別嗎?會不會在有些狀況下能影響到輸出結果? |
4/13-4/19 | 兩天 | 170 | 一、學習了與字符串有關的一些字符串處理函數;二、學習了利用指針實現內存動態分配 | 究竟什麼狀況下采用內存動態分配?具體要採用哪種動態內存分配? |
4/20-4/26 | 兩天 | 135 | 一、學習告終構及結構變量的定義與運用 | 若是運用遞歸函數解決問題,雖然使代碼簡化了,更美觀了。但會致使相同的運算重複進行,佔內存。感受遞歸弊大於利。 |
4/27-5/3 | 一天 | 一、複習告終構與數組、指針間的關係,二者之間是如何進行替換利用; | ||
5/4-5/10 | 三天 | 165 | 一、學習了遞歸程序的設計;二、宏的基本定義;三、文件包含等內容; | 鏈表知識點看了看,不是很懂 |
本週在作題時,剛看到選擇題都懵了。覺得是我上課錯過了什麼,不少題都不肯定答案,在翻過書後才發覺,原來是沒怎麼講。看過書後有了一點概念。關鍵仍是編程題,哇,感受編程題難度不小,不,是很大。第一題是在看了例題後,照葫蘆畫瓢勉強作出來的。後面兩道題,看過以後,第一反應是老師是否是出錯題目了。以後助教在羣裏喊話,意思是盡力寫,寫不出來也要有思路,瞬間就認爲本身不須要寫出來,寫思路就行,但我看了PTA裏的提交列表後,發現有很多人都作了出來,有用c++的,有用c的,而後就感受不能放棄啊,實在不行就搜啊,只要本身看懂了,理解了,記住了,掌握了,也行。最後也勉勉強強理解了第二道編程題,價值一億的代碼。
結對時,隊友選擇題答案不肯定,互相之間討論了兩下。到編程題時,因爲題目較難,隊友也不肯直接跳過,兩我的上網搜答案,答案看不懂就互相說一說本身的想法,先將答案搞懂。
時間 | 累計代碼行數 | 累計博客字數 |
---|---|---|
第一週 | 80 | 275 |
第二週 | 50 | 883 |
第三週 | 180 | 1303 |
第四周 | 210 | 1849 |
第五週 | 120 | 1988 |
第六週 | 150 | 2717 |
第七週 | 200 | 3000 |
第八週 | 170 | 2820 |
第九周 | 135 | 2855 |
第十週 | 3945 | |
第十一週 | 165 | 4934 |