基礎C語言
開發環境設定
C語言的編譯器是gcc或是clang。
開始前,先使用gcc --version檢查之前是否已經安裝過環境。如果出現錯誤,再進行下方的教學。
info
如果設定過了,可以直接跳到下面的教學
windows(以MinGW舉例)
也可以看vscode的教學
會透過MSYS2安裝MinGW。
從這裡下載MinGW的exe安裝檔,或是自己到MSYS2官網下載
之後執行這個exe檔,照著安裝精靈的指示安裝(總之一直點確認就可以了,可以把安裝位置改成自己想要的位置)
完成後勾選Run MSYS2就可以在點擊Finish後自動開啟一個終端機。(沒勾選就去搜尋MSYS2 CLANG64然後開啟他)
在這個終端機內執行以下指令:
1 | pacman -S --needed base-devel mingw-w64-ucrt-x86_64-toolchain |
出現Enter a selection (default=all)時直接按enter,不用輸入內容。
之後有任何提示就輸入y,然後按enter。
安裝完成後要去修改環境變數。
在windows搜尋欄輸入環境變數並開啟:
點擊環境變數:
點擊使用者變數的Path選項,然後按編輯:
點擊新增並把安裝MinGW的位置貼上,預設安裝會是C:\msys64\ucrt64\bin,但因為我在安裝時是設定安裝在D:\,所以我設定的位置會是C:\msys64\ucrt64\bin(總之就是你在安裝時選擇安裝在哪裡,就輸入什麼位置)。輸入完成後按確定。
之後就一直點擊確定來退出。
打開終端機輸入指令確認安裝是否成功:
1 | gcc --version |
成功會顯示以下內容:
1 | PS C:\Users\ben> gcc --version |
MacOS
安裝XCode(檔案大)或是Xcode Command Line Tools(檔案小)
以Xcode Command Line Tools舉例:
在終端機輸入以下指令:
1 | xcode-select --install |
如果沒有權限,在前面加上sudo:
1 | sudo xcode-select --install |
安裝後檢查是否安裝成功:
1 | gcc --version |
Debian 系列 Linux 發行版(如 Ubuntu)
透過apt安裝:
1 | sudo apt install gcc |
檢查安裝是否成功:
1 | gcc --version |
副檔名
C語言的副檔名為c,例如hello.c。
標頭檔
在開始時引入標頭檔(Header file),例如
stdio.hstring.hmath.h
引入的時機就是在需要使用這些標頭檔中所定義的函數或變數時。例如,當你需要使用輸入輸出功能時,就需要引入 stdio.h;當你需要進行字串處理時,就需要引入 string.h;當你需要進行數學運算時,就需要引入 math.h。
入口點函式main()
幾乎每個程式都會需要main()這個函式。他返回的數值通常是int,所以用int開頭。
程式的主要內容會寫在main()函式裡面。
1 | int main() { |
輸出與輸入
在C語言中,輸出使用函式 printf(),而輸入則使用函式 scanf()。
printf()函式
printf() 用於在終端輸出文字或變數的值。
範例: 輸出文字
1 |
|
執行後會在終端顯示:hello world。
範例: 輸出變數值
要輸出變數的值,需要在格式字串中使用佔位符來指定變數型別,例如:
1 |
|
以上程式會將 age 的值插入到 %d 的位置,輸出結果為:你16歲。
scanf()函式
scanf() 用於從終端讀取輸入,並將輸入值儲存到指定變數中。
範例: 輸入數值
以下程式讀取使用者的年齡並輸出:
1 |
|
執行流程:
- 使用者會看到提示
請輸入你的年齡:。 - 使用者輸入數值後,
scanf()將數值儲存到變數age中。 - 輸出顯示輸入的年齡,例如:
你18歲。
變數
變數是用來儲存資料的命名儲存空間。
在 C 語言有幾種常用的變數型態:
| 型態 | 說明 | 範例值 |
|---|---|---|
int |
整數 | 42 |
char |
字元 | ‘a’ |
double |
雙精度浮點數 | 3.14159 |
float |
單精度浮點數 | 3.14 |
bool |
布林值,只有true(1)或false(0) | true(或是1) |
long |
長整數,範圍比 int 大 |
1234567890 |
long long |
更長整數,範圍比 long 大 |
9876543210 |
unsigned |
無符號整數,不會有負數,會加在整數型別前,例如 int。 |
42 |
範例:
1 | int number = 100; |
String
更詳細的內容請參閱W3schools的教學
C沒有內建的string變數(但其他程式語言通常會有),所以在創建字串變數時就需要使用char建立字元陣列來代替string。
例如:
1 | char hello[] = "hello world"; |
注意,一定要用雙引號 " ,不能用單引號 '
輸出字串時,要使用 %s 這個佔位符:
1 |
|
bool
C語言在C99之前並沒有內建bool這個型態的變數。不過你可以使用stdbool.h這個函式庫來加入bool變數。或是用_Bool這個型態(限C99和之後的版本)。
範例(不引入stdbool.h,限C99和之後的版本):
1 |
|
如果引入stdbool.h,就可以把bool的值使用true或false來代替1跟0:
1 |
|
佔位符
佔位符用在格式化輸出時,指定如何顯示變數的內容。例如,在C語言的printf函式中,我們使用不同的佔位符來表示變數的型態。這些佔位符可以指明數值的格式(如整數、小數點後的位數等)。
常見佔位符與資料型態:
| 資料型態 | 佔位符 | 說明 |
|---|---|---|
int |
%d |
帶符號的十進制整數 |
unsigned int |
%u |
無符號十進制整數 |
char |
%c |
單個字符 |
double |
%lf |
雙精度浮點數 |
float |
%f |
單精度浮點數(printf中會自動轉為double) |
bool |
%d |
布林值(0 表示false,1 表示true) |
long |
%ld |
長整數 |
unsigned long |
%lu |
無符號長整數 |
long long |
%lld |
長長整數 |
unsigned long long |
%llu |
無符號長長整數 |
short |
%hd |
短整數 |
unsigned short |
%hu |
無符號短整數 |
size_t |
%zu |
無符號大小型別,用於物件大小 |
int*(指標) |
%p |
指標地址,以十六進制表示 |
char*(字串) |
%s |
字串(以 null 結尾) |
範例:
1 |
|
輸出結果
1 | int: -123 |
浮點數精度控制:
- 可以用格式指定小數點位數,例如:
%.2f表示輸出小數點後兩位數的浮點數。
1 |
|
if else判斷式
用來做兩個值的判斷。
例如我有兩個變數,a和b:
1 | int a = 10; |
我想要判斷這兩者的值是否相同,這時就可以使用if。
if的判斷式會寫在他旁邊的括號裡面。
判斷時會使用比較運算子和邏輯運算子。以下是各種的比較運算子:
比較運算子
| 運算子 | 說明 | 舉例 |
|---|---|---|
== |
比較兩個數值是否相等 | a == b |
!= |
比較兩個數值是否不相等 | a != b |
> |
比較前項數值是否大於後項數值 | a > b |
< |
比較前項數值是否小於後項數值 | a < b |
>= |
比較前項數值是否大於而且等於後項數值 | a >= b |
>= |
比較前項數值是否小於而且等於後項數值 | a <= b |
範例:
1 | int a = 5, b = 3; |
邏輯運算子
各種邏輯運算子:
| 運算子 | 說明 | 舉例 |
|---|---|---|
&& |
檢查兩個條件是否都為 true |
a > b && a != b,當 a 大於 b 而且 a 也 不等於 b 時,結果才會是true(1) |
|| |
檢查兩個條件是否至少有一個為 true |
a > b || a == b,當 a 大於 b 或 a 等於 b 時,結果會是 true(1) |
! |
將條件結果取反,如果為 true 則變為 false,反之亦然 |
!(a > b),當 a 不大於 b 時,結果才會是 true(1) |
範例:
1 | int a = 5, b = 3; |
迴圈
分為for跟while兩種,for會在知道要重複執行幾次時使用,while是在不知道明確重複次數時使用。
for
for的基本語法為:
1 | for (初始變數; 判斷式; 遞增式) { |
在 for 迴圈的語法中,初始變數; 判斷式; 遞增式 分別代表:
- 初始變數 (Initialization) :設定迴圈開始時的初始條件,通常用來宣告或初始化控制變數,例如
int i = 0。 - 判斷式 (Condition) :每次迴圈執行前檢查的條件,若為
true則繼續執行,為false則結束迴圈。 - 遞增式 (Update) :在每次迴圈執行完後,對控制變數進行更新操作,例如
i++或i += 2。
範例:
1 | for (int i = 0; i < 5; i++) { |
- 初始變數:
int i = 0(設定起始值為 0)。 - 判斷式:
i < 5(當i小於 5 時執行迴圈)。 - 遞增式:
i++(每次迴圈結束後將i增加 1)。
while
while 迴圈的基本語法:
1 | while (條件式) { |
說明
- 條件式:在每次執行迴圈前檢查,當條件為
true時執行迴圈,為false則結束。 - 執行內容:條件成立時執行的程式碼。
範例
1 | int i = 0; |
- 初始值
i = 0在迴圈外設定。 - 每次檢查
i < 5,滿足條件則執行。 i++更新變數以避免無限迴圈。(因為如果不更新變數,輸出的內容會一直是0,就無法達成i < 5這個條件,就會形成無限迴圈)
巢狀迴圈
就是在一個迴圈內加入另一個迴圈。執行的順序會是最裡面的迴圈先執行,執行完成後才會輪到他外層的迴圈執行。
假如有一個三層的巢狀迴圈,那執行順序就會是第三層 -> 第二層 -> 第一層。
用九九乘法表舉例:
因為九九乘法表裡面有兩個會變動的數值 - 乘數跟被乘數,所以會用到兩層的for巢狀迴圈。
首先設定用來控制乘數的迴圈:
1 |
|
接下來設定顯示被乘數和結果的迴圈:
1 |
|
這會在終端機顯示以下內容:
1 | 1*1=1 1*2=2 1*3=3 1*4=4 1*5=5 1*6=6 1*7=7 1*8=8 1*9=9 |
break跟continue
break
break可以在迴圈達成某項條件時結束(跳出)這個迴圈。
例如在while迴圈,我想要在迴圈數到5的時候結束:
1 |
|
這個程式會顯示這些內容:
1 | 0 |
當i等於5時,break語句會跳出while迴圈,程式繼續執行迴圈後的程式碼。
continue
continue 可以在迴圈達成某項條件時跳過當前迴圈的剩餘部分,直接進入下一次迴圈。
例如在 for 迴圈中,我想要跳過數值為 3 的迴圈:
1 |
|
這個程式會顯示這些內容:
1 | 0 |
當i等於3時,continue語句會跳過本次迴圈的剩餘部分,直接進入下一次迴圈,程式繼續執行後面的迴圈。
陣列
陣列是一種資料結構,用來儲存多個相同型別的變數,並且可以通過索引來訪問每個元素。
要建立陣列,要定義資料類型和設定陣列名稱,然後在後面加一個[]。
1 | int number[] = {1, 2, 3, 4, 5}; |
陣列的排列是從0開始的,不是從1開始。
所以上面的number[]排列順序就是
1 | int number[] = {1, 2, 3, 4, 5}; |
如果需要使用陣列的某個內容,例如我想顯示陣列中的第3個數字:
1 |
|
如果要修改陣列的內容,就要用<陣列名稱[你要修改的某個內容]>,例如我要修改number[]的第3個內容,把它從4改成10:
1 | int number[] = {1, 2, 3, 4, 5}; |
這樣這個陣列現在就變成1, 2, 3, 10, 5了。
如果要把陣列的內容輸出出來,可以使用for迴圈。
1 |
|
多維陣列
就是在陣列裡放入其他的陣列。可以用$x$跟$y$或是表格來理解。例如我需要一個二維陣列:
1 | int m[3][5] = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}}; |
寫得好看一些:
1 | int m[3][5] = { |
如果要取用多維陣列中的某個數值,例如要顯示第2層陣列的第三個數值:
1 |
|
如果要顯示這個二維陣列中的所有內容,可以用巢狀的for迴圈:
1 |
|
三維陣列可以用$x,y,z$的方式來理解,因為三維陣列就是一個立體的圖形。
三維陣列在定義時會需要三個[],例如:
1 | int m[][][] |
以下面的範例來說,可以把第一個[]看成$y$,第二個[]看成$x$,第三個[]看成$z$。
1 |
|
可以理解成一個長3寬5,高度2的立方體。
如果要顯示這個陣列的內容,要用到3層的for巢狀迴圈:
1 |
|
函式
函式是用來封裝一段可以重複使用的程式碼,並且可以通過呼叫函式名稱來執行這段程式碼。
例如我想要顯示很多次10+10的結果,如果不使用函式會長這樣:
1 |
|
使用函式(在main()裡面輸入函式名稱+括號):
1 |
|
需要寫的程式碼變少了。
函式參數
在函式中使用變數的目的,是讓函式能夠接收輸入值(參數),並根據這些值進行計算或操作。
需要使用幾個參數,就新增幾個參數。例如我要三個參數:
1 | int add(int a, int b, int c) { |
如果要兩個:
1 | int add(int a, int b) { |
例如,你可以讓函式 add 接收兩個數字作為參數,然後計算它們的和,像這樣:
1 |
|
函式參數(parameters)
在定義函式時,括號內的變數(例如int a, int b)稱為參數。它們是函式的輸入值,必須在呼叫函式時提供具體的數值。函式呼叫(function call)
當你在main中呼叫add(10, 20)時,數值10和20分別賦值給a和b,函式會根據這些值進行計算。重複使用
現在add函式可以針對不同的輸入值計算和,不需要每次都重寫計算邏輯。
參數回傳
有時候,你可能希望函式不直接輸出,而是將結果傳回給使用者,讓使用者決定如何使用。這時就要使用 return。
例如:
1 |
|
回傳類型 int add(int a, int b) 的 int 要根據回傳值的類型修改。例如在上面範例的 add() 回傳的數值會是整數,也就是 int,所以在設定函式時就要寫 int。如果回傳的值是 double,那就要改成 double。
1 |
|
這樣這個函式就可以進行小數計算。