The Twelve Days of Xmas https://www.youtube.com/v/kqeobzlx Z8 丁培毅 1
On the first day of Xmas A Partridge in a Pear Tree On the second day of Xmas On the third day of Xmas On the fourth day of Xmas Lyrics On the fifth day of Xmas On the sixth day of Xmas On the seventh day of Xmas On the eighth day of Xmas 2
On the ninth day of Xmas On the tenth day of Xmas On the eleventh day of Xmas 11 Pipers Piping and a Partridge in a Pear 6 Geese Tree a Laying On the twelfth day of Xmas 12 Drummers Drumming 11 Pipers Piping 3
題目 請設計一個 C 程式, 列印出聖誕歌謠 12 Days of Christmas 完整的 12 段歌詞 請運用 for 迴圈 switch 敘述 及字串陣列設計 ( 上面 switch 的運用可以用迴圈取代 ) 請注意一定要避免重複的敘述 請小心歌詞中 and 連接詞以及冠詞 A 的大小寫 範例輸出 On the first day of Christmas A Partridge in a Pear Tree On the second day of Christmas On the third day of Christmas On the twelfth day of Christmas 12 Drummers Drumming 11 Pipers Piping 4
Bizarre Obfuscated Non example main(t,_,a)char* a;{ return! 0<t? t<3?main( 79, 13,a+main( 87,1 _,main( 86, 0, a+1)+a)):1,t<_?main(t+1, _, a ):3,main( 94, 27+t, a)&&t == 2?_<13?main(2, _+1, "%s %d %d\n"):9:16:t<0?t< 72?main(_, t,"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+, /+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+k w'k:'+}e#';dq#'l q#'+d'k#!/+k#;q#'r}ekk#}w'r}ekk{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'k {rw' ik{;[{nl]'/w#q#n'wk nw' iwk{kk{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl' {}rw]'/+,""}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/"):t< 50?_==*a?putchar(31[a]):main( 65,_,a+1):main((*a == '/') + t, _, a + 1):0<t?main(2, 2, "%s"):*a=='/' main(0,main( 61,*a, "!ek;dc i@bk'(q) [w]*%n+r3#l,{}:\nuwloca O;m.vpbks,fxntdCeghiry"),a+1); } 印出的歌詞裡有兩個地方有錯, 好想把它改過來, 可是 5
設計方法與分析 1. 由範例輸出可以看到輸出有 12 個段落, 這一定需要一個迴圈, 因為在進入迴圈之前就知道需要做 12 次, 所以用一個 for 迴圈是很合適的, 每一次迴圈內列印出 1 個段落 On xxx my and a Partridge 其中藍色部份是每次迴圈執行時都不同的 On the first day of Christmas A Partridge in a Pear Tree On the twelfth day of Christmas 12 Drummers Drumming 11 Pipers Piping 2. xxx 代表 first, second, third, fourth,, twelfth 這些字串, 如果 for 迴圈的控制變數 i 由 0 遞增到 11 的話, 需要設計一個字元的指標陣列, 例如 const char *const ordinal[] = {"first", }; 然後在迴圈內運用 printf("on %s ", ordinal[i]); 來列印 6
3. 迴圈第一次執行時印一列, 第二次印兩列,, 第十二次印十二列, 這樣的表現看起來需要第二層的迴圈, 執行的次數由第一層迴圈的控制變數去算出來, 例如 : for (i=0; i<12; i++) // 印出 12 段歌詞 { } 或是 for (j=i; j>=0; j--) 印出步驟 2 的結果印出前 i+1 列 for (j=11 i; j<=11; j++) const char *sentences[] = {"a Partridge ",, 印出最後 i+1 列 "12 Drummers "}; ( 可以像步驟 2 中一樣設計一個字元的指標陣列 const char *sentences[] = {"12 Drummers ",,"a Partridge "}; 4. 和步驟 3 等效的另一種寫法是用 switch 敘述, 你可以想一下 測試一下下面這段程式的輸出 switch (paragraph) { case 12: printf("12 "); case 11: printf("11 "); } paragraph 為 12 時是不是印出兩列? paragraph 為 11 時是不是只印出一列? 嘗試修改為我們需要的功能 7
5. 步驟 3 或是步驟 4 中我們沒有特別去處理第 1 段歌詞中是 A Partridge in a Pear Tree, 但是在第 2 段到第 12 段歌詞中是 的問題, 該怎樣不重複程式碼又能夠只修改這一點點呢? a. 第一種方法是 if (i==0) // 第 1 段 printf("a Partridge in a Pear Tree\n"); else printf("\n"); 當然這樣還是有一部份重複 b. 簡單的改一下 if (i==0) // 第 1 段 printf("a"); else printf("and a"); printf(" Partridge in a Pear Tree\n"); 反正相同的部份就不要重複就是了 8
5. c. 程式可以再改一點點, 多運用變數來改變程式的表現, char article = 'A'; if (i>0) article = 'a'; printf("%c Partridge in a Pear Tree\n", article); 至於 and 就合併到 \nand 字串的後面, 反正印出 \n 時下一列一定是 and 開頭 6. 在這個程式的設計過程裡, 你也許發現我們某種層面上盡量在避開運用 if 或是 switch 把程式裡面各種選項展開來 ( 步驟 4, 步驟 5a, 和步驟 5b), 這樣子做當然讓程式可以很快地達成我們要求的表現, 但是你可以想像如果今天不是 12 段歌詞, 而是 120 段, 那麼用 switch 就頭痛了, 像這樣的考量其實在設計很多程式時都會不斷出現, 基本上不管是 12, 120, 或是 2, 其實寫程式的人都會像這樣有兩種考量, 有時你也許接到程式的需求時是 10, 可是後來付錢的人又改成 100, 你還是需要去滿足顧客的需求的, 有錢就任性囉! 9