前言
C 語言是許多大專院校入門程式設計的必學程式語言也是一個通用型的程式語言,廣泛應用於嵌入式系統軟體、應用開發上,算是歷史悠久但又保持長青的程式語言。許多的程式語言或多或少都有借鏡 C 語言的設計思想與哲學,儘管如此若是在工作場合比較少使用 C 語言進行開發的話,時間一久就會容易生疏。偶爾適時複習一下編譯器和 C 語言的使用方式也是一種調劑身心的方式?本文就透過簡明 C 語言入門教學快速複習 C 語言語法的重要特性,方便讀者複習查詢使用。
環境設定
雖然我們只要使用文字編輯器(若不希望使用花枝招展的編輯器,使用 vim 就對了)即可撰寫 C 語言程式但由於 C 語言執行程式前需要先使用編譯器(compiler)進行編譯,若是使用 MacOS/Linux 使用者可以考慮使用 gcc
等工具進行編譯而 Windows 的使用者則可以考慮使用 Visual Studio Community 版本進行開發。關於 Visual Studio Community 安裝教學可以參考官方網站和Visual Studio Community 專案創建方式。以下將以 MacOS 搭配 gcc
為範例。
基本程式概論與結構
由於 C 語言可以操作更底層的元件,所以對於一些程式初學者來說 C 語言的進入門檻相對較高,但事實上只要能掌握 C 語言的核心重要觀念,其他的程式語言也能觸類旁通。
由於 C 語言為編譯式語言,所以我們執行前需要經過編譯:
- 撰寫程式 source file 原始檔(副檔名為
.c
檔案) - 將程式碼進行編譯成目的檔案(object file)
- 為目的檔案進行連結(link)
- 成為可執行程式
C 語言基本程式架構:
#include <stdio.h> // 註解:使用 printf 列印顯示結果函式所需的程式標頭檔
// main 程式進入點
int main() {
// 列印格式化內容
printf("Hello, world!\n");
// 回傳正常結束結果
return 0;
}
編譯程式(使用環境為 MacOS,-o
後面接編譯後檔案名稱):
$ gcc -o demo demo.c
執行程式:
$ ./demo
呈現結果:
Hello, world!
變數
變數(variable)在 C 語言中就像是放入值或是字串文字內容的箱子,可以將資料暫存在變數(記憶體)中,方便程式之後使用(一般沒有條件判斷和迴圈控制程式是由上往下執行)。
整數型態
除了 int 外,還有 unsigned int、long、unsigned long、short、unsigned short、char、unsigned char 等整數型態,不同型態使用的記憶體量會有所不同。
#include <stdio.h>
int main() {
// 宣告變數 number 為 integer 整數型態
int number;
// 給定變數內容
number = 100;
}
浮點數型態
主要有 float 和 double 型態,double 支援數值費為較廣,所需要記憶體空間較大。
#include <stdio.h>
int main() {
// 宣告變數 width 為 float 浮點數型態
float width;
// 給定變數內容
width = 100.5;
}
字元型態
char
可用於儲存 0-127 整數字元碼,所以也可以用為單一字元的儲存型態。
#include <stdio.h>
int main() {
// 宣告變數 single_char 為 char 整數型態,單引號將字元包起來
char single_char = 'C';
// %d 為整數格式,印出字元碼。\n 為換行符號
printf("%d\n", single_char);
// %d 為字元格式,印出字元
printf("%c\n", single_char);
}
字串型態
字串為字元的集合體,我們在使用時會使用 ""
雙引號包起來。字串最後會有一個空字串 \n
代表字串結束,會佔用一個記憶體空間。
#include <stdio.h>
int main() {
// 宣告變數 text 為 字串型態
char text[10] = "I love C";
printf("%s", text);
}
若在初始化後需要更改內容,則需要使用 strcpy()
函式,不能直接重新指定值:
#include <stdio.h>
#include <string.h>
int main() {
char text[15] = "I love C";
printf("%s\n", text);
strcpy(text, "I love Python");
printf("%s\n", text);
}
位元與位元組
當電腦在處理資料時是使用 0 和 1 來表示電源的開關狀態。而這個代表 0 或 1 資料的儲存最小單為就稱為位元(bit)。一般我們會使用位元組(byte)來當作單位的換算基準,8 個位元代表 1 個位元組(byte)。
型別轉換
若是需要將值或變數型別轉換成特定型別可以在值或變數前面括弧 (型別)
就可以將其轉為特定型別。
#include <stdio.h>
int main() {
float num = 1.5;
printf("%d\n", (int)num);
}
運算子
賦值運算子
在 C 語言中 =
為賦值,給定值給變數暫存。
#include <stdio.h>
int main() {
int num = 15;
printf("%d\n", num);
}
遞增/遞減運算子
遞增運算子:
#include <stdio.h>
int main() {
int num = 15;
num += 1; // 等同於 num = num + 1
printf("%d\n", num);
}
遞減運算子:
#include <stdio.h>
int main() {
int num = 15;
num -= 1 // 等同於 num = num - 1
printf("%d\n", num);
}
比較運算子
透過 >
、<
、>=
、<=
和 ==
可以比較數值的大小並回傳結果。
#include <stdio.h>
int main() {
int num_1 = 15;
int num_2 = 10;
printf("%d\n", num_1 > num_2);
}
邏輯運算子
使用 &&
且,||
或,以及 !
否來進行邏輯運算的操作,方便進行條件控制判斷。
// x 大等於 100 且 x 小於 500
(x >= 100) && (x < 500)
// x 大等於 100 或 x 小於 500
(x >= 100) || (x < 500)
int x = 10;
// ! 表示相反結果
!(x >= 100)
條件判斷
if...else 條件判斷
if 條件判斷是讓我們的程式隨著條件不同而執行不同的程式區塊。
#include <stdio.h>
int main() {
int age = 18;
if (age > 20) {
printf("可以投票");
} else {
printf("小朋友還未成年");
}
}
switch 判斷
根據不同狀況進入不同的程式區塊。
#include <stdio.h>
int main() {
// 接收使用者輸入字元
char input = getchar();
switch (input) {
case '1':
printf("first one");
break;
case '7':
printf("lucky 7");
break;
default:
printf("other number");
}
}
迴圈
for 迴圈
給定一定條件下不斷執行程式區塊(可以搭配使用 break
、continue
):
#include <stdio.h>
int main() {
int result = 0;
// 累加 1...10
for (int i = 1; i <= 10; i++) {
result += i;
}
printf("result: %d", result);
}
while 迴圈
若條件符合不斷重複執行某個程式區塊,要注意避免無窮迴圈(可以搭配使用 break
、continue
)。
#include <stdio.h>
int main() {
int result = 0;
int i = 0;
// 累加 1...10
while (i <= 10) {
result += i;
i++;
}
printf("result: %d", result);
}
do...while 迴圈
與 while 迴圈相比,do while 因為條件判斷寫在下方,所以至少會先執行一次程式區塊(可以搭配使用 break
、continue
)。
#include <stdio.h>
int main() {
int result = 0;
int i = 1;
// 累加 1...10
do {
result += i;
i++;
} while (i < 0);
printf("result: %d", result);
}
陣列
陣列的用途在於將多個相同型別的變數值可以整合在一個資料結構中,方便管理大量的變數資料。
#include <stdio.h>
int main() {
// 宣告陣列變數型別和大小(可容納的元素數量)
int x[10];
// 陣列索引 index 從 0 開始
x[0] = 2;
x[1] = 3;
x[2] = 3;
x[3] = 0;
printf("%d", x[1]);
}
指標
指標是一個變數,內容是儲存記憶體位置。此外在動態配置記憶體時也可以很靈活使用。
#include <stdio.h>
int main() {
char x = 10;
char *pointer = &x; // 將 x 變數記憶體位置指定給 pointer 指標變數
char y = *pointer; // 將 pointer 指到的值給定給 y 變數
printf("取出指標值,也是 x 變數值: %d", y);
}
函式
函式(function)為一連串處理相關功能的程式集合。在函式內宣告的變數為區域變數(local variable)僅可以在函數內使用,在函數外宣告的為全域變數可以跨函數使用。
#include <stdio.h>
int global_num = 101;
int add_number(int x, int y) {
printf("global_num: %d\n", global_num);
return x + y;
}
int main() {
int result = add_number(10, 34);
printf("global_num: %d\n", global_num);
printf("result: %d\n", result);
}
struct 結構
struct 結構是一種可以讓多個型別變數整合在一個複合型的資料型別(有點類似陣列,但陣列在 C 語言中只能允許同樣的資料型別)。struct 主要使用步驟為宣告結構樣板和結構變數使用的宣告。
#include <stdio.h>
int main() {
// 樣板宣告
struct user {
char name[12];
int age;
};
// 變數宣告
struct user demo_user = {"Amy", 29};
// 印出結構體成員值
printf("demo_user name %s\n", demo_user.name);
printf("demo_user age %d\n", demo_user.age);
demo_user.age = 30;
printf("demo_user age %d\n", demo_user.age);
}
檔案讀取/寫入
透過 fopen()
函式我們可以讀取文字檔案或是二進位檔案。
以下為文字檔案範例:
data.txt
:
I love C
You love Python
She love Java
He love C++
讀取檔案程式碼:
#include <stdio.h>
int main() {
// 檔案指標
FILE *fp;
// 用來讀取檔案的字串
char str[50];
// 開啟檔案,r 模式為讀取
fp = fopen("./data.txt", "r");
// 若無法開啟則程式結束
if (fp == NULL) {
return 0;
}
while(1) {
// 接受最大讀取字元為 50
fgets(str, 50, fp);
// 若讀取到最後結尾則結束
if(feof(fp)) {
break;
}
printf("%s", str);
}
// 關閉檔案
fclose(fp);
}
寫入檔案程式碼:
#include <stdio.h>
int main() {
// 檔案指標
FILE *fp;
// 開啟檔案,w 模式為寫入
fp = fopen("./data1.txt", "w");
if (fp == NULL) {
return 0;
}
// 寫入檔案
fputs("I love C \n", fp);
// 寫入格式化字串
fprintf(fp, "I love Java, %d \n", 101);
fputs("I love Python \n", fp);
// 關閉檔案
fclose(fp);
}
總結
以上快速複習了 C 語言語法的重要特性,除了上述介紹的內容外,還有動態記憶分配、巨集、時間函式等更多使用方式下次有機會再整理給讀者,若有疏漏的地方也會陸續更新。有時寫久了直譯式程式語言也會覺得其實編譯式程式語言也有其可愛有趣的地方呢!