【程式設計】第一講:Introduction === # Outline **- Computer Programming** **- Our first C++ program: compile & run** **- Our first C++ program: structure** **- Escape sequences** **- Variables and data types** **- Assignment operator** **- cin** **- if and while statement** **- syntax and logic errors** **- Formatting a C++ program** ## Computer Programming 什麼是 <font color="#9D33FF">**Computer Programming**</font> ? 程式是什麼 ? 基本上就是電腦裡面運作的元件 <font color="#9D33FF">**\(element\)**</font>,很多時候我們也稱呼它為<font color="#9D33FF">**軟體**</font>,相對於看得見的硬體,軟體通常顯得比較抽象,如果能結構化的組合資料和指令並且透過這個組合,讓電腦產生我們想要的結果的話,就可以稱為是一個程式。 所以這裡的重點是電腦把資料以及指令組合起來,給電腦一些可以運算的素材並且告訴它要算什麼要怎麼算,這樣就是程式設計。 寫程式的理由是因為電腦處理運算的速度較快,因為電腦有大量的記憶體這是人所做不到的 目前為止的缺點為電腦不知道自己要做什麼,程式設計師的任務就是必須要告訴電腦應該要怎樣做。 程式設計師與電腦要如何溝通,程式設計師使用 <font color="#9D33FF">**Programming Language**</font>,寫程式語言或是講程式語言基本上就是一行一行的把程式碼寫下來,然後來組成我們的電腦程式,執行一個程式有時候叫 <font color="#9D33FF">**Running a Program**</font> 或 <font color="#9D33FF">**Executing a Program**</font>,基本上就是一行一行的執行指令,並且最後得到我們想要的結果。 程式語言分為至少三大類,<font color="#9D33FF">**Machine Language**</font>、<font color="#9D33FF">**Assembly Language**</font> 以及 <font color="#9D33FF">**High-Level Language**</font>,機器語言 (Machine Language) 和組合語言 (Assembly Language) 基本上就是直接控制硬體,根據不同型態的硬體,比如說 PC 或者是 Mac 硬體的結構如果不一樣,需要的組合語言和機器語言也就不一樣,不過由於可讀性差且不好編程,通常會去寫高階語言,可讀性佳但需要 translator 做轉譯的動作,絕大部份的 Application Software 都是用高階語言寫的,在 C++ 的世界裡我們使用編譯器 <font color="#9D33FF">**compiler**</font> 進行 translate 的動作轉換成 Assembly Language,有些其它的高階語言用的是 interpreter 也就是直譯器。 C++ 是從 C 語言開發出來的,差別在於 C 語言是一個 procedural programming language 也就是程序式的語言,程式為一個一個的 procedure,每個 procedure 可以解決一個小任務然後把所有的 procedure 組合在一起就可以解決整個問題,C++ 則是一個 <font color="#9D33FF">**object-oriented programming language (OOP)**</font> 物件導向的程式語言,物件導向的概念是想像程式裡有許多的 entity,每一個 entity 就是一個物件,藉由建立許多的物件並且定義它們之間會有什麼互動來達成所謂的物件導向。 C++ 就是把物件導向的概念加入至C語言內,因為可以用於一群人花費長時間去開發一個大型的系統。 ## Our first C++ program: compile & run ```cpp= #include <iostream> using namespace std; int main() { cout << "Hello World! \n"; return 0; } ``` ## Our first C++ program: structure 以剛剛的程式為範例可以被拆成四個部份 1. <font color="#9D33FF">**The preprocessor**</font> 1. <font color="#9D33FF">**The namespace**</font> 1. <font color="#9D33FF">**The main function block**</font> 1. <font color="#9D33FF">**The statements**</font> ```cpp= #include <iostream> // 1.preprocessor 前置處理器 using namespace std; // 2.namespace 命名空間 int main() // 3.The main function block 程式從這行開始 { cout << "Hello World! \n"; // 4.Statements、cout (console output) and << (insertion operator) return 0; } // 3.The main function block 程式到這行結束 ``` 從上面的程式碼範例可以看出有一些字會以不同的顏色標註,這些字為 C++ 的保留字 <font color="#9D33FF">**\(reserved words、keywords\)**</font>,有著特殊的用途。 ```cpp= #include <iostream> using namespace std; ``` 開頭這兩行就是所謂的 <font color="#9D33FF">**The preprocessor**</font> 和 <font color="#9D33FF">**The namespace**</font>,事實上 preprocessor 就稱為前置處理器,namespace 稱為命名空間,這兩行基本上就是做一些前置工作,先將環境 setup 好使 program 可以執行。 ```cpp= int main() { cout << "Hello World \n"; return 0; } ``` <font color="#9D33FF">**The main function block**</font> 就是表示當編譯並且產生執行檔的時候要從哪裡開始執行,程式的起點就是 <font color="#9D33FF">**main function**</font>,這裡提到了一個概念稱為函數,函數的概念就是有一個 <font color="#9D33FF">**Component**</font> 裡面有許多行的程式碼,一次執行這個 Component 就會產生某一種結果這樣就稱為一個 function,program 裡面 main function 負責程式從這一行開始往下執行到某個地方結束,標示的程式的開始和結束且過程中可能會去呼叫別的函數或是跑去別的地方,因為標示著程式的開始和結束所以一個程式一定只會有一個 main function,從 "{" 到下個 "}" 這一對大括號 <font color="#9D33FF">**{} (curly brackets)**</font> 為這個函數的範圍,如果作業系統在執行執行檔的時候看到 <font color="#9D33FF">**return 0;**</font> 就會告訴你這個程式已經運作完成。 <font color="#9D33FF">**Statement**</font> 就是敘述,在程式碼裡面寫下一行又一行敘述然後每一個敘述會做一些事情,return 0; 本身也是一個敘述,程式在執行的時候會以 Statement 為單位依序執行每個 Statement, 在 C++ 裡面每一個 Statement 都會用一個分號 (;) 來做結尾。 ```cpp cout << "Hello World \n"; ``` 這個 Statement 裡面的 <font color="#9D33FF">**cout**</font> 是C++ 裡面一個 pre-defined 的物件,意思是系統已經把它當成是標準配備,只要安裝 C++ 的編譯或是編譯環境的話,那麼電腦裡就認得 cout,cout 就是 console output 意思就是要把運算的結果往哪個地方呈現出來,而電腦的 console output 就是將資料印在螢幕上,cout 這個物件基本上就是傳給它什麼資料它就會把它丟到標準顯示裝置,cout 後面接的 <font color="#9D33FF">**<< \(The insertion operator\)**</font> 就是標示著資料流的方向,把一個東西流進 console output 裡面,這裡的 cout 把它想成是螢幕,把資料沿著由右往左的方向流到螢幕上 <font color="#9D33FF">**\(Data "flow" like stream\)**</font>,"Hello World \n" 的雙引號裡面的東西是一個字串 <font color="#9D33FF">**\(string\)**</font>,用雙引號 <font color="#9D33FF">**" " \(double quotation marks\)**</font> 包著一系列的字元,它們就會依序被排好組成一個字串再把組成字串的字元一個一個的依序丟到螢幕上。 ## Escape sequences ```cpp cout << "Hello World \n"; ``` <font color="#9D33FF">**\n**</font> 它的用途就是一個標記特殊符號,反斜線 <font color="#9D33FF">**\\ (slash symbol)**</font> 為一個特殊符號,代表後面是一個跳脫字元 <font color="#9D33FF">**escape sequence**</font>,跳脫字元為一個特殊字元這個字元符號是鍵盤上看不到的,在鍵盤上按一下 Enter 游標會跳到下一行,並不會真的看到換行符號,但電腦裡必須儲存所謂的換行符號,假設使用筆記本或 Word 檔隔天打開電腦換行的地方還是會存在,所以電腦裡勢必有把在這裡換行的這個動作用某個方式儲存起來,就是所謂的跳脫字元,電腦裡所有的東西都是有編碼的,換行也有所謂的換行字元 <font color="#9D33FF">**newline character \n**</font> 在系統裡面有一個編碼,電腦才知道當資料顯示在螢幕上時看到這個換行符號就要進行換行的動作。 ```cpp= #include <iostream> using namespace std; int main() { cout << "Hello world! \n"; cout << "I love C++\n so much! \n"; return 0; } ``` **執行出來的結果就會如下圖所示,該換行的地方就會換行 :** ![escape sequence](https://i.imgur.com/VGMedPB.png) **跳脫字元有很多個,一些比較常見的用法如下表所示 :** | Escape sequence | Effect | Escape sequence | Effect | |:------ |:----------- |:------ |:----------- | | \n | A new line | \\\ | A slash: \ | | \t | A horizontal tab | \\' | A single quotation: ' | | \b | A backspace | \\" | A double quotation: " | | \a | A sound of alert | ```cpp cout << "Hello world! \\n"; // 會打印\n出來而不會換行 cout << "I love C++\n so much! \n"; ``` **執行出來的結果就會如下圖所示,會打印 \n 出來而不會換行:** ![\\](https://i.imgur.com/YM7t0l3.png) ```cpp cout << "Hello world! \'n"; // 會打印'n出來而不會換行 cout << "I love C++\n so much! \n"; ``` **執行出來的結果就會如下圖所示,會打印 'n 出來而不會換行:** ![\'](https://i.imgur.com/KH3uNT9.png) ```cpp cout << "Hello world! \"n"; // 會打印"n出來而不會換行 cout << "I love C++\n so much! \n"; ``` **執行出來的結果就會如下圖所示,會打印 "n 出來而不會換行:** ![\"](https://i.imgur.com/UpJeWZ8.png) The insertion operator << 可以串聯複數個 data stream <font color="#9D33FF">**\(Concatenated data streams\)**</font>,也就是說如果有一批資料想讓它流進螢幕,另一批資料也想讓它流進螢幕的話,可以用 << 把它們串起來。 **如範例所示 "Hello World! \n" 會先流進螢幕而 "I love C++\n so much!" 會接著流進螢幕:** ```cpp // The two statements cout << "Hello World! \n"; cout << "I love C++\n so much! \n"; // and this statement cout << "Hello World! \n" << "I love C++\n so much!"; // These two statements are display the same thing ``` **兩種 Statement 寫法所執行出來的結果是相同的:** ![Concatenated data streams](https://i.imgur.com/XDp3ANh.png) **下面的程式為錯誤的範例C++ 的語法有規定 cout 必須要放在字串的左邊:** ```cpp // Note that the statement is wrong! "Hello World!" >> cout; ``` ## Variables and data types **cout** 就是 console output 電腦的 console output 就是將資料印在螢幕上,要使用跟 cout 相對應的東西叫 **cin**,要來 <font color="#9D33FF">**input**</font> 資料,過程中會需要變數,cin 為另一個 C++ 已經幫我們準備好讓我們跟程式互動所 pre-defined 的物件,大部份是用它來從鍵盤 (typically the keyboard) 輸入資料 (console input),如果要使用 cin 物件的話我們要做的事情就是我們會打一些字把一些 value 傳給程式,value 一定要有地方存所以我們需要 <font color="#9D33FF">**container**</font> 這在程式語言的世界裡指的就是要宣告變數 <font color="#9D33FF">**(variable)**</font> 的意思,如果宣告了一個變數以後,那變數就可以用來存這些 value,**cin >>** 想成從鍵盤輸入一些資料到變數裡面,而 **cout <<** 想成從螢幕流出來要顯示的東西。 ```cpp cin >> variable; cout << "word" ``` 變數是用來存取 value 用的容器,在電腦裡面一但宣告一個變數以後它就會去跟作業系統要記憶體空間 <font color="#9D33FF">**(system allocates a memory space)**</font>,讓我有空間來存放輸入進來的資料,每一個 program 都會佔據記憶體一塊空間,所以多宣告變數它就會多耗記憶體空間。 C++ 裡面每一個變數都一定要有一個被指定的資料型態,容器有大小跟形狀之分,存 value 用的變數所佔的記憶體空間也是一樣,宣告資料型態了以後電腦才知道這個資料型態裡面是要裝什麼,電腦才知道它應該要如何分配記憶體空間以及如何解讀存放在裡面的那一堆 0 跟 1,因為電腦是二進位制所以所有的東西都是以 0 和 1 的形式去儲存,如果變數的型態不知道的話,電腦還要花時間去判斷會變成效能很差花費時間,所以 C++ 要求一定要宣告資料型態,除了對變數本身有影響以外,它還會影響對變數做運算的時候會去怎麼樣子做運算<font color="#9D33FF"> **(operations)**</font>。 所以一個變數必須有四個資訊: - Type 要知道變數的型態 - Name 幫變數取名字之後才能用 - Value 變數是存值的所以裡面一定會有值 - Address 變數被放在記憶體的哪個位址 C++ 裡面有十種基本的資料型態 <font color="#9D33FF">**(built-in on primitive)**</font>,它是 C++ standard 裡面所提供的東西: | Category | Type | Bytes | Type | Bytes | |:------ |:----- |:------|:----- |:----- | | Integers | bool (是或否0或1) | 1 | long | 4 | | Integers | char | 1 | unsigned int | 4 | | Integers | int (整數) | 4 | unsigned short | 2 | | Integers | short | 2 | unsigned long | 4 | | Fractional numbers | float | 4 | double | 8 | 型態不同需要記憶體的空間大小也就不同,用多少 byte 是跟編譯器有關 <font color="#9D33FF">**\(compiler-dependent\)**</font>,compiler 會去跟作業系統要空間,且 compiler 一定程度上有一些自由可以決定要多少記憶體空間。 **在我們使用變數之前必須先做宣告的動作,宣告變數的語法為以下所示:** 將它的 type 寫在前面變數的名字寫在後面,也就是先宣告 <font color="#9D33FF">**data type**</font> 再宣告變數的名稱 <font color="#9D33FF">**name**</font> 中間用一個空白鍵隔開就知道左右各是什麼。 ```cpp type variable name; ``` **For example:** 宣告一個名為 myInt 的整數變數。 ```cpp int myInt; ``` 所以執行了這行 Statement 之後,在電腦記憶體空間的某處電腦就會配置一塊記憶體空間位址給我們使用,電腦會記住存在這個記憶體位址上的變數叫做 **myInt**,但還不知道它的值,因為我們還沒有 assign value 給它,每當執行一次宣告的 statement 記憶體就會開一塊空間給我們使用。 | Address | Identifier | Value | |:----- |:----- |:----- | | 0x22fd4c | myInt | ??? (no initialization) | 所謂的變數名稱 <font color="#9D33FF">**(Variable name)**</font> 我們也稱它為識別字 <font color="#9D33FF">**(Identifier)**</font>,我只要記得變數叫什麼名字就好,系統自己會幫我去系統的記憶體位址上,找出一個正確的空間讓我來存取那上面的變數,作業系統裡面會有一張表紀錄每個變數存在哪個記憶體位址,當你跟系統說要某個變數它就會去幫你找變數在哪個記憶體位址以及裡面的值。 如果宣告變數可以得到一塊記憶體空間,當然得要能夠 <font color="#9D33FF">**assign value**</font> 給變數才行。 ```cpp int myInt; // declares an integer variable myInt = 10; // assigns 10 to myInt ``` 上面兩行是讓 myInt 變成 10 的意思,也可以說是 <font color="#9D33FF">**assign 10 to myInt**</font> 這個整數變數,本來記憶體位址的變數不知道是什麼值但做完 assignment 以後記憶體位址的變數值就會變 10。 | Address | Identifier | Value | |:----- |:----- |:----- | | 0x22fd4c | myInt | 10 | **一個 Statement 宣告變數跟指派變數的值可以一起做,語法如下:** ```cpp type variable name = initial value; ``` **For example:** 宣告一個名為 youInt 的整數變數,並且 assign 5 這個值指派給 youInt 這個整數變數: ```cpp int yourInt = 5; // declares an integer ``` yourInt 就會在記憶體的某個位址生出來然後直接得到一個值,在宣告的時候同時做指派這個動作就稱為初始化 <font color="#9D33FF">**(initialization)**</font>: | Address | Identifier | Value | |:----- |:----- |:----- | | 0x20c648 | youInt | 5 | C++ 大部份的變數在宣告的時候它裡面的值是什麼都不是很確定,通常會是上次使用的值,也因為裡面存什麼值不確定,所以如果把這個值拿來使用的話會發生什麼也不知道,因此最好還是每一次要宣告的時候都順便做初始化,知道它是什麼值就先 assign 給它,不知道它是什麼值的話就 assign 0 這個值給它,來確保程式每次跑起來會是一樣的。 ## Assignment operator ```cpp myInt = 10; ``` 在考慮這個 statement 的時候,我們使用了<font color="#9D33FF">**指派運算子 (assignment operator)**</font> 也就是這個等號 <font color="#9D33FF">**" = "**</font>,它可以把 10 這個數字 assign 給 myInt 這個變數,myInt 裡面就會裝著 10 這個值,我們稱它是一個 <font color="#9D33FF">**assignment operation**</font>,因為這一個 operation 做了一件事情,一個 statement 裡面可能有很多 operation,比如 declare 和 assign,operation 是運算的最小單位,一般來說 operation 裡面有所謂的<font color="#9D33FF">**運算子 (operators)**</font> 和運算元 <font color="#9D33FF">**(operands)**</font>,通常邏輯就是當有一個 operator 的時候: **(1) 會拿一個或數個 operands 來當作運算的 input。** **(2) 然後會對這些 operands 做一些事情。** **(3) 並且在最後會回傳一個值。** <font color="#9D33FF">**它本質上跟函數式很像,因為函數就是塞東西給一個函數它作一些運算最後跑結果出來**</font> 所以對 assignment operation 來說發生的事情是會存在兩個 operands,第一個是一個 variable 第二個是一個 value,在程式設計的語言裡面我們會稱 operator 左邊的叫做 <font color="#9D33FF">**L value**</font> 右邊的叫 <font color="#9D33FF">**R value**</font>,assignment operation input 兩個 operands 以後 operand 本身可能會發生變化,左邊的 variable 變成右邊的 value,也就是 variable 本身發生變化,最後是 assign 的 value 會被 <font color="#9D33FF">**return**</font>,如果 assign 8 那它就會回傳 8 給這個系統給這個程式。 **變數宣告 (Variable declaration)** 我們可以在一個 statement 裡面宣告數個 variable 比如像下面這樣用逗點隔開的話就會一次宣告三個整數 a、b 和 c : ```cpp int a, b, c; ``` 或者是我們可以在一個 statement 裡面一次把它全部都初始化,如果想要初始化成不同的值就要像下面這樣寫 a = 1、b = 2、c = 3 : ```cpp int a = 1, b = 2, c = 3; ``` 變數名稱是有一些限制的,只能使用<font color="#9D33FF">**連續的英文字母、數字以及下底線符號 (" _ ")**</font>且<font color="#9D33FF">**開頭不能是數字**</font>,也不能跟C++ 的<font color="#9D33FF">**關鍵字 (keywords)**</font> 重複,然後<font color="#9D33FF">**大小寫 (case-sensitive)**</font> 是有區別的,如果可以的話請<font color="#9D33FF">**永遠都初始化所宣告的變數**</font>,不知道要給什麼值就給 0,取變數名稱的時候儘量取有意義的變數名稱,如果要取一個變數的名稱要讓它有用的話常常需要組合數個字,這時候建議<font color="#9D33FF">**每一個字的第一個字母都大寫,但是第一個字不要**</font>,比如像下面這樣: ```cpp int yardToInch = 12, avgGrade = 0, maxGrade = 100; ``` **第二個 C++ 的程式:** 先宣告兩個整數 num1、num2,並且分別初始化成 13 跟 4,接著會做 cout statement 先把兩個 operands 加起來,加出來的結果就是這個 operation 的 return value,這個 operation 跟 assignment 有點不同,assignment 會改到左邊 operands 的值,因為會被 assign 一個東西但是加法並不會改變 operand 的值,加法就是會單純 return 一個 value 而那個 value 就被拿來丟到螢幕上面去,也就是 cout statement (cout <<),於是我們就會在螢幕上看到 17。 ```cpp= #include <iostream> using namespace std; int main() { int num1 = 13, num2 = 4; cout << num1 + num2; return 0; } ``` **執行這個程式時系統裡面發生這些事:** | Address | Identifier | Value | |:----- |:----- |:----- | | 0x20c648 | num1 | 13 (declare & initialization) | | 0x22fd4c | num2 | 4 (declare & initialization) | | 0x20c630 | (no name) | 17 (Console) | **(1) 宣告一個整數,這個整數叫 num1 而且會被 assign 13 這個 value,在 0x20c648 這個記憶體位址。** **(2) 宣告一個整數,這個整數叫 num2 而且會被 assign 4 這個 value,在 0x22fd4c 這個記憶體位址。** **(3) num1 跟 num2 會被加起來,加起來的時候它會被暫時的存起來不需要有名字,沒取電腦自己也不需要因為這是一個暫時性的動作,於是就得到了 17 這個 value。** **(4) 最後做一個 cout 的 operation 然後 17 就會被印到螢幕也就是 console 上面。** ## cin **將剛剛所寫的第二個 C++ 的程式做美化,所謂美化的意思就是改變一下 output 讓它看起來好一點 :** ```cpp= #include <iostream> using namespace std; int main() { int num1 = 13, num2 = 4; cout << "The sum of " << num1 << " and " << num2 << " is " << num1 + num2 << "\n"; return 0; } ``` **執行出來的結果就會如下圖所示,The sum of 13 and 4 is 17** ![cout_fine_tune](https://i.imgur.com/57QbFgN.png) **除了加法<font color="#9D33FF"> **(Addition)** </font>以外還有除法<font color="#9D33FF"> **(Division)** </font>、減<font color="#9D33FF"> **(Subtraction)** </font>法、乘法<font color="#9D33FF"> **(Multiplication)** </font>及取餘數<font color="#9D33FF"> **(Modulus)** </font>可以做運算:** ```cpp= #include <iostream> using namespace std; int main() { int num1 = 13, num2 = 4; cout << num1 + num2 << "\n"; cout << num1 - num2 << "\n"; cout << num1 * num2 << "\n"; cout << num1 / num2 << "\n"; cout << num1 % num2 << "\n"; return 0; } ``` **執行出來的結果就會如下圖所示:** ![operator](https://i.imgur.com/f0u3nvH.png) <font color="#9D33FF">**資料型態**</font>會影響某些 operation 的結果,比如除法這個動作的左邊和右邊的 inputs 如果都是整數的話,那在做除法的時候就被設計為只要回傳商,也就是扣掉小數扣掉餘數的部份,回傳值不管是多少都會把它<font color="#9D33FF">**無條件捨去 (truncated)**</font> 成整數,所以本來 13 除以 4 應該是 3.XX 才對,但因為是整數相除所以只會有整數只回傳 3,如果今天左邊跟右邊的 inputs 並不都是整數型態而是有非整數的資料型態的話,就不會只回傳整數。 **完整的第二個 C++ 的程式 (含 cin):** ```cpp= #include <iostream> using namespace std; int main() { int num1 = 0, num2 = 0; cout << "Please enter one number: "; cin >> num1; cout << "Please enter another number: "; cin >> num2; cout << "The sum of " << num1 << " and " << num2 << " is " << num1 + num2 << "\n"; return 0; } ``` **執行這個程式時系統裡面發生這些事:** **(1) 先宣告兩個整數 num1 & num2,一開始沒有值就給它們初始化的值為 0。** **(2) cout statement 是所謂的<font color="#9D33FF">**提示語 (prompts)**</font>,輸入值完按 enter 的時候值才會被輸入到變數裡面。** **(3) 讓使用者輸入兩個整數並宣告兩個變數來吃它們,當我們使用 <font color="#9D33FF">**cin object**</font> 的時候 cin 會把從鍵盤輸入的資料丟到變數裡面。** **(4) 最後就會印出兩個變數相加的結果 (cout << "The sum is " << num1 + num2;)。** **The cin object** cin 是使用 <font color="#9D33FF">**extraction operator >>**</font> 它是相對於 <font color="#9D33FF">**insertion operator <<**</font>,我們在輸入資料的時候事實上可以一次輸入多筆資料,只要我們用 <font color="#9D33FF">**enter**</font> 或者用<font color="#9D33FF">**空白鍵**</font>把它們隔開它們自然就會被切開來,切開來的資料就會被送進不同的變數裡,還沒有地方裝的輸入資料就會被裝到一個 <font color="#9D33FF">**input buffer**</font> 去等待下一次看到 cin operation 的時候。 ```cpp= #include <iostream> using namespace std; int main() { int num1 = 0, num2 = 0; cout << "Please enter two numbers, separated by a white space: "; cin >> num1 >> num2; cout << "The sum of " << num1 << " and " << num2 << " is " << num1 + num2 << "\n"; return 0; } ``` ## if and while statement **第三個 C++ 的程式:** ```cpp= #include <iostream> using namespace std; int main() { int num1 = 0, num2 = 0; cout << "Please enter two numbers, " << "separated by a white space: "; cin >> num1 >> num2; if(num1 > num2) cout << "The larger one is "<< num1 << endl; // 如果num1大於num2就印出num1 if(num1 < num2) cout << "The larger one is "<< num2 << endl; // 如果num2大於num1就印出num2 if(num1 == num2) cout << "The two are equal" << endl; // 如果num2等於num1就印出兩個數相等 return 0; } ``` **執行這個程式時系統裡面發生這些事:** **(1) 先宣告兩個整數 num1 & num2,一開始沒有值就給它們初始化的值為 0**。 **(2) cout statement 是所謂的<font color="#9D33FF">**提示語 (prompts)**</font>,輸入值完按 enter 的時候值才會被輸入到變數裡面**。 **(3) 讓使用者輸入兩個整數並宣告兩個變數來吃它們,當我們使用 <font color="#9D33FF">**cin object**</font> 的時候 cin 會把從鍵盤輸入的資料丟到變數裡面**。 **(4) 如果第一個 number 比第二個 number 大就印出** <font color="#9D33FF">**"The larger one is num1"**</font>。 **(5) 如果第一個 number 比第二個 number 小就印出** <font color="#9D33FF">**"The larger one is num2"**</font>。 **(6) 如果第一個 number 跟第二個 number 相等就印出** <font color="#9D33FF">**"The two are equal"**</font>。 **我們使用 if statement 來控制程式執行的順序或是流程:** ```cpp= if(condition) { statements } ``` 以前寫的程式都是一行一行往下執行的,使用 if statement 我們可以跳過一些 statement,也就是我們可以根據 condition 來決定要執行哪個 statement,如果 condition <font color="#9D33FF">**成立 (true)**</font> 就會依序執行以下 statement 否則就跳過這些 statement。 **比較運算子 (The comparison operators)** 使用 <font color="#9D33FF">**" == "**</font> 來確認左右兩邊是否<font color="#9D33FF">**相等 (equal)**</font>,比較完之後會回傳一個<font color="#9D33FF">**布林值 (Boolean value)**</font>,布林值為一種資料型態裡面只存兩種可能性不是 <font color="#9D33FF">**true (non-zero)**</font> 就是 <font color="#9D33FF">**false (zreo)**</font>,所以也可以說它是一個 binary variable。 **" = " 和 " == " 是完全不同的兩個 operator:** 當使用一個等號 " = " 的時候在做的事情是 assignment,是把右邊的值 assign 給左邊然後回傳值。 當使用兩個等號 " == " 的時候我們是在比較左邊右邊是不是一樣大,這個時候會回傳的是 True 或 False。 要做比較的話要寫 " == " comparison 而不是 " = ",因為等號 (" = ") 是 assignment,要分辨清楚是<font color="#9D33FF">**變成 (become) 它**</font>還是<font color="#9D33FF">**等於 (equal) 它**</font>。 ```cpp= #include <iostream> using namespace std; int main() { int a = 0; if(a == 1) { cout << "here!"<< endl; } if(a = 1) { cout << "here!"<< endl; } if(a = 0) { cout << "here!" << endl; } return 0; } ``` 執行這個程式時系統裡面發生這些事: **(1) 因為int a = 0 所以 if (a == 1) 的 statement 就不會被執行,會被跳過。** **(2) 因為int a = 0 後面 if (a = 1) 會做的事情是 assignment,1 會被 assign 給 a 所以 a 的值會變成 1,而且會回傳 assign 進去的數字也就是回傳 1 給這個 statement,operation 如果回傳 1 的話,在布林值的世界裡 1 就是 true,所以 "here!" 這個 statement 就會被印出來。** **(3) 因為int a = 0 後面 if (a = 0) 會做的事情是 assignment,0 會被 assign 給 a 所以 a 的值就會變成 0,在布林值的世界裡 0 會被判定為 fail 這時候就不會執行 statement 了**。 **除了 " == " (equals) 以外以下的幾個運算子也都會回傳一個布林值:** |comparison operators|means |意義 | |:----- |:----- |:-----| |> | bigger than |大於 | |< | smaller than |小於 | |>= | not smaller than |不小於 | |<= | not bigger than |不大於 | |== | equals |等於 | |!= | not equals |不等於 | 在一個 if 的 block 裡面可以有<font color="#9D33FF">**好幾個 (multiple) statement**</font>,會用<font color="#9D33FF">**一對大括號 (curly brakets " { } ")**</font> 來標示這個 block 從哪裡到哪裡: ```cpp= int a = 0; if (a == 1) // return false { cout << "he" << endl; // statement 1 cout << "re!" << endl; // statement 2 } ``` 如果<font color="#9D33FF">**只有一個 (only one) statement**</font> 的時候<font color="#9D33FF">**可以不用加大括號 (" { } " could be drop)**</font>: ```cpp= int a = 0; if(a == 1) // return false cout << "here!" << endl; // only one statement {} could be drop ``` **如果有好幾個 statement 但是卻沒加大括號的話:** ```cpp= int a = 0; if(a == 1) // return false cout << "he" << endl; // statement of if, and Boolean value is false so it will skip cout << "re!" << endl; // it is not a statement of if so it will print out ``` 程式執行時會覺得以上兩行是同一個 block,所以當 a 不是 1 時,回傳的布林值也就不為 true 它就不會去執行 cout << "he" << endl;,但是程式會執行 cout << "re!" << endl; 雖然看起來跟 cout << "he" << endl; 是同一組的 statement 但程式執行時是看不出來的,程式執行時只會認大括號或著是只認下一個 statement,如果不加大括號給 if 的話,只認它的下一個 statement,但如果加了大括號給 if 的話它就可以認很多個 statement。 **將第三個 C++ 的程式改成 the while statement 的形式:** ```cpp= #include <iostream> using namespace std; int main() { int num1 = 0, num2 = 0; cout << "Please enter two numbers, " << "separated by a white space: "; cin >> num1 >> num2; while (num1 > num2) // 只要num1有比num2大它就會一直做 { cout << "number 1 is " << num1 << endl; num1 = num1 - 1; //num -= 1 } return 0; } ``` The while statement 語法如下,它會去檢查括號內的 condition 是不是<font color="#9D33FF">**成立 (true)**</font>,如果成立就繼續做然後再檢查一次直到它不成立為止: ```cpp= while(condition) { statements } ``` 使用 while statement 時它會一直<font color="#9D33FF">**重複做事情 (repeat several statements)**</font>,可以把 while 想成是一個會重新回來檢查的 if。 if 的話就是 condition 回傳布林值 true 就做,回傳布林值 false 就不做,不做就跳過去然後就結束,而 while 的話就是 condition 回傳布林值為 false 跳過去,如果回傳布林值為 true 就做完再回來檢查是不是,所以它就是一個會回頭檢查的 if。 **第三個 C++ 的程式執行出來的結果如下圖:** ![while statement](https://i.imgur.com/hMXZL6j.png) 剛剛在執行 num1 = num1 - 1; 的時候,第一個動作 num1 - 1 會先被算出來,之後再把算出來的值 assign 給等號左邊的 num1,所以它才會讓 while 迴圈可以正確運作。 **assignment operator " = ":** ```cpp= num1 = num1 - 1; ``` 它是一個很重要的東西,因為在這個 program 裡面如果不做這件事的話那麼 num1 就不會改變 num2 也不會改變,while (num1 > num2) 這個 condition 就會一直回傳布林值 false 如此一來這個 while statement 就會一直跑,這個情況下就會跑不出結果而得到無窮迴圈。 ```cpp= while(num1 > num2) // 只要num1有比num2大它就會一直做 { cout << "number 1 is " << num1 << endl; num1 = num1 - 1; //num -= 1 } ``` 所以可以得知以上的 program 執行時 num1 和 num2 會持續的被做比較來確認 num1 有沒有比 num2 大,只要 num1 比 num2 大就會把 num1 給印出來再執行 num1 - 1 讓 num1 變小一單位,然後 num1 和 num2 再做比較,一直到 num1 沒有大於 num2 時,程式就會自己跳出這個 while 迴圈不會繼續執行。 ## syntax and logic errors **語法錯誤 (Syntax Error)** <font color="#9D33FF">**語法錯誤 (syntax error)**</font> 就是當程式語言不符合程式的語法的時候就會發生,compiler 會偵測到錯誤。 ```cpp= if(num1 > num2) cout << ""The larger one is << num1 << endl; if(num1 < num2) cout << ""The larger one is " << num2 << endl ``` **邏輯錯誤 (Logic Error)** 程式能夠執行但是跑出來卻不是所預期的結果,compiler 不會知道有邏輯錯誤所以程式設計師必須要自己找出所有的邏輯錯誤讓程式能夠正確運作,這個過程就稱為 <font color="#9D33FF">**debugging**</font>。 ```cpp= if(num1 > num2) cout << "The larger one is " << num1 << endl; if(num1 < num2) cout << "The larger one is " << num1 << endl; ``` ## Formatting a C++ program 好的程式排版很重要,雖然寫出來的 code 是要寫給電腦的,但有非常多的時候是要給人看的<font color="#9D33FF">,**分號 (semicolons " ; ")**</font> 是我們用來標 statement 結束的地方,空白鍵、tab鍵、換行並不會影響<font color="#9D33FF">**編譯 (compilation)**</font> 及<font color="#9D33FF">**執行 (execution)**</font>,當有分號的時候就<font color="#9D33FF">**換行 (start a new line)**</font>,不要把兩個 statement 放在同一行,大括號應該要垂直的被<font color="#9D33FF">**對齊 (Align)**</font>,以下是兩個相等的程式,但排版方式不一樣表示同樣是一個相等的程式可以有不同的寫法,但一般會以第一種寫法來排版程式。 **好的程式排版:** ```cpp= #include <iostream> using namespace std; int main() { cout << "Hello World! \n"; return 0; } ``` **不好的程式排版:** ```cpp= #include <iostream> using namespace std; int main () {cout << "Hello World! \n";return 0;} ``` <font color="#9D33FF">**有一些基本的規則可以讓寫出來的程式碼排版好看:**</font> **Indentions (縮排)** 把 block 往右邊<font color="#9D33FF">**縮排 (Indent)**</font> 讓它們可以顯示出它們現在是屬於哪一個階層的,正常的編譯器當打一個大括號按 Enter 之後會自動幫忙做縮排的動作。 **正確有縮排的範例:** ```cpp= #include <iostream> using namespace std; int main() { int a = 5; if(a < 5) { cout < "..."; cout < "..."; } return 0; } ``` **無縮排的範例:** ```cpp= #include <iostream> using namespace std; int main() { int a = 5; if(a < 5) { cout < "..."; cout < "..."; } return 0; } ``` **Variable declaration (變數宣告)** 最好取<font color="#9D33FF">**有意義的名稱 (understandable names)**</font>,類似或是用途相近的變數<font color="#9D33FF">**在同一行 (in the same line)**</font>做宣告以便尋找或使用。 **有意義的變數名稱:** ```cpp= #include <iostream> using namesapce std; int main() { int dice1 = 0, dice2 = 0; int sum = 0; cin >> dice1 >> dice2; sum = dice1 + dice2; cout << sum << "\n"; return 0; } ``` **無意義的變數名稱:** ```cpp= #include <iostream> using namespace std; int main() { int a = 0, b = 0, c = 0; cin >> a >> b; c = a + b; cout << c << "\n"; return 0; } ``` **Write spaces and empty lines (空白鍵和空行)** 空白和空行通常能讓程式碼有比較好的視覺效果,當有Binary operator的時候就是加、減、乘、除、等號、比較之類的,在它們的<font color="#9D33FF">**左右各加一個空白鍵 (two white spaces)**</font>,如果有<font color="#9D33FF">**逗點 (comma)**</font> 在後面加空白鍵,如果有一組一組的程式的話,用<font color="#9D33FF">**空行 (empty line)**</font> 來區隔它們。 **Comment (註解)** <font color="#9D33FF">**註解 (Comment)**</font> 是在程式裡面可以寫一些<font color="#9D33FF">**筆記 (notes)**</font>,自己或別人可以看但程式執行時會選擇忽略,在C++ 裡面有兩種寫註解的方式,如果有某一行你希望從某個字開始後面都是註解的話就在那行打 <font color="#9D33FF">**" // "**</font>,後面可以註明這行在做什麼,如果想用一排註解的話就可以用 <font color="#9D33FF">**" /* */ "**</font> 中間放多排註解。