阿格里森姆 - 2

實際上還在語法

Lecturer:我才不在乎梵諦岡的袋鼠

             Repkironca、阿蘇

圈內人數數都是 zero-based

田鼠這個菜逼八寫錯了 🐢🐢🐢

不要懷疑,這真的是第二節

Bruh 我超級有誠意

目錄有做超連結ㄛㄛㄛ

I 雜七雜八補充

還敢教那麼快啊 BrineTW

Online Judge 上的回應結果

簡稱

全名

翻譯年糕

常見原因

AC

Accepted

測資全過

輸出正確

你太電了

我也是沒辦法

WA

Wrong Answer

有一筆或多筆測資沒過

未考慮極端測資

扣沒照著你理想跑

TLE

Time Limit Error

你扣跑太慢了

超出規定時間

時間複雜度過高

無限迴圈沒有 break

Online Judge 上的回應結果

簡稱

全名

翻譯年糕

常見原因

MLE

Memory Limit Error

記憶體被你

用爆了啦

請不要開超大陣列好嗎

遞迴打太深ㄌ

RE

Runtime Error

扣跑到一半吃

segfault

陣列的索引值超出範圍

訪問 deleted pointer

CE

Complie Error

在編譯過程中

就已經爛掉了

你直接在解答區打扣 ==

拿非常數去設定 array

endl 哪裡做錯了???

  • 還記得 i/o 優化嗎,不開在競程上很容易出事
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// 其實第三行可以不加,但我習慣會給
  • 事實上,文字在輸出前,會先進到一個 緩衝區    在特定時間才會輸出,不見得與你預想的一樣
  • 把緩衝區的文字強制輸出:flush,是件很耗時間的事
  • OJ 只管你最後的輸出對不對,根本不在意文字是何時輸出的,顯然我們沒有一直 flush 的需求

endl 哪裡做錯了???

  • 是故,除非你今天在做互動題(一般會明講要你 flush)  否則不要亂用 endl,就算它看起來很酷
  • endl 本身的意義是 換行並 flush,會直接毀了你的優化

直接用 '\n' 換行就好ㄌ

  • But,cin 本身就帶有 flush 的功能,我們要把它取消
cin.tie(0);
  • 另外,C++ 預設會讓 iostream 與 stdio 同步,但這也很浪費時間,最好也取消這個
ios_base::sync_with_stdio(false);

auto && 快速遍歷

BrineTW 有講過這個,但他只有提到用 auto 遍歷

  • auto:讓 C++ 自動幫你判斷變數型別
  • 一般是用在已知型別的複製上,不要當成 JS 的 var 用,很容易出事
vector <int> vec; // type:vector
auto tmp = vec; // type:vector
vector <vector <pair <pair <int, char>, pair <int, bool> > > > mess;
auto tmp = mess[0][0].first; // type:pair <int, char>
  • 快速遍歷 ( [類型] 命名 : [容器] )
vector <int> vec(100, 1);
for (int i = 0; i < vec.size(); i++)
  cout << vec[i] << ' ';
for (auto to:vec) // type of auto:int
  cout << to << ' ';
=

其實 vector 下節課會重教,他本來就是那邊的範圍

0 / 1 取代 false / true 有哪裡不好嗎

  • 如果你只是要當作 while () 中的判斷之類,   的確不太會出事
int input_count; cin >> input_count;
while (input_count--){
	
}
  • 資芽的語法班會扣你 coding-style 分數
  • 但當你需要 C++ 自動判斷 type 時,就要特別留心
void typeCheck (int tmp){
  cout << "This is an integer\n";
}

void tyoeCheck (bool tmp){
  cout << "This is a boolean\n";
}

int main (){
  cout << typeCheck(1) << '\n';
  //這絕對會判成整數
}

define

  • 把特定關鍵字 取代 成你想要的東西!
#define ll long long int
#define vveci vector <vector <int> >
#define gura ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);

語法

#define (空格) [關鍵字] (空格) [內容]

換言之,系統會在你 code 運行前,就先把關鍵字 全部取代完
  • 屬於 C++ 的 預處理,所以要加 #,不用加分號

* 預處理:在實際執行你的 code 之前,就會先做完的事情

除非你想把 ; 也 define 進去

define

  • 進階應用:帶參數的 define
#define sum(a, b) a + b
#define mod(a, b) (a+b) % b
#define print(str) cout << str << '\n';

現在你們可以拿 C++ 寫 python 了

int main (){
  cout << sum(2, 3) << '\n';
  cout << sum(-2, 3) << '\n';
}

output:

5

1

int main (){
  print("This is C++")
}

output:

This is C++

define

關鍵字 內容 備註
veci vector <int> 好像不怎麼常見
pii pair <int, int> 你們還沒教,但很常見
F / FF first 你們還沒教,但很常見
S / SS second 你們還沒教,但很常見
pq priority_queue ​你們還沒教,但超常見
ll long long int 常見到幾乎等於默認
usll unsigned long long int 默認關鍵字不是這個
gura (3 行 i/o 優化) 默認關鍵字絕對不是這個
debug(x) cerr << x << '\n Aaw 大推

我自己常用的一些 define

(有些很毒不建議模仿)

printf

  • 與 cout 不同的 輸出方法
  • 屬於 <stdio.h> ,我不知道為何 APCS 超級愛它
  • 呈上,會破壞 i/o 優化,不要跟 cout 混用(debug 完 記得註解掉

語法

printf(" [輸出文字與格式指定碼] ", [要填入的變數] );

printf("print without cout\n");

print without cout

int a = 2, b = 5;
printf("%d + %d = %d\n", a, b, a+b);

註:整數的格式指定碼為 %d

2 + 5 = 7

printf

  • 遇到要填入的變數,就先用 格式指定碼 取代,逗號後再依序補上
  • 如果輸出格式很煩,要打一堆 <<,也可以考慮用 printf
  • 與 cout 不同,變數格式要 自行判斷,只要填錯就會 CE
%d 10 進位整數
%f  浮點數
%s 字串
%p 指標記憶體

最常用的格式指定碼

debug 的基本技巧

1. 亂砸測資

看清楚題目的範圍,常常就是被那一筆極限搞到

N\;\in\;Z\\ N\;\geq\;0\\ \forall\;N\;\leq\; M \leq\; 1e5

可能會出現

N = 0 且 M = 0 的 case

M 是小數的 case 也合理

相信我,80 % 都不是照著你預想的跑,人難免會失誤

2. cout 大法

把每個執行階段的關鍵變數都 cout 出來

  • 如果有用遞迴,進入迴圈時輸出所有傳入值
  • 如果有一堆迴圈,迴圈結束時輸出你改變的東西

debug 的基本技巧

3. 註解大法

把一大部分的程式註解掉,每次只讓小部份執行

尋找問題出在哪裡,一旦哪行進來程式就無法執行

(常用於 RE、MLE、CE 時)

4. ㄟ學長姐幫我看一下啦拜託嘛我超級需要你耶

學長姊都很 nice,絕對會幫忙你的

但一般我們也只是重複上面三個步驟

只是經驗稍微多一點而已

不要覺得這些很基本耶

因為有很多一三都不會,吐血

II 遞迴 Recursion

在學演算法前的必備技能

一句話定義

  • 一坨演算法的實作方式
  • APCS 超級愛考
  • 符合直覺,真的不會的題目可以拿來暴力
遞迴ㄛ,在 function 中呼喚自己,        真的就這樣而已啊

– 阿蘇自己亂掰的
 

認真的定義

"若有一函數,是由自身所定義的,我們將此稱為遞迴

我想知道費氏數列的第 N 項

你有辦法通靈出一段 code

負責解決這個問題ㄇ

a_n = \left\{ \begin{matrix} 0 &if& n = 0\\ 1 &if& n = 1\\ a_{n-1} + a_{n-2} &if& n \geq 2 \end{matrix} \right.

數學上的遞迴

e.g. 費波那契數列

0, 1, 1, 2, 3, 5, 8, 13, 21, 34...

* 如果所求項是第 0 項(雖然理論上不可能)

   或第 1 項,要把它特判掉

   否則會出現 Fibonacci (-1) 這種奇怪東東

當然你也可以拿迴圈,就本題來說速度甚至會更快

但暫不列入今日討論範圍

int Fibonacci(int tar, int index = 2, int a = 1, int b = 0){
  if (tar == 0) return 0;
  // 如果是第 0 項,定義為 0
  if (tar == 1) return 1;
  // 如果是第 1 項,定義為 1
  if (tar == index) return a + b;
  // 若已經找到所求項,則 a + b 就是答案
  return Fibonacci(tar, ++index, a+b, a);
  // 否則更新 a、b,繼續找下一項
}

拿遞迴刻,這堂課的重點

不過遞迴沒刻好,會讓你進入無窮迴圈ㄛ

終端條件:讓你遞迴能結束的方法

  • 一定要確定這遲早會發生
int Fibonacci(int tar, int index = 2, int a = 1, int b = 0){
  if (tar == 0) return 0;
  if (tar == 1) return 1;
  if (tar == index) return a + b;
  return Fibonacci(tar, ++index, a+b, a);
}

第 4 行的 if

當找到我們要的那項

就把遞迴結束

  • 要放在呼叫自身函式的前面
int Fibonacci(int tar, int index = 2, int a = 1, int b = 0){
  if (tar == 0) return 0;
  if (tar == 1) return 1;
  return Fibonacci(tar, ++index, a+b, a);
  if (tar == index) return a + b;
}

左邊就是無窮迴圈

條件寫心酸的嗎.jpg

遞迴裸題

 

F(x) = \left\{ \begin{matrix} 1 &if& x = 1\\ F(x/2) &if& x \equiv 0 \pmod{2}\\ F(x-1) + F(x+1) &if& x \equiv 1 \pmod{2} \end{matrix} \right.
int F (int x){
  if (x == 1) return 1;
  if (x%2 == 0) return F(x/2);
  return F(x-1) + F(x+1);
}
  • 偶數:跟 2 取模 = 0

或跟 1 做 and 等於 0

沒難度吧。那我們幫題目穿上衣服(X

稍微加入一點點變化...?

 

  • 好消息,他已經給我們函式回傳結果了

我本來以為要自己推導函式,怕爆

  • 遞迴式...?那種東西在這題好像沒什麼用
  • 把函式丟到函式裡面...不覺得怎麼聽都很遞迴嗎
vector <int> ret(1e5+17, 0);

int query (int num, int count){
  if (count > 0) return query(ret[num], --count);
  return num;
}
  • 好寫、符合直覺

Why Recursion?

  • 可讀性高
  • 速度相對比較慢
  • 吃空間,容易爆 MLE

往後很多題目,你第一個想到的往往是遞迴解

跟迴圈寫法相較,遞迴會比較好懂

等他一來一往的時間,常常已經 TLE 了

MAXN 大的題目,會因為開太深而直接爆記憶體

總結:遞迴是種語法兼概念,主要是應用在 演算法實作 上,

   但單獨考遞迴的題目其實不多,常常是暴力解擔當

不過有個破考試對遞迴情有獨鐘ㄛ...

\begin{aligned} & \Sigma_{N = 1}^{100} + 10\\ &= 101 × 50 + 10\\ &= 5060 \end{aligned}
long long f(int x, int y) {
    if (x == 0) return y;
    else return f(x - 1, x + y);
}

int main() {
    printf("%d\n", f(100, 10));
    //cout << f(100, 10) << '\n';
}

APCS 觀念題 111 年 01 月 第一場 p13

求輸出,沒有選項因為沒人記得。

  • 第 7 行是來亂的,永遠不可能 run 到
  • 第 4 行的 n / 2 會 = 0,等同於 return 1 + 0 = 1

k(30)

k(7)

k(1)

30
+\;7
+\;1
+\;0
=\;38

k(0)

int k(int n) {
    switch(n) {
        case 0: return n;
        case 1: return n + k(n / 2);
        default: return n + k(n / 4);
    }
    return n;
}

int main() {
    printf("%d\n", k(30));
    //cout << k(30) << '\n';
}

APCS 觀念題 111 年 01 月 第一場 p14

求輸出,沒有選項因為沒人記得。

void func(int n) {
    printf("%d ", 2 * n);
    //cout << 2*n << '\n';
    if (n < 4)
        func(n + 1);
    printf("%d ", 2 * n - 1);
    //cout << 2*n - 1 << '\n';
}
int main (){
  func(2);
}

APCS 觀念題 111 年 01 月 第二場 p2

求輸出,沒有選項因為沒人記得。

[ output ]

4

L5

L5

L6

L6

L6

k(2)

L2

k(3)

L2

k(4)

L2

6

8

7

5

3

好耶砸題單時間(TCIRC)

其實就,輾轉相除法,一模一樣

很煩,超級煩,強烈建議用 vector 做

如果你做出了上一題,那這就是水題

已經有點實作題的味道ㄌ

好耶砸題單時間(CSES)

八皇后問題,去年有被改編成社賽題目

做為防破台門檻。你們肯定可以的吧:)

本來要當成例題,但我沒時間做

好耶砸題單時間(NEOJ)

當時被我跟先帝公認的煩死人題目

特別有趣,感受痛苦吧:)

有個內建函式可以解決這個

但試試用遞迴寫 la

如果現在想不出來,可以等上完 DP 再回頭

相對來說比較簡單

好耶砸題單時間(ZJ)

前面的例題,且與 TCIRC_b001 完全等價

呈 CSES_2165,不過又多了變化

現在開始與結束狀態都不固定了

先思考一下他的遞迴式為何?

題目本身是不難

但輸出格式很麻煩

III 結構 Struct

aka 變數縫合怪

若我們今天要儲存 N 個四維坐標 {x, y, z, w}

你直覺想到的做法會是什麼?

const int MAXN = 1007;
int x[MAXN], y[MAXN], z[MAXN], w[MAXN];

int main (){
  int N; cin >> N;
  for (int i = 1; i <= N; i++) cin >> x[i] >> y[i] >> z[i] >> w[i];
}
  • 開四條 array 存?
#define veci vector <int>
veci x(1007), y(1007), z(1007), w(1007);

int main (){
  int N; cin >> N;
  for (int i = 1; i <= N; i++) cin >> x[i] >> y[i] >> z[i] >> w[i];
}
  • 開四條 vector 存?

明明是同一組數據,卻要翻四個不同地方,感覺 缺乏整體性

結構 struct

  • 自己定義一種 資料結構,可將 變數函式 綁定在一起

語法(定義一個 struct)

sturct [結構名稱]{  //沒有 (),否則你會宣告成函式

    [成員變數或成員函式]

};   //這個分號一定要加!!!

struct location {
  int x, y, z, w;
};

例如剛剛的四維坐標

這樣存會好很多

struct wordle {
  int problem_ID;
  string answer;
  char letter[6];
  bool correct;
};

當然,你也可以

儲存類型不同的變數

結構 struct

  • 宣告 struct 的做法與 int、string 等 完全相同

語法(宣告一個 struct)

[結構名稱] [命名];

location dot;
const int MAXN = 1007;
location dot_set [MAXN];
vector <location> dot_set_2(MAXN);
while (int i = 1; i <= N; i++)
  cin >> dot_set[i].x >> dot_set[i].y >> dot_set[i].z >> dot_set[i].w;
  • 在你宣告的 struct 後加個 dot,就能汲取出裡面的 成員變數

語法(汲取成員變數)

[結構變數].[成員變數]

結構 struct

  • 其實不只變數,你甚至可以把整個 function 塞進 struct ㄛ
  • 順帶一提,你可以直接在定義時就做完初始化
struct location {
  int x = 0, y = 0, z = 0, w = 0;
};

int main (){
  location dot;
  dot.x = 5; dot.w = 37;
  printf("x = %d, y = %d, z = %d, w = %d\n", dot.x, dot.y, dot.z, dot.w);
}

output:x = 5, y = 0, z = 0, w = 37

結構 struct

struct location {
  int x = 0, y = 0, z = 0, w = 0;
  void printLoc (){
    printf("x = %d, y = %d, z = %d, w = %d\n", x, y, z, w);
  }
};

int main (){
  location dot, dot_2; //dot_2 就是初始化的狀態
  dot.x = 1; dot.y = 2; dot.z = 3; dot.w = 4;
  dot.printLoc();
  dot_2.printLoc();
}

把整個函式塞進 struct 的例子:

output:x = 1, y = 2, z = 3, w = 4

x = 0, y = 0, z = 0, w = 0

  • 適時地使用 struct,能大幅增加 code 的 可讀性            也更好配合之後教的 STL

從資芽偷來的 題目(NEOJ)

除了 print()、girls_average()、boys_average() 外,

不要上傳任何其他東西,也不要 #include 或 #define

同時它沒有 using namespace std,所以 cout 前要加 std::

拜託,真的,相信我,用 struct 做

否則你會極度痛苦

 

它有點煩,有問題可以來問我沒關係

從 lemonilemon偷來的 題目(ZJ)

建議用遞迴先做個 gcd() 出來

在這題會很有幫助

IV 指標 Pointer

直接針對記憶體操作

0x00 0x01 0x02 0x03 0x04 0x05
0x06 0x07 0x08 0x09 0x0a 0x0b

我們平常對變數做的事 be like...

  • 這是一段記憶體,至少假裝它是。
int i = 0;

i

0

  • 電腦找到了一段可以用的記憶體,標記那格為 i,且賦值其為 0
  • 此時,0x00 就是變數 i 的 位置
int j = 2;

j

2

  • 再抓一段記憶體,此例中是 0x01,給變數 j,且賦值為 2

事實上,記憶體編號不會那麼漂亮,而且 int 佔 32 bits。但我暫時不鳥它 :partying_face:

我們平常對變數做的事 be like...

i++;
j = i;
  • 先利用變數名稱 i,找到 0x00 後改變它的值

1

  • 同樣,找到 0x01 後,將其值設定得與 0x00 相同
0x00 0x01 0x02 0x03 0x04 0x05
0x06 0x07 0x08 0x09 0x0a 0x0b

i

1

j

2

變數名稱只是方便我們打 code

電腦還是以記憶體為主

指標 Pointer

  • 一種變數,永遠佔 8 bytes,無論它指向什麼
  • 指標絕對具備的 4 個要素(事實上每個變數都具備):

類別:同 所指變數 的類別

名字:就,這個指標的命名

:即 所指變數 的位置

位置:這個指標本體的所在,如前文所提,佔 8 bytes

  • 值本身是一段記憶體位置,會繼承該位置變數的所有要素

"指標就像一隻寄生蟲,會指向一個變數,寄生在它身上。        擁有該變數的所有特性,共享一副身體。

    任何一方受到傷害,都會連累另一個人"

- 對,阿蘇剛剛唬爛出來的

指標 Pointer

  • 前面的 * 沒其他意思,僅代表 這是一個指標
  • 後面的 & 在此為 取址符號,可取出變數的位置

> 宣告一個指標叫 num_ptr,值設為 num 的位置!

  • 然後呢?這隻寄生蟲與宿主間有什麼聯繫?
  • 如何宣告一個指標:

語法

[指標的類別] *[指標命名] = &[指向的變數名字]

int num = 5;
int *num_ptr = &num;

指標 Pointer

  • 取得這個指標等於多少
int num = 5;
int *num_ptr = &num;

語法

*[指標名稱]

cout << *num_ptr << '\n'; //5
  • 如果我更改所指變數的值,或直接從指標改它?
num += 5;
*num_ptr += 5

or

  cout << *num_ptr << ' ' << num << '\n'; // 10 10

Cuz 指標是直接 指向位置

也是直接更改 所指位置 的數字

Array 本身其實就是 Pointer ㄛ

  • Array 實際上是一段相連的記憶體
int arr[10];
0x08 0x09 0x0a 0x0b 0x0c
0x0d 0x0e 0x0f 0x10 0x11

arr[0]

arr[1]

arr[2]

arr[3]

arr[4]

arr[5]

arr[6]

arr[7]

arr[8]

arr[9]

* 為求方便,所有記憶體位置都是假設ㄉ,且令 int 只佔 1 bit

  • 如果只打 array 的名稱,完全不加中括號,                                        則它與一個指向 [0] 的 pointer 等價
int arr[10] = {};
int *arr_ptr = &arr[0];
cout << arr << ' ' << arr_ptr << '\n';
// 別忘了指標本身的值是記憶體位置ㄛ,我並沒有加 *

output :

0x08 0x08

Array 本身其實就是 Pointer ㄛ

  • btw,我們可以利用 + 與 - 來使陣列的 指標平移
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
printf("%p %p %p\n", arr, arr+1, arr+2); // %p 就是直接印出指標的值
printf("%d %d %d\n", *arr, *arr+1, *arr+2);
0x08 0x09 0x0a 0x0b 0x0c
0x0d 0x0e 0x0f 0x10 0x11

arr[0]

arr[1]

arr[2]

arr[3]

arr[4]

arr[5]

arr[6]

arr[7]

arr[8]

arr[9]

* 事實上,每次平移應該會跳一個 int 的大小,也就是 32 格,aka 4 bytes

output :

0x08 0x09 0x10

1 2 3

  • 如果要 複製 array,只要創造一個指向 [0] 的 pointer 就好了
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int err[10] = arr;

這樣會 Complie Error

int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *err = arr;

正確做法

"所以 Pointer 實際上有什麼用?

    剛剛的狀況看起來都沒什麼價值啊"

喔對啊,剛剛的狀況的確不太會用到

至少我到現在

還沒遇過半題,會需要開指向一般變數的 pointer

  • 當指標碰上 struct...
  • 當指標碰上 STL...
  • 當指標碰上 Graph Theory....

指標的概念很重要

等上面那些酷東西進來後,你會很感謝自己的

就算現階段比較難應用

又是來自資訊毒芽ㄉ(NEOJ)

請看清楚提敘,乖乖照著規定做

否則根本過不了 (。・∀・)ノ゙

跟上一題超級像

我甚至不記得我當年在資芽

有寫過這一題

所以顯然很水

V 參考 Reference 

永久更改 function 中的傳入值

參考 reference

  • 參考:一種比 pointer 更寄生的變數型態                           自從宣告後 所有要素都會與宿主等價 (包含記憶體) 

宣告方法

[變數型態] &[參考命名] = [宿主名稱]

  • 必須一次完成宣告,等號右邊 不可省略
  • 這邊的 & 沒其他意思,僅代表 此變數是一個參考
  • 宣告後,用法與一般變數 完全相同
int b = 5; //令其儲存在 0xff
int &a = b; // a 的型態是 int&,aka 參考,寄生在 b 上面
cout << a; //輸出 a 的值
cout << &a; //對 a 取址

output:5

output:0xff

此時 a、b 完全等價

& *
用於宣告 這是一個 參考 這是一個 指標
其他時候 取址符號 取值符號

[ 用法比較,不要搞混否則會出事 ]

Pointer v.s Reference

int a = 0;
int b = 5;
infor
pos 0x01 0x02

a

b

0

5

c

0x01

0x03

int *c = &a;
int &d = b;

d

cout << c << '\n';  //0x01
cout << &c << '\n'; //0x03
cout << d << '\n'; //5
cout << &d << '\n'; //0x02
cout << *c << '\n';  //0
cout << *d << '\n'; //Compile Error

L1:* 是宣告指標,& 是取址

L2:& 是宣告參考

全部的 & 都是取址

L1:* 是取所指變數的值

L2:* 會讓你扣爛掉

變數生命週期

  • 區域變數:開在 function(包含 main)、for/whileif/else                      等地方的變數,作用範圍只在 兩個大括弧內
  • 全域變數:直接開在外面的變數,作用範圍包含 整份 code

btw,在全域 array 的上限會提高一些

  • 範圍重疊:當兩 名稱相同、作用範圍不同 的變數衝突時,系統       會以 作用範圍小 的為主
int num = 0; //全域變數,作用範圍是整份 code

int main (){
  int num = 2; //區域變數,作用範圍是 main() 裡面
  cout << num; // 2
}
  • 形參?實參?

Bruh,我才不要用此類文謅謅的詞來解釋這種簡單語法

來做個小實驗ㄅ

void PlusOne (int num){
  num++;
  cout << "In function, n = " << num << '\n';
}
int main (){
  int n = 0;
  cout << "Before function, num = " << n << '\n';
  PlusOne(n);
  cout << "After function, n = " << n << '\n';
}

output:

Before function, n = 0

In function, num = 1

After function, n = 0

  • 在 function 中的確有加到,為何出來卻有跟沒有一樣?

廢話,因為 num 的作用範圍 只在 PlusOne 裡面

  • 解決方法:改成傳入參考進去!
void PlusOne (int &num){
  num++;
  cout << "In function, n = " << num << '\n';
}
int main (){
  int n = 0;
  cout << "Before function, num = " << n << '\n';
  PlusOne(n);
  cout << "After function, n = " << n << '\n';
}

output:

Before function, n = 0

In function, num = 1

After function, n = 1

我只有動第 1 行

  • 此時,num 會直接與傳入值 等價
  • 事實上,你只要加個 &,其他用法都 跟一般參數相同
  • 無論你做什麼操作,都能 直接反映 在傳入的變數身上
  • 上次田鼠不是很緊張地在寫 swap() 嗎,那也是參考的應用

還是我現場再寫一份出來

  • 截至目前所學,只有 array 本身就是指標可以不用加
void reverse (vector <int> &vec){
  vector <int> tmp = vec;
  for (int i = 0; i < vec.size(); i++) vec[i] = tmp[vec.size()-1-i];
}
void reverse (int arr[], int length){ //你現在知道 array 是指標ㄌ
  *tmp = arr;
  for (int i = 0; i < length; i++) arr[i] = tmp[length-1-i];
}

喔,By the way...

現在我來 鞭屍 了,因為有人 簡報寫錯   ╮(╯_╰)╭

  • 第 9 行會爛掉,C++ 只會幫你補 左邊的中括弧,右邊必須 給定值
int h (int y[][11])
  • 順帶一提,int **y 是一個 指向指標的指標,但真的很少用到
  • 第 10 行會爛掉,C++ 無法判斷 指標陣列 的大小,而且 *y 要加 小括號
int h (int (*y)[11])

\倒數 10 天了/

  • 地點鬼轉成 二二八和平公園

這樣就夠了

我再多講下去

Ivan Lo 又要說我在噁別人

  • 烤肉店鬼轉成 夯肉殿

因為原本那家倒了,有夠瞎

  • 報名費不變,還是 $ 800

總務要哭出來了

真的不考慮現在交嗎

SOURCE

SOURCE

SOURCE

我要給 ㄘㄇㄏ 一個

屬於他的版面

建北小社_algorithm 03 雜七雜八、遞迴、指標、struct、參考

By repkironca

建北小社_algorithm 03 雜七雜八、遞迴、指標、struct、參考

  • 537