作者game0416 (鳳狼)
看板NTUE-CS102
標題Re: [閒聊] 程設作業
時間Wed Dec 9 22:58:44 2009
.....
不抄不問自己翻課本做得出來的應該沒幾個(汗)
這裡先重新說明函式用法,在解題前一樣會留個防雷頁的
是說這次解題應該是可以抄的境界(?),雖然沒什麼人看,大概也不太需要在意(?)
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)