小屋創作

日誌2018-12-20 13:09

[達人專欄] 跟著豬腳 C 起來:一次宣告一堆變數的方法

作者:解凍豬腳

 
  前篇:跟著豬腳 C 起來:各式各樣的資料型態

  大家好。還記得上次豬腳跟大家示範了幾種內建的資料型態,對吧?這樣你應該對於「變數」如何運用跟規劃,稍微有了些概念。例如,我們想要儲存一個學生的性別、分數、存款、身高、體重,就可以如以下的方式來宣告。我們來複習一下:

    // 關於性別,我們可以用 1 代表男生、2 代表女生、3 代表其他……等等,隨你自由設定,只要別把規則設得太複雜,能方便使用即可
    short gender = 1;
    short score = 87;
    int money = 22000;
    float height = 172.4;
    float weight = 67.3;

  有了以上的宣告跟初始化,就可以儲存某個人的五項資料到變數裡,並且在之後有需要的時候操作它。例如今天他在路上撿到了 1000 元,並且存入了銀行,那我們就可以做:

    money += 1000;

  這樣的話,電腦就會把 1000 元加進原有的 22000,使得 money 這個變數的值成為 23000。

  然而,倘若今天情況變得不同——現場有 10 個人,存款皆為 0 元,而我們想要用變數來儲存這 10 個不同人的存款,怎麼辦?剛學過變數宣告的人,就會這麼做:

    int money1 = 0;
    int money2 = 0;
    int money3 = 0;
    int money4 = 0;
    int money5 = 0;
    int money6 = 0;
    int money7 = 0;
    int money8 = 0;
    int money9 = 0;
    int money10 = 0;

  這麼做的話,當然可以達到目的。但是,如果今天有 600 個人的資料需要儲存跟處理呢?我相信你不會希望花了整整 600 行的篇幅,就只為了宣告這堆變數。

  你可要知道,電腦本來就是被設計來處理大量資料的,不是嗎?所以,在大部分的程式語言當中,都有個很好用的功能,叫做陣列(array)。如何使用呢?我們只需要在宣告的時候使用中括號和想宣告的數量,就可以一次宣告很多個變數:

  int money[600];

  從這句應該不難看出就是宣告 600 個叫做 money 的變數。為了在這 600 個都叫做 money 的變數之間做出分別,所以系統對它們加上了編號。當然你可以把它想像成令電腦設置一個含有 600 個格子的置物櫃,並且將這個置物櫃取名為 money。



  請注意,在 C 語言(以及大部分的程式語言)當中,array 都是從 0 開始編號的。這是因為在 money 這個 array 裡面,後面的 599 個變數都是依序緊接著排在第一個的後面,畢竟電腦只要將記憶體的參照位置都以第一個為基準的話,就不需要耗費太多空間去一一記錄 600 個不同變數的記憶體位置。

  所以,我們只要用一句 int money[600]; 宣告完,就可以使用 money[0] ~ money[599] 這樣總共 600 個各自為一個 int 型態的變數(這樣每一個變數在 array 裡面稱為元素)。

  先前在介紹變數的時候,不曉得大家還記不記得,身為一個有良好習慣的工程師,如果宣告完變數,記得要把裡頭的數值初始化,例如:

    int count = 0;

  這件事情拿到了 array 上面也是同理,只是表達方法不同。我們如果想要把這 600 個元素統一設為 0 的話,應該在宣告的同時這麼做:

    int money[600] = {0};

  這樣一來,就可以確保宣告好的每個元素都是 0,而不會遇上殘值的問題了(也就是先前舉例過上一個使用廁所的人沒沖馬桶的情況)。

  如果我們想要為這 array 裡面的其中一個元素賦值或是運算,其實做法就跟一般的變數沒有什麼不同:

    money[22] = 4000;
    money[3] += 300;

  這麼做的話就是將 money 這個 array 裡的第 23 個元素設為 4000,第 4 個元素則是增加 300 進去。千萬別忘記了,陣列一律都是從 0 開始數。

  Array 就是這麼方便的東西。

  所以,將 array 搭配上次的 char,我們還可以這麼做:

    char name[32] = "UPK.painting";
    printf("Hello, my name is %s.", name);

  只要把很多個 char 組起來,就會成為一個字串(string)。現在其實許多程式語言都已經內建字串為一種資料型態,不需要刻意把 char 用陣列串起來,更不用設定字串長度的最大值就是了。

  當然陣列還有更進階的用法,例如二維陣列(陣列裡頭的每個元素都是一個陣列)、三維陣列(陣列裡頭的每個元素都是一個二維陣列),或者是把陣列搭配迴圈使用,都可以完美地把陣列存在的意義發揮得淋漓盡致。關於迴圈,我們會留到下次再說(當然你也可以先自己拿去問 Google)。

  補充:在其他程式語言裡不只 array,有的語言還另外內建 list、slice、map、hash table 等功能,這些東西同樣都是可以儲存多個變數,但因為使用方法及可以做到的事情不太一樣,因此都有各自的優缺點。因為 C 語言就只有內建最簡單的 array,所以就不多談了。

  學會了 array 的宣告及使用以後,我們可以利用這樣的方法,將 600 個學生的性別、分數、存款、身高、體重使用簡短的幾句儲存起來了:

    short gender[600] = {0};
    short score[600] = {0};
    int money[600] = {0};
    float height[600] = {0};
    float weight[600] = {0};

  這種情況下,我們就完成了 600 筆個資的宣告,只要使用 gender[27]、score[27]、money[27]、height[27]、weight[27] 就可以取得第 28 個人的資料。

  但這樣實在太不直觀了。明明每個人都會有這五種屬性,我卻得要輸入五次 600 來宣告它,這樣不是很奇怪嗎?如果今天想要改成 2000 筆,我要把好幾個 600 一個一個改成 2000,這樣也挺麻煩的。

  再說,我們在查詢分數的時候,也習慣說:「28 號學生的分數」,而不是「分數表上的第 28 筆資料」,不是嗎?

  所以說,既然是以「人別」來作為分類,我們就不應該以「屬性別」來宣告,這樣才比較符合我們人類平常習慣口頭上說的語言。

  於是,我們又可以用到 C 語言的一個功能了:結構(structure)。它有點像是剛才所提到 array 的變種,差別在 array 是用編號來指定元素,但 structure 則是使用成員(屬性)的名稱來指定,而且 structure 可以儲存很多種不同型態的資料。

  如此一來,每個宣告出來的 structure 變數都好像一個實體的物件一樣,就會讓人覺得真的好像在操作物品,而不是一堆雜亂無章、毫無結構可言的變數。

  舉個例子。如果我們今天班上有 50 名學生,我們想要記錄他們的姓名、性別、身高、體重、分數,那我就可以利用 struct 功能,先宣告好「一個 student 該有哪些屬性」,宣告的方法跟一般宣告變數的格式類似,只要使用資料型態和屬性名稱即可:

    struct student {
        char name[32];
        short gender;
        float height;
        float weight;
        short score;
    }

  放在 main 裡面就可以了(你想放在 main 外面也沒問題,這會牽涉到這個結構可以被誰使用,等到之後介紹「函數」,就可以放在一起講了)。

  請注意,以上這段程式碼只是預先向電腦定義好型態,並沒有實際要求電腦挪出記憶體、宣告成可以存取的變數。

  直到下面這步,才是實際宣告變數:

    struct student myStudents[50] = {0};

  這就跟一般宣告陣列沒有什麼不同,我們只不過是把原來該填入資料型態的地方換成了 struct student 而已。



  只看文字的話好像有點複雜,其實只是像上圖這樣,先告訴電腦一個 student 該有什麼,然後再一次宣告很多個 student,如此而已。

  我們就得到了 50 筆已經初始化完的學生資料變數。那麼該如何取值呢?我們可以使用半形的「.」來連接,在這裡你可以暫時把它口語化理解成「的」,例如:

    myStudents[3].score = 70;

  這樣就可以令「第 4 個學生『的』分數」為 70 分了。

  使用 structure 的方便之處在於,倘若今天突然發現漏了東西,我們臨時想要補上記錄學生父母名字的欄位的話,就只需要修改 struct student { … } 這段,在裡面另外加上兩個變數即可:

    struct student {
        char name[32];
        char dadName[32];
        char momName[32];
        short gender;
        float height;
        float weight;
        short score;
    };

  最重要的是,定義好的 struct 可以重複使用,這樣如果有很多不同班級的學生資料需要被記錄,那我們就不需要一直複製貼上了,寫出來的程式碼就會簡單又乾淨。

  其實說到這裡,我們還沒有完全發揮 structure 跟 array 的特性,目前這篇的內容只能讓讀者知道宣告變數的時候應該要有策略地運用兩者,以免後患。

  下次,我會說明如何利用「迴圈」的技巧,令程式執行大量重複的類似工作,並且和今天所提到的陣列和結構搭配使用,只要把這些學會,你就已經完成基礎的一半囉!敬請期待。
 

97

30

LINE 分享

相關創作

《生活中的資安風險:偵防技術實戰》

promise.all 有一個失敗就不會往下做其他promise了,如何無痛讓promise做事 - promise.all的陷阱

2024 的個人網頁設計

留言

開啟 APP

face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】