因為 C 是個「麻煩」的程式語言,而 Python 其實已經簡化很多步驟。先學 C 語言了解程式語言的架構,再學其他語言就會覺得更簡單。在學習 C 語言的過程中可以了解電腦科學較接近底層的基本運作,不只有侷限在單純寫出漂亮的程式碼。
首先,我們從印出 hello,world 認識標頭檔。
#include <stdio.h> //第一步:加入標頭檔,讓程式能使用「標準輸入輸出」的功能。
int main(void) // 主程式的起點
{
printf("hello, world"); // 最後加上;表示結束
}
//
是程式的註解,在此之後的資訊都不會被運行。<stdio.h>
,是 C 語言裡負責處理輸入和輸出的函式庫。函式庫的概念是前人寫好的功能包,只要導入標頭檔,即可使用該函式庫的所有功能。注意,stdio 是 "standard input/output" 的縮寫,不是 "studio"。int
表示這個主程式會回傳一個整數結果,main
是程式的主要函式。(void)
表示這個程式不需要從使用者接收任何資料。C 語言中,需要定義每個函數的型態。雖然結果是印出「hello,word」,但實際上程式的最後一段會有return 0
表示程式執行成功,並結束主程式,所以這個函式仍是int
類別。printf
是用來輸出文字到螢幕上的函式。這裡會顯示 "hello, world"。每個命令結尾要用分號 (;) 表示這一行程式碼結束。寫完之後還不能直接跑,必須先用 make 檔名編譯轉成電腦,再輸入 ./
才會跑出程式的結果。
咦?奇怪怎麼出現 $
printf("hello, world\n")
。\n
是屬於 Escape Sequence 跳脫序列的其中,除了 \n
還有 \t
:水平跳位 (tab)printf("Hello\tWorld")
; 會輸出:Hello World
\\
:反斜線 (backslash)printf("C:\\Program Files")
; 會輸出:C:\Program Files
\"
:雙引號 (double quote)printf("\"Hello, World\"")
; 會輸出:"Hello, World"
這些跳脫序列讓你可以在字串中包含特殊的格式或字符。
電腦新手村的第一篇提到,電腦的 0 和 1 都需要有空間儲存。能處理的數值範圍越廣,占用的空間也越大。
int
(整數型別):
int
是 4 個位元組(32 位元),因此範圍是:float
(浮點數型別):
1 除以 3 應該得到 0.3333333 但是最後只有 0。因為電腦只保留整數部分,把小數點後面的數字直接捨去。更多的基本資料型別請按這裡。
float 不等於小數的原因是,超過記憶體負荷,後面的小數就會出現亂碼,並不符合數學定義的小數條件。
假設我要算 1/3 到小數第20位:
#include <stdio.h>
#include <cs50.h>
int main(){
int x = get_int("x: ");
int y = get_int("y: ");
float z = (float) x/ (float) y; //整數計算不會出現浮點數 (會出現0.000),所以要先轉成浮點數
printf("%.20f\n",z); // 取到20
}
解決方式:改成 double
的資料型別。
如果我不改變資料型別,會造成 Integer overflow(整數溢位)的問題。
前面提到,int
範圍是 -2,147,483,648 到 2,147,483,647。如果你嘗試加一個大於這個範圍的數字,結果就會發生「溢位」。代表數值爆掉,會從頭開始。例如:
2,147,483,647 + 1
會變成 -2,147,483,648
,而不是你預期的 2,147,483,648
。如果是在 CS50 的環境,先導入<cs50.h>
的函式庫才可以繼續使用 string
這個字串;至於一般在電腦本機運行的C語言則是要用「字元陣列」的方式表達。( 之後再細講這個部分。
#include <stdio.h>
#include <cs50.h>
int main(){
string name = get_string("請問你叫什麼名字?\n"); //()括弧裡面是提示
int age = get_int("請問你幾歲?\n"); // 程式從右邊讀到左邊,即將使用者輸入的值,「賦值給age這個變數」
printf("Hi %s, 你 %d 歲\n", name, age);
//因為使用者輸入名字和歲數都不固定所以要用%s表示變數,而%s代表的數值又是從剛剛問的name得到,同理用%d表示整數,整數來自剛剛使用者輸入的age
}
=
:這是賦值的符號。它的作用是把右邊的值賦給左邊的變數。可以把它想像成把右邊的內容放到左邊的容器中。舉個例子:count = count + 1
。它的作用是把 count
的值增加 1
。使用 count++
可以更簡潔地完成這個操作。=
是用來賦值的,把右邊的內容給左邊的變數。count = count + 1
和 count++
都是用來讓變數 count
的值增加 1
%d
和 %s
是格式化輸出(format specifiers)用來顯示變數的不同類型%d
、%i
和 %s
printf("Hi %s, 你 %d 歲\n", name, age);
舉例來說,%d
是指輸出的變數型態為整數,而輸出的值要對應到 age 。如果直接輸入 age 而不是變數,最後的結果會變成 「你 age 歲」,而不是「你 25 歲」。
看起來都可以得到正確答案,但假如使用者亂回答,我們怎麼避免呢?我們來做進階的練習~
如果使用者回答 200 歲或是 -10,可以在前面多設一個關卡。這裡會用到「 C 語言中的邏輯運算子」
AND: &&
OR: ||
NOT: !
#include <stdio.h>
#include <cs50.h>
#include <string.h>
int main()
{
string name = get_string("請問你叫什麼名字?\n"); // ()括弧裡面是提示
int age = get_int("請問你幾歲?\n"); // 程式從右邊讀到左邊,即將使用者輸入的值,「賦值給age這個變數」
while (age > 100 || age < 0) {
age = get_int("請重新輸入年齡\n");
}
if (age >= 65) {
printf("Hi %s, 你 %d 歲是老年\n", name, age);
} else if (age >= 18 && age <= 65) {
printf("Hi %s, 你 %d 歲是成年\n", name, age);
} else {
printf("Hi %s, 你 %d 歲是未成年\n", name, age);
}
}
while
在這裡的用意是確認使用者輸入到正確的年齡才可以進行判斷,若單純用 if
只會問一次「請重新輸入年齡」。
連續三個 if 是 前一個判斷的結果都沒有功能
相關補充
「布林值」就是 true
跟 false
兩個答案,true
代表 1 ,false
代表 0 ,所以寫 if 60 <= a <= 100 居然是錯的邏輯,因為程式從左邊讀到右邊,首先讀 60 <=a ,不管答案是true (1) 或是false (0)。再往右邊讀,0 或 1都小於等於 100,所以答案會永遠都是 true。參考筆記
clear
清除前面終端的指令