2024-08-20|閱讀時間 ‧ 約 14 分鐘

C 語言 | 程式碼基本要素 | if else / if 差別

    為什麼從 C 開始 ? 為什麼不是 Python?

    因為 C 是個「麻煩」的程式語言,而 Python 其實已經簡化很多步驟。先學 C 語言了解程式語言的架構,再學其他語言就會覺得更簡單。在學習 C 語言的過程中可以了解電腦科學較接近底層的基本運作,不只有侷限在單純寫出漂亮的程式碼。

    首先,我們從印出 hello,world 認識標頭檔。


    怎麼寫出 Hello World?

    怎麼運行 Hello World? 記得要編譯阿!

    • 初學者可以用 CS50.dev 內建的雲端版,寫自己第一個程式。每一行程式都可以解釋,請見下圖程式碼:
    #include <stdio.h>  //第一步:加入標頭檔,讓程式能使用「標準輸入輸出」的功能。

    int main(void)  // 主程式的起點
    {
        printf("hello, world"); // 最後加上;表示結束
    }
    1. // 是程式的註解,在此之後的資訊都不會被運行。
    2. 這個標頭檔叫做 <stdio.h>,是 C 語言裡負責處理輸入和輸出的函式庫。函式庫的概念是前人寫好的功能包,只要導入標頭檔,即可使用該函式庫的所有功能。注意,stdio 是 "standard input/output" 的縮寫,不是 "studio"。
    3. 主程式的起點。int 表示這個主程式會回傳一個整數結果,main是程式的主要函式。(void)表示這個程式不需要從使用者接收任何資料。C 語言中,需要定義每個函數的型態。雖然結果是印出「hello,word」,但實際上程式的最後一段會有return 0 表示程式執行成功,並結束主程式,所以這個函式仍是int類別。
    4. printf 是用來輸出文字到螢幕上的函式。這裡會顯示 "hello, world"。每個命令結尾要用分號 (;) 表示這一行程式碼結束。

    寫完之後還不能直接跑,必須先用 make 檔名編譯轉成電腦,再輸入 ./ 才會跑出程式的結果。

    make hello 才是對的,多打了 hello.c 就跑不出來。

    跑出另外一個檔是由 0 和 1 組成,電腦才看得懂得檔案~ 點開沒有 .c 的檔案會被告知檔案是二進位檔案。




    編譯之後,再 ./ 檔名,就會跑出「hello, world」,

    最後的成果

    咦?奇怪怎麼出現 $

    解法是要「換行」, 輸入 \n (注意 \ 跟 / 的差別)。完整的寫法會是:

    printf("hello, world\n")

    \n 是屬於 Escape Sequence 跳脫序列的其中,除了 \n 還有

    1. \t:水平跳位 (tab)
      • 插入一個水平跳位,相當於按下 Tab 鍵。
      • 範例:printf("Hello\tWorld"); 會輸出:Hello World
    2. \\:反斜線 (backslash)
      • 用來輸出一個反斜線字符。
      • 範例:printf("C:\\Program Files"); 會輸出:C:\Program Files
    3. \":雙引號 (double quote)
      • 用來在字串中輸出雙引號。
      • 範例:printf("\"Hello, World\""); 會輸出:"Hello, World"

    這些跳脫序列讓你可以在字串中包含特殊的格式或字符。

    C 語言的資料型別:int, float, char...

    電腦新手村的第一篇提到,電腦的 0 和 1 都需要有空間儲存。能處理的數值範圍越廣,占用的空間也越大。

    int (整數型別):

    • 一般來說,int 是 4 個位元組(32 位元),因此範圍是:
      • 有號整數: -2,147,483,648 到 2,147,483,647
      • 無號整數 (unsigned int): 0 到 4,294,967,295 (把負數的數值移到正數,想像範圍是一把尺,起始點不同但是區間內包含的數量相同)

    float (浮點數型別):

    • 通常是 4 個位元組(32 位元),可以表示的範圍約為:
      • 正或負的範圍:約 ±3.4 × 1038 到 ±1.2 × 10-38
      • 小數點精度: 通常能提供 6 到 7 位有效數
    • 需要更廣的範圍要用到 double

    int 的 Truncation (截斷) 問題:

    1 除以 3 應該得到 0.3333333 但是最後只有 0。因為電腦只保留整數部分,把小數點後面的數字直接捨去。更多的基本資料型別請按這裡

    float 浮點數不精確:

    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
    }

    應該要是 0.3333 但是已經超出 float 所用的空間,後面就出現亂數。

    解決方式:改成 double的資料型別。

    儲存空間不足造成的問題:Integer overflow(整數溢位)

    如果我不改變資料型別,會造成 Integer overflow(整數溢位)的問題。

    前面提到,int 範圍是 -2,147,483,648 到 2,147,483,647。如果你嘗試加一個大於這個範圍的數字,結果就會發生「溢位」。代表數值爆掉,會從頭開始。例如:

    • 最大整數 2,147,483,647 + 1 會變成 -2,147,483,648,而不是你預期的 2,147,483,648


    C 語言沒有字串 String !!!如何讓使用者輸入字串?

    如果是在 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 = 1,這表示把數字 1 放到變數 count 中。
      • 如果後來你寫 count = count + 1,這表示把 count 現在的值加 1,然後把這個新值再放回 count 中。
    • count++:這是一種簡化的寫法,等同於 count = count + 1。它的作用是把 count 的值增加 1。使用 count++ 可以更簡潔地完成這個操作。

    小結:

    • = 是用來賦值的,把右邊的內容給左邊的變數。
    • count = count + 1count++ 都是用來讓變數 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: !

    int main()
    {
        string name = get_string("請問你叫什麼名字?\n"); //()括弧裡面是提示
        int age = get_int("請問你幾歲?\n"); // 程式從右邊讀到左邊,即將使用者輸入的值,「賦值給age這個變數」
        if (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);
    }


    三個 if 跟 if/else if/else 差在哪裡?

    連續三個 if 是 前一個判斷的結果都沒有功能


    相關補充

    「布林值」就是 truefalse 兩個答案,true 代表 1 ,false 代表 0 ,所以寫 if 60 <= a <= 100 居然是錯的邏輯,因為程式從左邊讀到右邊,首先讀 60 <=a ,不管答案是true (1) 或是false (0)。再往右邊讀,0 或 1都小於等於 100,所以答案會永遠都是 true。參考筆記


    終端機使用技巧與寫程式小工具分享

    clear 清除前面終端的指令

    參考資源:






    分享至
    成為作者繼續創作的動力吧!
    © 2024 vocus All rights reserved.