跳轉至內容

用遊戲概念學習 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 種基本資料型別,我們必須使用它們來宣告我們的變數。我們使用資料型別宣告它們,以便編譯器確切地知道每個變數包含什麼。它們包括

  1. char (例如 'a' | 單個字元)
  2. int (例如 123 | 整數)
  3. 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,則需要學習 cdls 命令。在命令終端中輸入

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.
華夏公益教科書