Syllabus - 0
內容 | 快速連結 |
---|---|
前導 | Section 1 |
goto 最基礎的重複結構 | Section 2 |
Ex I - I - 可控隨機數 (介紹) | Section 3 |
Ex I - II - 可控隨機數 (解析) | Section 4 |
Ex II - 考拉茲猜想 3n+1問題 | Section 5 |
do-while 結合 goto + if 的重複結構 | Section 6 |
Ex III - I - 什麼是二進位? | Section 7 |
Ex III - II - 進位制轉換 - I | Section 8 |
To do or not to do? | Section 9 |
while 事先檢查的重複結構 | Section 10 |
Ex IV - 質數判斷 | Section 11 |
for 最重要的重複結構 | Section 12 |
break & continue 流程控制 | Section 13 |
Loop p.s. 重複結構注意事項 | Section 14 |
內容 | 快速連結 |
---|---|
Loop sp. 盤點那些奇怪的迴圈 | Section 15 |
Ex V - APCS觀念題練習 | Section 16 |
Ex VI - 第二大數字判斷 | Section 17 |
Review 複習所有重複結構 | Section 18 |
Nested loop 巢狀重複結構 - 你今晚的惡夢 | Section 19 |
Double for 最經典的雙重迴圈 | Section 20 |
Ex VII - 指數表 | Section 21 |
Double break !! 跳出雙重迴圈 | Section 22 |
Ex VIII - I - 孤單的機器人 | Section 23 |
Ex VIII - II - 孤單的機器人 (補充) | Section 24 |
Ex IX - 幾何解析小幫手 | Section 25 |
Ex X - 三角形 | Section 26 |
結語 | Section 27 |
重要章節
主要章節
Before Before Class - 1
Esc後大概長這樣,你可以先Esc在上下左右選你要看哪頁投影片。
Before Before Class - 0
Before Class - 0
Before Class - 1
剛剛影片的流程圖
Before Class - 2
一個流程圖告訴你為什麼推ayame
goto - 0
流程圖
#include <iostream>
using namespace std;
int main() {
int x;
// 標記點 (label)
start:
cin >> x;
cout << x+1 << endl;
goto start;
return 0;
}
[標誌名稱]:
goto [標誌名稱];
goto - 1
一個比之前更完整的猜數字流程圖
3 mins
int x = 7, guess;
cin >> guess;
if (guess > x) {
cout << "Smaller.\n";
} else if (guess == x) {
cout << "Atari!\n";
} else {
cout << "Larger.\n";
}
原本猜數字的code
goto - 2
一個比之前更完整的猜數字流程圖
3 mins
#include <iostream>
using namespace std;
int main() {
int x = 7, guess;
start:
cin >> guess;
if (guess > x) {
cout << "Smaller.\n";
goto start;
} else if (guess == x) {
cout << "Atari!\n";
} else {
cout << "Larger.\n";
goto start;
}
return 0;
}
猜數字 + goto 的code
goto - 2
5 mins
#include <iostream>
using namespace std;
int main() {
/* you can NOT add some code here. */
start:
/* you can add some code here. */
cout << "PEKOPEKO!" << endl;
goto start;
/* you can add some code here. */
return 0;
}
start:
if (false) {
cout << "PEKOPEKO!" << endl;
goto start;
}
start:
goto end;
cout << "PEKOPEKO!" << endl;
goto start;
end:;
聰明的你可能會用if。
腦子有洞的你可能會用goto。
start:
/*
cout << "PEKOPEKO!" << endl;
goto start;
*/
你怎麼就沒想過註解呢?
start:
return 0;
cout << "PEKOPEKO!" << endl;
goto start;
性格灑脫的你可能會自行了斷。
goto - 3
一種資安的競賽類型 - 奪旗比賽 (Capture the Flag)
Exercise I - I - Controllable RNG 可控隨機數 - 0
隨機數生成器是通過一些算法、物理訊號、環境噪音等來產生看起來似乎沒有關聯性的 數列的方法或裝置。丟硬幣、丟骰子、洗牌就是生活上常見的隨機數產生方式。
大部分計算機上的偽隨機數,並不是真正的隨機數,只是重複的周期比較大的數列,是按一定的算法和種子值生成的。
Random Number Generator
- by 維基百科
梅森旋轉算法
線性反饋移位暫存器
Exercise I - I - Controllable RNG 可控隨機數 - 1
wiki的LFSR範例圖
unsigned LFSR() {
static unsigned short lfsr = 44257;
unsigned bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5) ) & 1;
return lfsr = (lfsr >> 1) | (bit << 15);
}
線性反饋移位暫存器
44257 -> 22128 -> 43832 -> 21916 -> 10958
-> 5479 -> 35507 -> 17753 -> 8876 -> ...
Exercise I - I - Controllable RNG 可控隨機數 - 2
44257 -> 22128 -> 43832 -> 21916 -> 10958 -> 5479 -> 35507 -> 17753 -> 8876 -> ...
int num = LFSR() % (n + 1);
int num = LFSR() % (b - a + 1) + a;
Exercise I - I - Controllable RNG 可控隨機數 - 3
線性反饋移位暫存器
int num = LFSR() % (n + 1);
int num = LFSR() % (b - a + 1) + a;
5 mins
#include <iostream>
using namespace std;
unsigned LFSR() {
static unsigned short lfsr = 44257;
unsigned bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5) ) & 1;
return lfsr = (lfsr >> 1) | (bit << 15);
}
int main () {
int n = 10, x;
x = LFSR() % (n+1);
cout << x << " ";
x = LFSR() % (n+1);
cout << x << " ";
x = LFSR() % (n+1);
cout << x << " ";
x = LFSR() % (n+1);
cout << x << " ";
x = LFSR() % (n+1);
cout << x << " ";
// ...
}
Exercise I - I - Controllable RNG 可控隨機數 - 4
線性反饋移位暫存器
Exercise I - I - Controllable RNG 可控隨機數 - 5
44257 -> 22128 -> 43832 -> 21916 -> 10958 -> 5479 -> 35507 -> 17753 -> 8876 -> ...
程式練習題
接下來有一題請你用
程式實做重複結構的題目。
15 mins
Exercise I - II - Controllable RNG 可控隨機數 - 0
unsigned LFSR() {
static unsigned short lfsr = 44257;
unsigned bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5) ) & 1;
return lfsr = (lfsr >> 1) | (bit << 15);
}
這題的流程圖
15 mins
#include <iostream>
using namespace std;
unsigned LFSR();
int main() {
int n, k;
cin >> n >> k;
int cnt = 0;
start:
int x = LFSR() % (n+1);
if (x % k == 0)
goto start;
cout << x << endl;
cnt ++;
if (cnt != 5)
goto start;
return 0;
}
unsigned LFSR() {
static unsigned short lfsr = 44257;
unsigned bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5) ) & 1;
return lfsr = (lfsr >> 1) | (bit << 15);
}
Exercise I - II - Controllable RNG 可控隨機數 - 1
這題的流程圖
程式練習題
接下來有一題請你用
程式實做重複結構的題目。
Exercise I - Collatz Conjecture 考拉茲猜想 - 0
20 mins
wiki對考拉茲猜想的描述。
1 -> end
18 -> 9 -> 28 -> 14 -> 7 -> 22 -> 11
-> 34 -> 17 -> 52 -> 26 -> 13 -> 40
-> 20 -> 10 -> 5 -> 16 -> 8 -> 4
-> 2 -> 1 -> end
Exercise I - Collatz Conjecture 考拉茲猜想 - 1
20 mins
cin >> n;
cout << n << " -> ";
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
cout << n << " -> ";
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
cout << n << " -> ";
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
直接寫出來就是長這樣。
cin >> n;
start:
cout << n << " -> ";
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
goto start;
用goto循環
Exercise I - Collatz Conjecture 考拉茲猜想 - 2
20 mins
cin >> n;
start:
cout << n << " -> ";
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
goto start;
用goto循環
cin >> n;
start:
cout << n << " -> ";
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
if (n != 1)
goto start;
cout << "1 -> end" << endl;
如果n還沒到1才要回去。
Exercise I - Collatz Conjecture 考拉茲猜想 - 3
20 mins
cin >> n;
start:
cout << n << " -> ";
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
if (n != 1)
goto start;
cout << "1 -> end" << endl;
如果n還沒到1才要回去。
一開始n是1會錯QQ
cin >> n;
if (n != 1) {
start:
cout << n << " -> ";
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
if (n != 1)
goto start;
}
cout << "1 -> end" << endl;
AC!
Exercise I - Collatz Conjecture 考拉茲猜想 - 4
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
if (n != 1) {
start:
cout << n << " -> ";
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
if (n != 1)
goto start;
}
cout << "1 -> end" << endl;
return 0;
}
20 mins
do-while - 0
do-while流程圖
#include <iostream>
int main() {
int x;
do {
std::cin >> x;
} while (x != 0);
return 0;
}
do {
// 做事情
} while (true 或 false);
do-while - 1
do-while流程圖
do {
// 做事情
} while (true 或 false);
start:
// 做事情
if (true 或 false)
goto start;
do-while - 2
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
if (n != 1) {
start:
cout << n << " -> ";
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
if (n != 1)
goto start;
}
cout << "1 -> end" << endl;
return 0;
}
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
if (n != 1) {
do {
cout << n << " -> ";
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
} while(n != 1);
}
cout << "1 -> end" << endl;
return 0;
}
goto + if (剛剛的code)
do-while (改寫的code)
3 mins
do-while - 3
/*[*/#include<stdio.h>//
#include<stdlib.h>//]++++[->++[->+>++++<<]<][(c)2013]
#ifndef e//[o
#include<string.h>//]![misaka.c,size=3808,crc=d0ec3b36][
#define e 0x1//
typedef struct{int d,b,o,P;char*q,*p;}f;int p,q,d,b,_=0//|
#include __FILE__//]>>>[->+>++<<]<[-<<+>>>++<]>>+MISAKA*IMOUTO
#undef e//[->[-<<+<+<+>>>>]<<<<<++[->>+>>>+<<<<<]>+>+++>+++[>]]b
#define e(c)/**/if((_!=__LINE__?(_=__LINE__):0)){c;}//[20002,+[-.+]
,O,i=0,Q=sizeof(f);static f*P;static FILE*t;static const char*o[]={//
"\n\40\"8oCan\40not\40open %s\n\0aaFbfeccdeaEbgecbbcda6bcedd#e(bbed$bbd",
"a6bgcdbbccd#ead$c%bcdea7bccde*b$eebbdda9bsdbeccdbbecdcbbcceed#eaa&bae$cbe",
"e&cbdd$eldbdeedbbdede)bdcdea&bbde1bedbbcc&b#ccdee&bdcdea'bbcd)e'bad(bae&bccd",
"e&bbda1bdcdee$bbce#b$c&bdedcd%ecdca4bhcdeebbcd#e$b#ecdcc$bccda7bbcc#e#d%c*bbda",
">bad/bbda"};static int S(){return(o[p][q]);}static/**/int/**/Z=0 ;void/**/z(int//
l){if(/**/Z-l){Z=l;q++;if(p<b*5&&!S()){p+=b;q=0;}}}int main(int I, /**/char**l){//
d=sizeof(f*);if(1<(O=_)){b=((sizeof(o)/sizeof(char*))-1)/4;q=22; p= 0;while(p<b*5){
/*<*/if(Z-1){d=S()>96;i=S()-(d?96:32) ;q++;if(p<b*5&&!S()){p+=b; q= 0;}Z=1;}/*[[*/
while(i){_=o[0][S()-97];I=_-10?b:1; for( ;I--;)putchar(_ );if (! --i||d)z(~i );}
if(p==b*5&&O){p-=b;O--;}}return 0U; }if(! (P=( f*)calloc /*]*/ (Q ,I)))return 1;
{;}for(_=p=1;p<I;p++){e(q=1);while (q< p&& strcmp( l[p ] ,l[(q)]))++ q;
t=stdin;if(q<p){(void)memcpy/* " */ (&P [p],&P [q ] ,Q);continue ;}
if(strcmp(l[p],"-")){t=fopen(l [ p] ,"rb" ) ;if(!t ){{;} ;
printf(05+*o,l[p ]);return+1; {;} }}_=b= 1<<16 ;
*&O=5;do{if(!(P[p].q=realloc (P[p].q,(P[p].P += b)+1))){return 01;}O &=72 /
6/*][*/;P[p].o+=d=fread(P[p] .q +P[ p ]. o, 1,b,t) ;}//
while(d==b) ;P [p].q[ P[ p] .o ]= 012;d =0;
e(fclose(t ) );P [p] .p =P[ p] .q;if (O)
{for(;d<P[ p] .o ;d= q+ 1) {q= d;
while(q<P[ p].o&&P[ p].q[q]- 10 ){
q++;}b=q-d; _=P [p]. d ;
if(b>_){/*]b */
P[p].d=b;}{; }
#undef/*pqdz'.*/ e// ;
#define/*s8qdb]*/e/**/0 //
//<<.<<.----.>.<<.>++.++< .[>]
/*P[*/P[p].b++;continue;}}}t= stdout;
for (p=1;p<I;p++){/**/if(P[p].b>i ){i=P[p].b;}}
if (O){for(p=0;p<i;p++){q=0;/*[*/while(I >++q){_=P[q].p-P[q ].q;
b= 0;if(_<P[q ].o){while(012-*P[q].p) {putchar(*(P[q].p++));b++;}P[q]. p++;
} ;while (P[ q].d>b++)putchar(040);} putchar(10);}return 0;}p =1;
for(; p<I ;p++)fwrite(P[p] .q,P[ p].o,1,t);return 0 ;}//
#/*] ]<. [-]<[-]<[- ]<[ -]< [- ]<;*/elif e //b
|(1 << ( __LINE__ /* >> `*//45)) | 01U
# /* */ endif //
這份code可以讓多個文件並排輸出。
你可以複製上面的這份code編譯看看(?)
(要把文件存成.c 不能是.cpp)
跳來跳去好難看啊....
Exercise III - I - Dec2bin 進位置轉換 - 0
15 mins
Exercise III - I - Dec2bin 進位置轉換 - 1
1
2
3
4
...
9
10
5
6
1
10
11
100
101
110
Exercise III - I - Dec2bin 進位置轉換 - 2
1
2
3
4
5
6
1
10
11
100
101
110
十進位制
二進位制
看的出來
規律嗎?
Exercise III - I - Dec2bin 進位置轉換 - 3
1
2
3
4
5
6
001
010
011
100
101
110
Exercise III - I - Dec2bin 進位置轉換 - 4
一個將13轉成1101的過程
程式練習題
接下來有一題請你用
程式實做重複結構的題目。
15 mins
Exercise III - II - Dec2bin 進位置轉換 - 0
#include <iostream>
using namespace std;
int main () {
long long x;
cin >> x;
do {
cout << x % 2;
x /= 2;
} while (x != 0);
cout << endl;
return 0;
}
Exercise III - II - Dec2bin 進位置轉換 - 1
15 mins
To do or not to do ? - 0
再繼續往下之前,我們來複習一下吧!
goto:跳轉到你曾經設下的標記點。
do{}while();:做{},判斷()決定要不要跳轉到一開始。
do-while流程圖
goto流程圖
// 設下標記點
labelA:
do_something();
// 跳到標記點
goto labelA;
// =======================
do {
do_something();
// 如果true會跳到do{那行
} while (true 或 false);
To do or not to do ? - 1
再繼續往下之前,我們來複習一下吧!
循環的猜數字 (goto)
猜數字後判斷有沒有猜中,沒有回去再猜一次。
可控隨機數 (看著流程圖用goto實作)
生亂數後判斷有沒有違反條件或還沒生五次,以此決定要不要回去重生亂數。
考拉茲猜想 (goto -> do-while)
判斷已經是不是到1了,還沒就/2或*3+1並回去重做一次。
進位制轉換 (do-while)
輸出第一位數後 /2,判斷是否到0了,沒有就回去重做一次。
做動作
做判斷
跳code
To do or not to do ? - 2
有些情況,是需要先做事再判斷要不要跳回去的。
例如進位制轉換,亂數生成。
但有些情況是需要先判斷再做事,做完再重新判斷決定要不要跳回去。
考拉茲猜想要先判斷是不是1,做完之後還要重新判斷是不是1,好麻煩。
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
if (n != 1) {
do {
cout << n << " -> ";
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
} while(n != 1);
}
cout << "1 -> end" << endl;
return 0;
}
用do-while實作考拉茲猜想。
做動作
做判斷
跳code
while - 0
while流程圖
// while 一開始,如果判斷為F則跳到}後
while (T / F) {
// 做事情
} // 結束會回到while(){重新判斷
do-while流程圖
while - 1
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
if (n != 1) {
do {
cout << n << " -> ";
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
} while(n != 1);
}
cout << "1 -> end" << endl;
return 0;
}
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
while (n != 1) {
cout << n << " -> ";
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
}
cout << "1 -> end" << endl;
return 0;
}
考拉茲猜想用whlie實作的code。
while - 2
1+2+3+4+5+6+....+n為止
int sum = 0;
sum += 1;
sum += 2;
sum += 3;
sum += 4;
.... 加到n為止。
你可能會想這樣想
但這個東西不是重複結構啊?
code不一樣不能重複QQ
int sum = 0, i = 1;
sum += i;
i += 1;
sum += i;
i += 1;
sum += i;
i += 1;
.... 加到i=n為止。
耶?怎麼突然可以了?
while - 2
int sum = 0, i = 1;
do {
sum += i;
i += 1;
} while (i != n+1);
int sum = 0, i = 1;
while (i != n+1) {
sum += i;
i += 1;
}
int sum = 0, i = 1;
sum += i;
i += 1;
sum += i;
i += 1;
sum += i;
i += 1;
.... 加到i=n為止。
耶?怎麼突然可以了?
do-while的寫法
while的寫法
但n=0呢?
程式練習題
接下來有一題請你用
程式實做重複結構的題目。
Exercise IV - isPrime - 質數判斷 - 0
20 mins
數字範圍:
Exercise IV - isPrime - 質數判斷 - 1
20 mins
#include <iostream>
#include <cmath>
using namespace std;
int main() {
long long x;
cin >> x;
cout << sqrt(x) << endl;
return 0;
}
輸入一個數字,輸出平方根的小小程式例子
數字範圍:
Exercise IV - isPrime - 質數判斷 - 2
20 mins
#include <iostream>
#include <cmath>
using namespace std;
int main() {
long long i = 2, x;
cin >> x;
while (i <= sqrt(x)) {
cout << (x % i) << " ";
i += 1;
}
return 0;
}
小小提示
數字範圍:
Exercise IV - isPrime - 質數判斷 - 3
20 mins
#include <iostream>
#include <cmath>
using namespace std;
int main() {
long long i = 2, x;
cin >> x;
bool is_prime = (x != 1);
while (i <= sqrt(x)) {
if (x % i == 0)
is_prime = false;
i += 1;
}
cout << (is_prime ? "Yes" : "No") << endl;
return 0;
}
質數驗證的解答code
數字範圍:
Exercise IV - isPrime - 質數判斷 - 4
20 mins
long long i = 2, x;
cin >> x;
bool is_prime = (x != 1);
while (i <= sqrt(x)) {
if (x % i == 0)
is_prime = false;
i += 1;
}
cout << (is_prime ? "Yes" : "No") << endl;
質數驗證的解答code
int sum = 0, i = 1;
while (i != n+1) {
sum += i;
i += 1;
}
數字加總的code
for - 0
for 流程圖
int sum = 0, i = 1;
while (i != n+1) {
sum += i;
i += 1;
}
int sum = 0;
for (int i=1; i != n+1; i+=1) {
sum += i;
}
for 流程圖
int sum = 0, i = 1;
while (i != n+1) {
sum += i;
i += 1;
}
int sum = 0;
for (int i=1; i != n+1; i+=1) {
sum += i;
}
for (初始設置; True / False; 控制運算) {
// 做事情
}
for - 1
for 流程圖
int sum = 0;
for (int i=1; i != n+1; i+=1) {
sum += i;
}
for - 2
for - 3
for 流程圖
for (int i=a; i<=b; i++) { }
for (int i=1; i<=b; i*=2) { }
* i++ 和 ++i 和 i+=1; 和 i=i+1 在只有單獨出現的時候沒有什麼不同。
for (int i=a; i<b; i++) { }
變數 i 轉變的過程
for (int i=0; i<n; i++) { }
使用時機 / code
long long i = 2, x;
cin >> x;
bool is_prime = (x != 1);
while (i <= sqrt(x)) {
if (x % i == 0)
is_prime = false;
i += 1;
}
cout << (is_prime ? "Yes" : "No") << endl;
質數驗證的解答code (while)
數字範圍:
long long x;
cin >> x;
bool is_prime = (x != 1);
for (int i=2; i <= sqrt(x); i++) {
if (x % i == 0)
is_prime = false;
}
cout << (is_prime ? "Yes" : "No") << endl;
質數驗證的解答code (for)
for - 4
5 mins
5 mins
long long x;
cin >> x;
bool is_prime = x != 1;
for (int i=2; is_prime && i<=sqrt(x); i++) {
if (x % i == 0)
is_prime = false;
i += 1;
}
cout << (is_prime ? "Yes" : "No") << endl;
使用變數判斷提早跳出迴圈。
long long x;
cin >> x;
bool is_prime = x != 1;
for (int i=2; i<=sqrt(x); i++) {
if (x % i == 0) {
is_prime = false;
goto out;
}
i += 1;
}
out:
cout << (is_prime ? "Yes" : "No") << endl;
使用goto提早跳出迴圈。
for - 5
break & continue - 0
while + break
for + break
long long x;
cin >> x;
bool is_prime = x != 1;
for (int i=2; i<=sqrt(x); i++) {
if (x % i == 0) {
is_prime = false;
break;
}
i += 1;
}
cout << (is_prime ? "Yes" : "No");
cout << endl;
break & continue - 1
whlie + continue
for + continue
long long x;
cin >> x;
bool is_prime = x != 1;
for (int i=1; i<=sqrt(x); i++) {
if (i == 1)
continue;
if (x % i == 0) {
is_prime = false;
break;
}
i += 1;
}
cout << (is_prime ? "Yes" : "No");
cout << endl;
break & continue - 2
#include <iostream>
using namespace std;
int main () {
for (int i=0; i<10; i++) {
if (i % 2 == 0)
continue;
if (i == 7)
break;
cout << i << " ";
}
}
1 3 5
for + break
for + continue
2 mins
Loop p.s. - 0
Loop p.s. - 1
while (1) {
}
for 流程圖
for (;;) {
}
Loop p.s. - 2
for (int i = 0, j = 1; i < n && j <= m; i++, j*=2) {
// 做事情
}
Loop p.s. - 3
variable scope
#include <iostream>
using namespace std;
int main () {
int i = 7;
if (true) {
cout << i;
int i = 5;
cout << i;
}
cout << i;
}
757
一份看起來很混亂,實際上也很混亂的code
Loop p.s. - 4
variable scope
為什麼呢?
(A)
(B)
(C)
0 1 2 3 7
(D)
(C)
#include <iostream>
using namespace std;
int main () {
int i = 7, n = 3;
for (int i=0; i<n; i++)
cout << i << " ";
cout << i << endl;
}
0 0
1 1
2 2
3 3
Compiler Error
0 1 2 7
2 mins
Loop sp. - 0
取自 zerojudge a004 的輸入說明
int x;
while (cin >> x) {
// 做事情
}
輸入一個數字直到EOF的範例
Loop sp. - 1
*例如loop12
你曾經看過的 if-else 的投影片
Loop sp. - 2
我沒有故意要湊表情符號@@
"-->"是什麼運算子?
在讀完...,我驚奇的發現下面這份code可以編譯&成功執行
我想這是C的語法,因為GCC編譯器也可以執行。請問他定義在編譯器標準的哪裡?
// x 趨近於0
stackoverflow
一個(通常)發問程式問題的地方。
Loop sp. - 2
我沒有故意要湊表情符號@@
int Q = 4;
while (Q --> 0) {
cout << "(" << Q << ")";
}
(3)(2)(1)(0)
Q --> 0 的範例 (4次)
int Q = 4;
while (Q --> -2) {
cout << "(" << Q << ")";
}
(3)(2)(1)(0)(-1)(-2)
Q --> -2 的範例 (6次)
int Q = 4;
while (0 <-- Q) {
cout << "(" << Q << ")";
}
(3)(2)(1)
0 <-- Q 的範例 (3次)
Loop sp. - 2
我沒有故意要湊表情符號@@
你長度多一點遞減比較快(?)
用反斜線畫斜向箭頭。
APCS觀念考古題
接下來有四題重複結構的APCS觀念題目。
15. 若以f(22)呼叫右側 f()函式,總共會印出多少數字?
3 mins
void f(int n) {
printf ("%d\n", n);
while (n != 1) {
if ((n%2)==1) {
n = 3*n + 1;
}
else {
n = n / 2;
}
printf ("%d\n", n);
}
}
因為你可能看不懂,在這邊先解釋一下:
printf("%d\n", n);
cout << n << endl;
Exercise V - APCS觀念題 - I
這不就是考拉茲猜想 (3n+1問題)?
21. 右側程式碼,執行時的輸出為何?
2 mins
void main() {
for (int i=0; i<=10; i=i+1) {
// printf ("%d ", i);
cout << i << " ";
i = i + 1;
}
// printf ("%d ", i);
cout << endl;
}
0 2 4 6 8 10
0 1 2 3 4 5 6 7 8 9 10
(A)
(B)
0 1 3 5 7 9
(C)
0 1 3 5 7 9 11
(D)
(A)
因為第5行, i 變成 1。
因為for迴圈的i=i+1,i 變成 2。
輸出 2。 (接著下去直到 i = 12才會跳出去。)
Exercise V - APCS觀念題 - II
12. 右側程式片段執行過程中的輸出為何?
2 mins
int a = 5;
// ...
for (int i=0; i<20; i=i+1){
i = i + a;
// printf ("%d ", i);
cout << i << " ";
}
5 10 15 20
5 11 17 23
(A)
(B)
6 12 18 24
(C)
6 11 17 22
(D)
(B)
Exercise V - APCS觀念題 - III
接下來因為 i = i + a; 還有 i =i + 1; ,所以每次輸出前都會+6。
13. 右側程式片段無法正確列印 20 次的"Hi!",請問下 列哪一個修正方式仍無法正確列印 20 次的"Hi!"?
for (int i=0; i<=100; i=i+5) {
// printf ("%s\n", "Hi!");
cout << "Hi!" << endl;
}
需要將 i<=100 和 i=i+5 分別修正為 i<20 和 i=i+1
需要將 i=0 修正為 i=5
(A)
(B)
需要將 i<=100 修正為 i<100;
(C)
需要將 i=0 和 i<=100 分別修正為 i=5 和 i<100
(D)
(D)
Exercise V - APCS觀念題 - IV
2 mins
程式練習題
接下來有一題請你用
程式實做重複結構的題目。
Exercise V - 第二大數字判斷 - -1
20 mins
Exercise V - 第二大數字判斷 - 0
20 mins
20 mins
#include <iostream>
using namespace std;
int main () {
unsigned long long n, fmax;
cin >> n;
for (int i=0; i<n; i++) {
unsigned long long x;
cin >> x;
if (i == 0 || x > fmax)
fmax = x;
}
cout << fmax << endl;
}
找出最大的數字,想想看為甚麼要加上判斷 i == 0?
Exercise V - 第二大數字判斷 - 1
20 mins
目前最大值
fmax
目前第二大值
smax
x >= fmax
fmax >= x x >= smax
smax >= x
if (x > fmax)
smax = fmax, fmax = x;
else if (x > smax)
smax = x;
大概寫出來的樣子
Exercise V - 第二大數字判斷 - 2
20 mins
#include <iostream>
using namespace std;
int main () {
unsigned long long n, fmax, smax;
cin >> n;
for (int i=0; i<n; i++) {
unsigned long long x;
cin >> x;
if (i == 0 || x > fmax)
smax = fmax, fmax = x;
else if (i == 1 || x > smax)
smax = x;
}
cout << smax << endl;
}
最終解答的長相
if (x > fmax)
smax = fmax, fmax = x;
else if (x > smax)
smax = x;
大概寫出來的樣子
if (i == 0 || x > fmax)
smax = fmax, fmax = x;
else if (x > smax)
smax = x;
如果是第一個數字,強制設成fmax就可以了,那smax...?
Exercise V - 第二大數字判斷 - 3
20 mins
unsigned long long fmax = 0;
unsigned long long smax = 0;
if (x > fmax)
smax = fmax, fmax = x;
else if (x > smax)
smax = x;
大概寫出來的樣子
Exercise V - 第二大數字判斷 - 4
#include <iostream>
using namespace std;
int main () {
unsigned long long n, fmax=0, smax=0;
cin >> n;
for (int i=0; i<n; i++) {
unsigned long long x;
cin >> x;
if (x > fmax)
smax = fmax, fmax = x;
else if (x > smax)
smax = x;
}
cout << smax << endl;
}
最終解答的長相
Review - 0
再變得更難之前,我們來看看我們曾經做過什麼吧!
循環的猜數字 (goto)
可控隨機數 (看著流程圖用goto實作 -> for + do-while)
考拉茲猜想 (goto -> do-while -> while)
進位制轉換 (do-while)
累加數字 1+2+...+n (while -> for)
判斷質數 (while -> +break)
Review - 1
goto流程圖
// 設下標記點
labelA:
do_something();
// 跳到標記點
goto labelA;
goto 語法
Review - 2
do {
do_something();
// 如果true會跳到do{那行
} while (true 或 false);
do-while流程圖
do-while 語法
Review - 3
while流程圖
// while 一開始,如果判斷為F則跳到}後
while (T / F) {
// 做事情
} // 結束會回到while(){重新判斷
while 語法
Review - 4
for 流程圖
for (初始設置; True / False; 控制運算) {
// 做事情
}
for 語法
Review - 5
for + break
for + continue
#include <iostream>
using namespace std;
int main () {
for (int i=0; i<10; i++) {
if (i % 2 == 0)
continue;
if (i == 7)
break;
cout << i << " ";
}
}
輸出: 1 3 5
Nested Loop - 0
我們先來看看什麼是巢狀結構。
巢狀選擇結構的投影片。
Nested Loop - 1
還記得Exercise I - 可控隨機數嗎?
你能不使用goto,用其他種迴圈實作出來嗎?
int cnt = 0;
start:
int x = LFSR() % (n+1);
if (x % k == 0)
goto start;
cout << x << endl;
cnt ++;
if (cnt != 5)
goto start;
可控隨機數的流程圖
可控隨機數的code
Nested Loop - 2
還記得Exercise I - 可控隨機數嗎?
用do-while處理生亂數,因為次數不定,而且要先做一次。
int x, cnt = 0;
start:
do {
x = LFSR() % (n+1);
} while (x % k == 0);
cout << x << endl;
cnt ++;
if (cnt != 5)
goto start;
可控隨機數的流程圖
將生成亂數轉成比較可讀的迴圈
Nested Loop - 3
還記得Exercise I - 可控隨機數嗎?
用for處理計數字,因為固定要5次。
你會發現,這竟然是for + do-while的雙重迴圈。
Wow!竟然我們一開始學的例題就是巢狀迴圈嗎?
int x;
for (int cnt=0; cnt < 5; cnt++) {
do {
x = LFSR() % (n+1);
} while (x % k == 0);
cout << x << endl;
}
可控隨機數的流程圖
將計數五次轉成比較可讀的迴圈
Double for - 0
你知道什麼是一維座標系嗎?
我們可以用一個迴圈印出所有的點。
一個笛卡爾坐標系的範例圖
一個一維座標系(數線)的範例圖
for (int i=0; i<=n; i++) {
cout << "(" << i << ")\t";
}
* '\t'叫做水平定位符,簡單來說就是幫你空格到下一個八的倍數的地方。
Double for - 1
一個笛卡爾坐標系的圖
int n, m;
cin >> n >> m;
//==========================
for (int j=0; j<=m; j++) {
cout << "(" << j << ")\t";
}
cout << endl;
//==========================
for (int j=0; j<=m; j++) {
cout << "(" << j << ")\t";
}
cout << endl;
//==========================
for (int j=0; j<=m; j++) {
cout << "(" << j << ")\t";
}
cout << endl;
// 重複做n+1次
int n, m;
cin >> n >> m;
for (int i=0; i<=n; i++) {
for (int j=0; j<=m; j++) {
cout << "(" << j << ")\t";
}
cout << endl;
}
Double for - 2
一個笛卡爾坐標系的圖
(0,0) (0,1) (0,2) (0,3) (0,4)
(1,0) (1,1) (1,2) (1,3) (1,4)
(2,0) (2,1) (2,2) (2,3) (2,4)
(3,0) (3,1) (3,2) (3,3) (3,4)
(4,0) (4,1) (4,2) (4,3) (4,4)
#include <iostream>
using namespace std;
int main () {
int n, m;
cin >> n >> m;
for (int i=0; i<=n; i++) {
for (int j=0; j<=m; j++) {
cout << "(" << i << "," << j << ")\t";
}
cout << endl;
}
}
Double for - 3
(0,0) (0,1) (0,2) (0,3) (0,4)
(1,0) (1,1) (1,2) (1,3) (1,4)
(2,0) (2,1) (2,2) (2,3) (2,4)
(3,0) (3,1) (3,2) (3,3) (3,4)
(4,0) (4,1) (4,2) (4,3) (4,4)
輸入n, m,印出nm平面座標的程式。
#include <iostream>
using namespace std;
int main () {
int n, m;
cin >> n >> m;
for (int i=0; i<=n; i++) {
for (int j=0; j<=m; j++) {
cout << "(" << i << "," << j << ")\t";
}
cout << endl;
}
}
n, m = 4, 4的二維座標系
Double for - 4
接著我們利用座標系的雙層迴圈,做點轉換。
題目:你能夠依據右邊的程式,寫出一個
九九乘法表嗎? (從1到9,沒有0。)
提示:觀察印出來的座標和99乘法表的關係。
把範圍跟輸出稍微改一下就可以了!
#include <iostream>
using namespace std;
int main () {
for (int i=1; i<=9; i++) {
for (int j=1; j<=9; j++)
cout << i * j << "\t";
cout << endl;
}
}
10 mins
輸入n, m,印出nm平面座標的程式。
#include <iostream>
using namespace std;
int main () {
int n, m;
cin >> n >> m;
for (int i=0; i<=n; i++) {
for (int j=0; j<=m; j++) {
cout << "(" << i << "," << j << ")\t";
}
cout << endl;
}
}
(0,0) (0,1) (0,2) (0,3) (0,4)
(1,0) (1,1) (1,2) (1,3) (1,4)
(2,0) (2,1) (2,2) (2,3) (2,4)
(3,0) (3,1) (3,2) (3,3) (3,4)
(4,0) (4,1) (4,2) (4,3) (4,4)
n, m = 4, 4的二維座標系
一般的九九乘法表。
如果你把九九乘法表的迴圈全部都用 goto 實作,你會覺得這到底是三小==。
用 goto 實作九九乘法表。
#include <iostream>
using namespace std;
int main() {
int i = 1;
outer:
int j = 1;
inner:
cout << i * j << "\t";
j += 1;
if (j <= 9)
goto inner;
cout << endl;
i += 1;
if (i <= 9)
goto outer;
}
Double for - 5
程式練習題
接下來有一題請你用
程式實做多重迴圈的題目。
Exercise VII - 指數表 - 0
20 mins
"1\t0\t0\t0\t0\t0\n"
"1\t1\t1\t1\t1\t1\n"
"1\t2\t4\t8\t16\t32\n"
"1\t3\t9\t27\t81\t243\n"
"1\t4\t16\t64\t256\t1024\n"
"1\t5\t25\t125\t625\t3125\n"
輸入 5 5 應該要輸出的表
1 0 0 0 0 0
1 1 1 1 1 1
1 2 4 8 16 32
1 3 9 27 81 243
1 4 16 64 256 1024
1 5 25 125 625 3125
怕你格式有問題,這邊印出C++表達式。
(記得行末沒有\t。)
20 mins
Exercise VII - 指數表 - 1
int x = 1;
for (int k=1; k<=m; k++) {
x *= n;
}
給定數字 ,算出
20 mins
Exercise VII - 指數表 - 2
#include <iostream>
using namespace std;
int main () {
int n, m;
cin >> n >> m;
for (int i=0; i<=n; i++) {
for (int j=0; j<=m; j++) {
cout << "(" << i << "," << j << ")\t";
}
cout << endl;
}
}
輸入 ,印出 平面座標的程式。
#include <iostream>
using namespace std;
int main () {
int n, m;
cin >> n >> m;
for (int i=0; i<=n; i++) {
for (int j=0; j<=m; j++) {
// 想要印出 i^j
int x = 1;
for (int k=1; k<=j; k++) {
x *= i;
}
cout << x << (j != m ? '\t' : '\n');
}
}
}
把 的程式貼上去改一改就可以了
20 mins
Exercise VII - 指數表 - 2
#include <iostream>
using namespace std;
int main () {
int n, m;
cin >> n >> m;
for (int i=0; i<=n; i++) {
int x = 1;
for (int j=0; j<=m; j++) {
cout << x << (j != m ? '\t' : '\n');
x *= i;
}
}
}
其實 可以透過 來算出,
利用前面算過的值就不用跑這麼多次了!
#include <iostream>
using namespace std;
int main () {
int n, m;
cin >> n >> m;
for (int i=0; i<=n; i++) {
for (int j=0; j<=m; j++) {
// 想要印出 i^j
int x = 1;
for (int k=1; k<=j; k++) {
x *= i;
}
cout << x << (j != m ? '\t' : '\n');
}
}
}
把 的程式貼上去改一改就可以了
Double Break!! - 0
10 mins
#include <iostream>
using namespace std;
int main () {
for (int i=1; i<=9; i++) {
for (int j=1; j<=9; j++)
cout << i * j << "\t";
cout << endl;
}
}
一般的九九乘法表。
Double Break!! - 1
10 mins
for (int i=1; i<=9; i++) {
bool flag = false;
for (int j=1; j<=9; j++) {
cout << i * j << "\t";
if (i*j == 49) {
flag = true;
break;
}
}
cout << endl;
if (flag)
break;
}
利用變數來跳脫雙重迴圈
Double Break!! - 2
10 mins
for (int i=1; i<=9; i++) {
bool flag = false;
for (int j=1; j<=9; j++) {
cout << i * j << "\t";
if (i*j == 49)
goto end;
}
cout << endl;
}
// 稍微注意一下,標記點之後
// 沒有code要加分號。
end:;
利用 goto 來跳脫雙重迴圈
程式練習題
接下來有一題請你用
程式實做多重迴圈的題目。
20 mins
Exercise VIII - I - 孤單的機器人 - 1
.@..
....
....
輸入:
n, m = 3, 4
x, y = 0, 1
Q = 3
初始地圖
(不用輸出)
..@.
....
....
..@.
....
....
....
..@.
....
D
W
S
往右移動
往上移動
但碰壁,不能移動
往下移動
結束!
忽略指令
也要輸出。
Exercise VIII - I - 孤單的機器人 - 2
20 mins
for (int i=0; i<n; i++) {
for (int j=0; j<m; j++) {
if (i == x && j == y)
cout << '@';
else
cout << '.';
}
cout << endl;
}
Exercise VIII - I - 孤單的機器人 - 3
20 mins
char cmd;
cin >> cmd;
if (cmd == 'W' && x != 0) x--;
if (cmd == 'A' && y != 0) y--;
if (cmd == 'S' && x != n-1) x++;
if (cmd == 'D' && y != m-1) y++;
Exercise VIII - I - 孤單的機器人 - 4
20 mins
#include <iostream>
using namespace std;
int main () {
int n, m, x, y, Q;
cin >> n >> m >> x >> y >> Q;
while (Q--) {
char cmd;
cin >> cmd;
if (cmd == 'W' && x != 0) x--;
if (cmd == 'A' && y != 0) y--;
if (cmd == 'S' && x != n-1) x++;
if (cmd == 'D' && y != m-1) y++;
for (int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
if (i == x && j == y)
cout << '@';
else
cout << '.';
}
cout << endl;
}
}
return 0;
}
Exercise VIII - I - 孤單的機器人 - 5
感覺很長的解答code
Exercise VIII - II - 孤單的機器人 (補充) - 0
Exercise VIII - II - 孤單的機器人 (補充) - 1
#include <windows.h>
#include <iostream>
using namespace std;
int main () {
while (true) {
cout << GetKeyState(VK_LEFT);
// 停0.1秒
Sleep(100);
}
}
跑跑看這份code!然後按按看左鍵(?)
5 mins
Exercise VIII - II - 孤單的機器人 (補充) - 2
#include <windows.h>
#include <iostream>
using namespace std;
int main () {
while (true) {
cout << GetKeyState(VK_LEFT);
// 停0.1秒
Sleep(100);
}
}
跑跑看這份code!然後按按看左鍵(?)
0
-127
1
-128
按下
按下
放
開
放
開
10 mins
Exercise VIII - II - 孤單的機器人 (補充) - 3
#include <windows.h>
#include <iostream>
using namespace std;
int main () {
bool pressed = false;
while (true) {
int getKeyLeft = GetKeyState(VK_LEFT);
if (getKeyLeft >= 0)
pressed = false;
else if (!pressed) {
pressed = true;
cout << "Left!" << endl;
}
}
}
0
-127
1
-128
按下
按下
放
開
放
開
10 mins
pressed =
false
pressed =
true
pressed =
false
pressed =
true
Exercise VIII - II - 孤單的機器人 (補充) - 4
10 mins
按下A: GetKeyState('A'),只能用大寫,A-Z同理。
按上下左右: VK_UP / VK_DOWN / VK_LEFT / VK_RIGHT
滑鼠左/右鍵: VK_LBUTTON / VK_RBUTTON
Enter: VK_RETURN
左/右Shift: VK_LSHIFT / VK_RSHIFT
F1...F12: VK_F1 ... VK_F12
...
跑出來大概的樣子
Exercise VIII - II - 孤單的機器人 (補充) - 5
10 mins
system("cls");
可以做到像這樣的事情。
程式練習題
接下來有一題請你用
程式實做重複結構的題目。
20 mins
Exercise IX - 解析幾何小幫手 - 1
*****
*****
*****
*****
****
***
***
***
**
範例測資1的輸入
不等式的長相
畫布該畫的區域
你的程式該輸出...
* 左下角(0, 0),
右上角(n, m)
20 mins
Exercise IX - 解析幾何小幫手 - 2
#include <iostream>
using namespace std;
int main() {
int n, m, a, b, c, d, e, f;
cin >> n >> m >> a >> b >> c >> d >> e >> f;
for(int y=m; y>=0; y--) {
for(int x=0; x<=n; x++){
bool constraint = (a*x*x + b*x*y + c*y*y + d*x + e*y >= f);
cout << (constraint ? '*' : ' ');
}
cout << endl;
}
return 0;
}
程式練習題
接下來有一題請你用
程式實做重複結構的題目。
20 mins
Exercise X - 數字三角形 - 0
__+
_++
+++
n = 3 的樣子
n = 5 的樣子
___________+
__________++
_________+++
________++++
_______+++++
______++++++
_____+++++++
____++++++++
___+++++++++
__++++++++++
_+++++++++++
++++++++++++
n = 12 的樣子
____+
___++
__+++
_++++
+++++
20 mins
____+
___++
__+++
_++++
+++++
n = 5的樣子
Exercise X - 數字三角形 - 1
20 mins
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
if (i+j >= n-1)
cout << "+";
else
cout << "_";
}
cout << endl;
}
}
雙層迴圈 + if-else 的解答
Exercise X - 數字三角形 - 2
20 mins
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i=0; i<n; i++) {
for (int j=0; j<n-i-1; j++)
cout << "_";
for (int j=0; j<=i; j++)
cout << "+";
cout << endl;
}
}
內層迴圈拆解的解答
Exercise X - 數字三角形 - 3
Review - 0
Review - 1
Peipei的投影片
Review - 2
影片: 四維陣列 (時間, RGBA, X軸, Y軸)
格子狀地圖: 二維陣列 ((X,Y)放了甚麼)
題目表 - 0
題目表 - 1