用遊戲概念學習 C/簡介
- 本書旨在向新使用者介紹 C 語言,同時使學習過程變得有趣,併為他們提供可以玩耍和修改的程式碼,以便他們在繼續學習的過程中進行自我教育。本書的作者是一位 C 語言初學者,面向初學者編寫,因此我可能並不總是使用最佳實踐。有興趣更深入地瞭解 C 語言的使用者建議檢視優秀的 C_Programming 華夏公益教科書.
- 我剛開始與他人分享程式碼,所以我覺得我應該宣告,包含在本華夏公益教科書中的程式碼是由作者生成的,與其他程式碼的任何相似之處並非有意為之,除非它是一些基本的東西,比如資料結構的實現(連結串列、堆等)。
本書建議初學者使用 Linux 發行版,例如 Linux Mint 或 Ubuntu。雖然我對 Windows 上的 C 程式設計不熟悉,但微軟的 Visual C++ 編譯器應該能夠編譯 C 程式碼(如果可用)。C 語言在 Unix/Linux 環境中很容易開始學習,因為 Gnu C 編譯器 (GCC) 預設包含在大多數發行版中。GCC 是一個命令列實用程式,它將 C 原始碼轉換為機器指令(二進位制檔案)。為了編寫程式碼,你需要一個文字編輯器或整合開發環境 (IDE)。一個易於使用的 IDE 是 Geany,你可以在 Linux 上使用包管理器找到它。
文字編輯器可以像記事本一樣簡單,也可以像 Vim 和 Emacs 一樣複雜。
讓我們一舉概括變數和標準 IO。
intro.c
#include <stdio.h>
int main() {
char input[50]; // # of characters we can read from standard input.
char name[50]; // variable to contain a name
printf("What is your name good sir?\n");
fgets(input, sizeof(input), stdin);
sscanf(input, "%s", &name);
printf("Ah, %s, a pleasure to meet you.\n", name);
return(0);
}
在我們編譯它之前,讓我們回顧一下我們的程式碼做了什麼。
程式開頭的 #include 語句讓編譯器知道我們要使用庫。C 語言中的庫稱為標頭檔案,以 ".h" 副檔名結尾。C 語言包含標準庫來執行各種常見任務。STDIO,顧名思義,包含各種用於列印和讀取的函式。
每個 C 程式的核心是主函式。它包含程式的主體,並且是程式啟動時呼叫的第一個函式。所有函式都遵循此語法
datatype functionName (datatype argument) {
statement;
return (datatype); // The datatype before the function name lets the
// compiler know this is the kind of variable we will return.
}
語句可以是變數宣告 (x = 100;) 或函式呼叫 (CallingFunction();)。所有語句都以分號結尾,並且將每個語句都放在自己的行上是一個好習慣。同樣重要的是要仔細檢查你的程式碼,以確保你沒有遺漏任何分號。
C 語言中有 3 種基本資料型別,我們必須使用它們來宣告我們的變數。我們使用資料型別宣告它們,以便編譯器確切地知道每個變數包含什麼。它們包括
- char (例如 'a' | 單個字元)
- int (例如 123 | 整數)
- float (例如 12.345 | 小數)
在我們的示例中,我們使用 char,但在它後面新增方括號和一個數字。語法 Variable[#] 讓編譯器知道,我們想要的不是單個字元,而是一個 陣列(字元字串)。
我們正在使用 STDIO 中的 3 個函式:printf、fgets 和 sscanf。我們的 stdin 和 stdout 來自我們將執行程式碼的命令列。
Printf 將字串(用引號表示)列印到標準輸出。如果字串中存在佔位符(%letter),它還會列印變數。Fgets 從標準輸入中讀取一行並將其放入名為 Input 的變數中。Sscanf 檢視名為 input 的變數並將它轉移到名為 name 的變數中。當我們獲取使用者輸入時,我們希望再次使用 Input,因此我們不能將我們的資訊留在其中,否則我們會覆蓋它!
return 語句可以從函式中返回 1 個數據型別或變數。我們使用返回值的最簡單示例是檢視某事物是真還是假。如果你有一個名為 isCapital 的函式,並對一個字母呼叫它,例如 isCapital('a'),我們將返回(False)。如果我們呼叫 isCapital('B'),我們將讓我們的函式返回(True)。呼叫 isCapital 函式的函式將被設計為根據我們返回的值做出決定。
但是,函式不需要返回值。有時你可能會看到在函式之前使用 'void'。這意味著該函式根本不返回值。
既然我們已經瞭解了我們的程式碼的作用,讓我們編譯並執行它。導航到包含你的 C 程式的資料夾。如果你不熟悉 BASH,則需要學習 cd 和 ls 命令。在命令終端中輸入
gcc intro.c -o intro
此命令呼叫編譯器 (GCC) 編譯 Intro.c 並輸出一個名為 Intro 的可執行檔案。如果由於某種原因你的檔案在編譯後未設定為可執行檔案,你可以輸入
chmod +x intro
要執行你的可執行檔案,請輸入
./intro
這不像列印 "Hello World" 那樣簡單,但希望它不難理解。隨著你繼續閱讀,隨著你開始識別程式設計中的常見模式,事情應該開始變得更有意義。
在我們繼續之前,花點時間調整我們的 Intro 程式。宣告一個名為 age 的 int 變數。將第一個列印語句更改為詢問你的年齡,並使用整數佔位符 %d 在第二個列印語句中列印你的年齡。
如果我們將所有函式和變數都放在一個檔案中,那麼閱讀大型程式將非常困難。假設我們還建立了一個很棒的函式,並且希望在所有程式中使用它,我們該怎麼做呢?
如果我們希望我們的可重用函式執行我們上一個程式執行的操作,我們只需將之前的所有語句放在一個具有唯一名稱的函式中,並將它們放在標頭檔案中。
greet.h
#include <stdio.h>
int Greet() {
char input[50]; // # of characters we can read from standard input.
char name[50]; // variable to contain a name
printf("What is your name good sir?\n");
fgets(input, sizeof(input), stdin);
sscanf(input, "%s", &name);
printf("Ah, %s, a pleasure to meet you.\n", name);
return(0);
}
現在可以在我們的程式中像 STDIO 一樣包含 Greet.h,我們甚至不需要在使用它之前編譯它。唯一的區別是,我們使用引號 "" 而不是尖括號 <>。如果你的主程式和你的標頭檔案在同一個資料夾中,#include "Greet.h" 是你唯一需要指定的內容。如果它們位於不同的資料夾中,你需要為編譯器提供完整路徑 #include "fullpath/Greet.h"
main_prog.c
#include "greet.h"
int main() {
Greet(); // We declared this function in greet.h
return(0);
}
當 main_prog.c 被編譯時,編譯器會查詢標頭檔案並將它們包含在編譯中。
gcc main_prog.c -o main_prog
main_prog,可執行檔案,將包含主程式和 Greet 檔案的機器指令。
./main_prog
What is your name good sir?
Theodore Roosevelt
Ah, Theodore Roosevelt, a pleasure to meet you.