精華區beta NTUE-CS102 關於我們 聯絡資訊
..... 不抄不問自己翻課本做得出來的應該沒幾個(汗) 這裡先重新說明函式用法,在解題前一樣會留個防雷頁的 是說這次解題應該是可以抄的境界(?),雖然沒什麼人看,大概也不太需要在意(?) int f () { ... } "宣告"一個函式大致可以分成這四個部份 注意是宣告,先想成像宣告變數一樣去做跟使用就好 int表示回傳值的型態,大多是只有用int float bool void而已,其他大多先不在乎 f是函式名稱,相關限制與注意事項與宣告變數名稱時的限制相同 ()是擺參數的地方,用來把特定數值/位址傳達給函式內使用 詳細用法會在接下來一小段簡單的示範code說明 這段code是 輸入兩個數值,將其相乘後的結果印出來 左邊是使用函式的方法;右邊是不使用的對照組 #include<iosream> #include<iosream> using namespace std; using namespace std; int multiple(int x ,int y) int main() { { return x*y; int x,y; } cin >>x >>y; cout <<x*y; int main() } { int x,y; cin >> x >>y; cout <<multiple(x,y); } 像這樣就是個簡單的對照,當然通常不幹這種小事就把code變長 這裡注意兩件事情 1.左邊使用函式的這邊,顏色不同的x.y表示的是"不同"的變數,雖然同樣稱作x.y 這個在寫code時沒做出明確分別很容易搞混,也是常見的問題 2.multiple(x,y) 在main()內,等同於程式碼中 x*y 的"數值" 因此,可以有 int i = multiple(x,y) 這樣的用法存在 再來,解題前先說明大概有幾種作法,供完全沒概念的人一點方向 1.將判斷擺在函式內,回傳xAyB的x.y ;這大概是老師最希望看到的...? 2.把整段while內的判斷擺在函式內,包含印出xAyB的行為 ;這是大部分人選的事情 3.全域變數 ;元品那邊好像大多都用這個方法? 4.指標 ; 現階段沒事幹不要做這種事情。 5.假主函式 ; 這個不知道算不算不合題意(逃遠) 大原則上,作法內容都差不多,只是數值從主函式到函式的方法差別而已 以下開始進入防雷 -- 請記得,如果你現在什麼都還沒有寫請稍微思考再往下看 如果你有寫完覺得有問題,請往下找到你自己的寫法看看有些什麼樣的問題可以參考 不然期末考應該很難過的。 -- 開頭,先擺上一個不使用函式的範例code做為基本對照組 如果需要抄這個code當作業,我會建議不如先回頭獨立作完過去的作業 或是另外向翔風ㄉㄉ要一點基本題目來寫,不然明年學弟妹可能會跟你一起修了 a系列變數是輸入的答案,in系列是猜的數字,a.b就是正確與錯誤位置的數目了 #include<iosream> using namespace std; int main() { sdgasgsdafasdfasdfasdfasdfasdfasdfasf sdint a1,a2,a3,in1,in2,in3,a,b; ascin >>a1 >>a2 >>a3; aswhile (1) asdasdasdasdasdasdasdasgfsagawrerehwe ty{ qwarwgtawergwaeftawef a=b=0; asdasdgaehsretyulkertyju[4k cin >>in1 >>in2 >>in3; if (a1==in1) a++; if (a1==in2 || a1==in3) b++; qweqweqwewasdgadefh ererif (a2==in2) a++; if (a1==in1 || a1==in3) b++;wqwearykenhp;ln45 if (a3==in3) a++; if (a1==in1 || a1==in2) b++;ergypwekhmrg['w cout <<a <<'A' <<b <<'B'; if (a==3) break; } } -- 1.將判斷擺在函式內,回傳xAyB的x.y 2.把整段while內的判斷擺在函式內,包含印出xAyB的行為 其實1.跟2.差不多,都還在目前交授範圍內,只是一兩步不同的差異 大體上都是while內大部分東西放到函式內,以下函式通用test表示判斷、測試部份 只是擺多少的差別,比如說 1.只把A.B判斷後的xAyB中x.y傳回,然後在主函式印出來 2.連同輸出都擺在裡面,所以連return都不太用 先舉出兩者在函式中代表的範圍,共通部份大致是以下這段 if (a1==in1) a++; if (a1==in2 || a1==in3) b++; qweqweqwewasdgadefh ererif (a2==in2) a++; if (a2==in1 || a2==in3) b++;wqwearykenhp;ln45 if (a3==in3) a++; if (a3==in1 || a3==in2) b++;ergypwekhmrg['w 依照使用者習慣決定要不要連同cin >>in1 >>in2 >>in3;一起置入 為了與大部分人思維相同,以不擺進為主..不然函式參數太長很容易亂掉 同時,避免讓人搞混,這裡參數名稱也會與主函式宣告的變數拼字不太一樣 下一頁是函式與其宣告內容 -- int testA(int aa1,int aa2,int aa3,int iin1 ,int iin2,int iin3) { int aa=0; if (aa1==iin1) aa++; er if (aa2==iin2) aa++;wqwearykenhp;ln45 if (aa3==iin3) aa++;ergypwekhmrg['w return aa; } int testB(int aa1,int aa2,int aa3,int iin1 ,int iin2,int iin3) { int bb=0; if (aa1==iin2 || aa1==iin3) bb++; erif (aa2==iin1 || aa2==iin3) bb++; if (aa3==iin1 || aa3==iin2) bb++;ergypwekhmrg['w return bb; } 會這樣做只是我想不到怎樣可以用現在教的範圍去做到"在一個函式輸入並回傳兩個值" 所以就是在輸入猜測數值後,才判斷並輸出,下頁擺上main的內容,再正式說明 -- int main() { int a1,a2,a3,in1,in2,in3; cin >>a1 >>a2 >>a3; while (1) { cin >>in1 >>in2 >>in3; cout <<testA(a1,a2,a3,in1,in2,in3)<<'A'<<testB(a1,a2,a3,in1,in2,in3) <<'B'; if (testA(a1,a2,a3,in1,in2,in3)==3) break; } 嗯,我也覺得那個參數引用的亂噁心的-____- 這邊我想提一下,可以的話,用函式就善加練習參數使用與回傳的應用比較好 不然哪天會像我一樣改個code快死在地上(倒) 嗯..這邊就先拿testA(a1,a2,a3,in1,in2,in3)說明就好 前三個參數,是要把正確答案傳達進函式使用,後三個是要把猜測的數傳進去使用 所以說aa1會相等成a1的數值,其餘比照處理 然後我們用跟原本寫法一樣的判斷去決定有幾個在正確的位置上,並且將其回傳給主函式用 -- 像是以下這一小段: cout <<testA(a1,a2,a3,in1,in2,in3) <<'A' 就是這樣的用法,還記得前面說有return的話可以把整串認知是return的值嗎? 假設現在是完全正確的答案,return的aa就會是3 這一小段就可以看作是 cout <<3 <<'A' 這樣的內容,雖然其實它原本長的很噁心。 往下看主函式的內容 if (testA(a1,a2,a3,in1,in2,in3)==3) break; 這段的原因是我在前面讓他重複執行的地方是採用無限迴圈 所以在這裡讓3A發生時會離開回圏,自然的結束這個程式 這段要不要存在或內容擺什麼端看怎麼寫迴圈判斷式... 比如你可以把這個判斷就放在while之中...應該是不會發生一開始預設值就相等的狀況 -- 再來是看到蠻多的函式用法,這種主要問題就只是如何離開迴圏 內容很直接,這邊稍微美化一點...今天大多使用參數都使用了很多無意義的宣告 void test(int aa1,int aa2,int aa3) { int in1,in2,in3,a=0,b=0; cin >>in1 >>in2 >>in3; if (aa1==in1) a++; if (aa1==in2 || aa1==in3) b++; if (aa2==in2) a++; if (aa1==in1 || aa1==in3) b++; if (aa3==in3) a++; if (aa1==in1 || aa1==in2) b++; cout <<a <<'A' <<b <<'B'; } int main() { int a1,a2,a3; cin >>a1 >>a2 >>a3; while (1) test(a1,a2,a3); } -- 這就是很單純把while內原有的東西都塞在裡頭的範例 簡單有效,只是這個迴圈終止不了而已 這邊大概是有三種作法... 1.把void改成會在3A時回傳一個特定值,在while裏判斷回傳的是不是特定值。 是的話break out int test(int aa1,int aa2,int aa3) { int in1,in2,in3,a=0,b=0; cin >>in1 >>in2 >>in3; if (aa1==in1) a++; if (aa1==in2 || aa1==in3) b++; if (aa2==in2) a++; if (aa1==in1 || aa1==in3) b++; if (aa3==in3) a++; if (aa1==in1 || aa1==in2) b++; cout <<a <<'A' <<b <<'B'; if (a==3) return 102; else return 0; } -- (中略) while (1){ int d=test(a1,a2,a3) if (d==102) break; } 像這樣利用回傳值去做要不要跳出函式的判斷就可以了 或是說,也能這樣用函式,函式內的事情還是會執行,也同樣會回傳值而不影響 while (1){ if (test(a1,a2,a3)==102) break; } 這個會延伸造成那個在翔風ㄉㄉ的文章裡頭提的今天另外一個問題 判斷式做一次,敘述又做一次這樣的狀況發生 更為乾脆、簡化的作法是3A回傳0或改成bool傳false,放在while判斷式裡頭 while (test(a1,a2,a3)) ; 不過呢,新手這種事情都少幹,因為只會把程式搞的更複雜到自己搞不懂 -- 第三種作法是blue不知不覺用的作法...之後應該會提到的遞迴 這裡我要提句名言"遞迴只應天上有,凡人應當用迴圈" 因為容易在思緒上亂掉,大多時候迴圈還是比較容易的 int test(int aa1,int aa2,int aa3) { int in1,in2,in3,a=0,b=0; cin >>in1 >>in2 >>in3; if (aa1==in1) a++; if (aa1==in2 || aa1==in3) b++; if (aa2==in2) a++; if (aa1==in1 || aa1==in3) b++; if (aa3==in3) a++; if (aa1==in1 || aa1==in2) b++; cout <<a <<'A' <<b <<'B'; if (a!=3) return test(aa1,aa2,aa3); else return 0; } int main() { int a1,a2,a3; cin >>a1 >>a2 >>a3; test(a1,a2,a3); } -- 看起來很複雜,其實遞迴是種自體呼叫的方法 也就是說在函式內使用自己,此部分名範例就費波納契數列、遞迴等 像是這樣寫的話,當a不是3的時候,就會再一次進入test裏頭 重新輸入猜測數字、判斷 當猜到3A時,就會回傳0,然後這個0會一路往上傳到第一次用的test() 隨即結束程式這樣 嘛...沒事不要這樣用(遠目) -- 再來是第三種,全域變數 以下可以都當茶餘飯後看看就好,不然一個比一個噁心.... 好吧,第五項可以看看(茶) 之前我們知道,每個變數只會在 宣告時的那組{ }之間可以使用 : 就是為什麼main跟函式間的x.y不能共用這樣的感覺 那如果說,把整個.cpp檔想成有個範圍很大的{ }的話 那麼連main()都會在這個 { }之中 也就是說,我們在跟main同樣的位置上宣告變數,那這個變數是不是就能用在很多函式中? 這就是全域變數,在所有的區域中都能使用的變數。 與之對比就是區域變數,只能在特定範圍使用的變數。 用這個方法,就能避免掉不會使用函數中的參數的問題 在初學來說是把雙面刃這樣...它可以讓你更容易完成作業,相反的也減少練習參數的機會 再來,一樣是code 只是這個更好抄-_______- -- #include<iosream> using namespace std; int a1,a2,a3,in1,in2,in3,a,b; bool test() { if (a1==in1) a++; if (a1==in2 || a1==in3) b++; if (a2==in2) a++; if (a1==in1 || a1==in3) b++; if (a3==in3) a++; if (a1==in1 || a1==in2) b++; cout <<a <<'A' <<b <<'B'; if (a==3) return 0; else return 1; } int main() { cin >>a1 >>a2 >>a3; while (test()) ; } 大概就是這樣,因為變成全域....所以寫起來感覺就跟都在main裏宣告一樣 也不用麻煩的去設函數的參數什麼的 -- 再來是我自己用的指標... 我只是想練習一下而已(拖走 老師今天有提過,從函式傳值的方法 也就是那個pass by value;pass by address什麼的(?) 指標就是後者這種,將變數存在的"位址"傳給函式中 讓改變數值是改變這個"位址"的數值 因此便能利用函式去改變主程式中的變數 其中pass by address分成 取值與給值..這裡範例用取值 在於這次的作業裡,大體上就是像模擬全域變數而已 只是利用指標能比較節省程式執行中記憶體 (吧?) 因為不到必要是不會去宣告一個變數擺在那裡不使用 然後一般寫程式應用也算廣,只是還沒教到的東西...就看看就好 可以不用急著搞懂怎麼用,有興趣先翻課本吧(跑遠) -- #include<iosream> using namespace std; void test(int *a1,int *a2,int *a3,int *in1,int *in2,int *a3,int *a,int *b) { if (*a1==*in1) *a+=1; if (*a1==*in2 || *a1==*in3) *b+=1; if (*a2==*in2) *a+=1; if (*a1==*in1 || *a1==*in3) *b+=1; if (*a3==*in3) *a+=1; if (*a1==*in1 || *a1==*in2) *b+=1; } int main() { int a1,a2,a3,in1,in2,in3,a,b; cin >>a1 >>a2 >>a3; while (cin >>in1 >>in2 >>in3) { a=b=0; test(a1,a2,a3,in1,in2,in3,a,b); cout <<a <<'A' <<b <<'B'; if (a==3) break; } } -- 看完很多莫名奇妙的東西,最後一個就稍微輕鬆一點,算是走在邊緣上的作法 我們把所有東西都寫在函式,然後讓主函式呼叫,這樣就是都不在主函式了 #include<iosream> using namespace std; void fake_main() { sdgasgsdafasdfasdfasdfasdfasdfasdfasf sdint a1,a2,a3,in1,in2,in3,a,b; ascin >>a1 >>a2 >>a3; aswhile (1) { qwarwgtawergwaeftawef a=b=0; asdasdgaehsretyulkertyju[4k cin >>in1 >>in2 >>in3; if (a1==in1) a++; if (a1==in2 || a1==in3) b++; qweqweqwewasdgadefh ererif (a2==in2) a++; if (a1==in1 || a1==in3) b++;wqwearykenhp;ln45 if (a3==in3) a++; if (a1==in1 || a1==in2) b++;ergypwekhmrg['w cout <<a <<'A' <<b <<'B'; if (a==3) break; } } int main(){ fake_main(); } -- 嗯,最後一個示範code要小小改了才能交,不然是不合題意的(跑) 希望各位是不要用抄的這樣(遠目) 很多因為都沒有拿去編譯過,所以小疏忽什麼的很容易出現 不過寫程式出錯可以改,所以就不要太拘泥要一次對了(逃跑 -- 本命 ○楽園の巫女  博麗 霊夢 職業:博麗神社の巫女さん  Hakurei Reimu   能力:主に空を飛ぶ程度の能力 @東方project系列 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 115.43.39.145
pk873:有較勁的意味?? 12/09 22:59
game0416:強者的宿命就是..... (拖走 12/09 23:01
CaptainWill:威... 12/09 23:03
Arashinoon:為什麼知道我是用全域變數 囧 太強大了 12/09 23:12
game0416:八卦來的消息,加上你那附近大部分也這樣用啊 XD 12/09 23:14
CaptainWill:你們都不說中文... 12/09 23:15
CaptainWill:鳳狼不用怕被說自肥,M了這篇吧 12/09 23:15
Arashinoon:話說 最後一個方法應該不能用ˊˋ 最後老師說不能在 12/09 23:22
Arashinoon:函數中用while 12/09 23:22
game0416:那就遞迴....(拖走 12/09 23:23
gcobc12632:不能在函數中用while?那在while裡面塞函數OK吧? 12/09 23:43
j2612280:OK 12/09 23:49
j2612280:只是要記得在while的()放函數的話函數也是會跑的唷! 12/09 23:50
gcobc12632:那還好沒寫錯…只不過好像多寫了很多東西(?) 12/10 00:00
j2612280:可能吧...慢慢來就會改善滴~ 12/10 00:03
ip3311:第163行最後面的B打錯了歐 = = 無意間看到XD 12/11 00:37
※ 編輯: game0416 來自: 115.43.39.145 (12/11 00:39)