創作內容

101 GP

[達人專欄] 跟著豬腳 C 起來:用電腦來操控資料吧

作者:解凍豬腳│2018-09-06 13:46:20│巴幣:311│人氣:5154
 
  前篇:跟著豬腳 C 起來:撰寫你的第一支程式

  上次我們利用了 printf 函數,成功地顯示「Hello, world!」這行字了。然而,我們每個人都知道,寫程式是需要有邏輯的,如果一支程式從頭到尾單單就顯示這麼一行字,它想必不能起什麼作用,我們時常會需要利用電腦來協助計算。

  我們都知道「電腦」又稱為「計算機」,只要涉及「運算」就必須存取資料,就好像你在數數的時候,心裡會默默記著「目前數的數字是多少」一樣。如果不知道電腦如何儲存資料的話,那我們對存取過程的理解就僅止於皮毛。所以,來談談電腦的演進吧!

  1940 年代,世界上出現了第一部電子電腦。在該時期,「真空管」成為了資料暫存媒介的主流。因為這裡不希望講太多物理相關的細節,所以你可以把真空管理解成是燈泡。

  ——燈泡怎麼可以用來儲存資料呢?科學家和工程師如此設計,可是有原因的。先來談談進位法吧!平常在數數字的時候,我們總是依著這樣的順序來進行的:

  0、1、2、3、…、8、9、10、11、…、19、20、21、…、98、99、100、101 …

  你發現了嗎?當我們每數滿 10 個數就會自動進位,所以個位數在 9 之後會進位,於是就成為了 10。當我們數到 99 以後,如果要再往上數一個數,個位的 9 會變成 10 而進位,十位的 9 也因為前者的進位而隨著進位,成為了 100。

  我們生活中所使用的系統就是這樣,所以我們可以說它是「十進位制」的數字。

  但科學家想得可不一樣。在這個世界上,科學家找不到適合的物質可以產生「十種狀態」的變化(0、1、2、3、4、5、6、7、8、9),而就算真的找到了這樣的物質,電腦也沒辦法對它操控自如。

  這時科學家想到了,因為燈泡可以有「亮」跟「不亮」兩種狀態,而且如果計算機是利用電力來運作的話,就可以更輕易地儲存、讀取資料,於是他們決定使用「二進位」作為電腦的運算基礎,同時把腦筋動到了真空管身上。

  如果我們用二進位的系統來數數,就會依照這樣的規律進行:

  0、1、10、11、100、101、110、111、1000、1001、1010、1011、1100 …

  「在非洲,每 60 秒,就會有 1 分鐘過去。」實際上,無論我們使用什麼樣的進位法,數學的性質仍然不會改變。1 分鐘和 60 秒的長度相同,如果我們平均每秒可以跑 3 公尺,那麼我們每分鐘可以跑 180 公尺,每 60 秒也仍然是 180 公尺,只是表示的方法不同而已。

  所以,科學家就很放心地這麼做了。

  回到問題本身來:如何使用燈泡和二進位制來表示資料?如果你夠聰明的話,沒有錯啦!每一個位,都需要使用一顆燈泡。只要燈泡越多,就可以儲存越多的資訊。

  舉個例子,當我們需要表示十進位當中「87」這個數的時候,要知道它的二進位是「1010111」(十進位跟二進位有互換的算法,此處不深談過程和原理),這時候可以使用七顆依序為「亮、暗、亮、暗、亮、亮、亮」的燈泡來表示,然後科學家又依著這樣的架構去設計出了加法器、減法器等電路元件,於是就架構出了電腦初步的運算功能。

  在接下來的 80 年間,科學家不斷嘗試使用不同的材料(元件)作為媒介,於是真空管就先後被電晶體、積體電路取代,並且持續進步至今。現在的半導體產業,正是利用精細的工法,把積體電路上的電晶體們做得又小又密集,你才能有這麼先進又高效能的電腦可以用。

  後來,科學家訂定了一個單位叫做「位元」(bit,縮寫為小寫 b),相當於上例的一顆燈泡,只能儲存一個 0 或是一個 1,同時也衍生了一個單位叫做「位元組」(byte,縮寫為大寫 B),相當於八顆燈泡。

  因此我們可以得知,一個位元組可以用來表示 00000000 ~ 11111111,也就是十進位的 0 到 255,總共有 256 種可能,除非特殊需要,否則現在的電腦幾乎是以「位元組」作為儲存資料的基本單位了。

  問題來了,一旦我們今天要用二進位表示一個稍微大一點的數字,就假設是 1795279453 這個數好了,把它轉換成二進位,會變成 01101011 00000001 11001010 01011101 這麼一串數字,那可多長。因此在某些情況下,我們會改以「十六進位」來表示一個很大的數字(特別是用來當作編號的時候),成為了 6B01CA5D。有些情況下,為了避免和十進位的數字搞混,我們習慣上會把它標記為 0x6B01CA5D 或是 6B01CA5Dh,表示它是十六進位的數;在二進位的數前面,我們則會加上一個 0b 代表它是一個二進位數(例如 0x5F = 0b1011111)。

  多了英文字母看起來就很複雜,對吧?其實很簡單,數數的規律還是那樣子的:

  0、1、2、…、8、9、A、B、C、D、E、F、10、11、…19、1A、1B、…、1F、20 …

  為何是使用十六進位,而不是十五進位、十四進位或其他的數字呢?主要來說,因為 16 恰好是 2 的 4 次方,十六進位的 F 恰好等於二進位的 1111,所以在轉換的時候就會很方便,二進位制的每 4 個位,恰好可以對應到十六進位制的每 1 個位。

  所以,你會在某些記憶體修改工具的畫面中看到,無論是記憶體位址編號還是該位元組的值,通通都會用十六進位來表示,如下圖:



  如果你有乖乖看完上面的說明,就會有以下的觀念:

  1. 電腦的底層是使用 0 和 1 來處理資料的,每一個位的單位稱為「位元」。
  2. 因為用 0 和 1 來表示資料太麻煩,所以編號類的東西常常會用 0~F 來表示。
  3. 因為「位元」太小,所以我們儲存資料通常以 8 個位元而成的「位元組」為單位。

  這些觀念看起來似乎都過於底層。可一旦有了這些概念,就可以避免日後多走些冤枉路。接下來的範例,也會用位元組作為單位,讓你理解電腦如何儲存資料。

  依照上次撰寫第一支程式時給的範例,請你先打上起手的程式碼:

#include <stdio.h>

int main(void){
    return 0;
}

  接下來就可以命令電腦替你準備記憶體空間了!我們都知道,如果要拿一張紙來計算加法,紙上就需要有一個空白處夠大的地方,這樣我們才能夠把數字寫上去。在電腦上面也一樣,只是我們必須先推測一件很重要的事:數字可能會多大?

  沒有錯,身為一個優秀的程式設計師,我們得要先注意接下來的計算過程會需要用到多少空間。這種感覺就好像你想要買個置物櫃來收納玩偶,只需要挑個夠大的櫃子就好,不需要搞得太大。如果買回來的置物櫃太大的話,那你的房間就會變得很擁擠。

  所以,在程式設計的世界當中同理,儲存資料所用到的空間,可以有很多種不同的形式,有的可以用來儲存整數,有的可以拿來儲存浮點數,我們稱為「資料型態」,而這個儲存資料所用到的空間,我們稱為「變數」。

  這時候,請你在 main 裡頭加上這行:

    int x, y;

  這句的意思是這樣:請電腦替你準備兩個「integer」型態的變數,一個叫做 x,另一個叫做 y,而這個過程我們稱為「宣告變數」。

  如果你一次只宣告一個叫做 k 的變數,可以這樣:

    int k;

  如果你一次想宣告四個分別叫做 ma、nnn、qq、pppp 的變數,可以這樣:

    int ma, nnn, qq, pppp;

  在一般的加減法用途上,如果不需要用到小數點後的位,數字也沒有特別大的話,我們會用一個稱為「整數」(integer)的資料型態來儲存數字,在 C 語言裡面稱為 int。當然,因為 int 有這樣的特殊意義,所以我們不能夠把變數的名稱取為「int」,像這種有特殊意義導致不能拿來取名的,就稱為「保留字」。至於變數型態有哪些、保留字有哪些,請你自己去 Google 吧,下回我可能會直接當作你已經會了。

  只要別用保留字來取名的話,變數名字當然就隨你高興了,只要能看得懂就好。通常我們會用小寫來替變數取名。

  一個 int 可以存多少資料呢?這要依照編譯器的規範而定。以我們使用的 Dev-C++ 所附的編譯器為標準,int 的資料長度是 4 bytes(位元組),也就是 32 個位元,這樣的話就總共有 4,294,967,296 種可能。因為我們可能有機會用到負數,所以預設的 int 是把範圍設定在 -2,147,483,648 ~ 2,147,483,647。

  你一定會問:如果想要用一個 int 的變數去儲存大於 2,147,483,647 的數,會怎麼樣呢?放心,你的電腦不會因此冒煙,但是會產生「溢位」(overflow)問題。

  其實在電腦眼中是這樣的:2147483647 + 1 = -2147483648,畢竟剛開始限定的範圍就只有那麼大,因此突破界線的時候就會循環。

  回頭繼續講宣告變數吧!我們剛剛做了這件事:

    int x, y;

  這時候 x 和 y 的值會是多少呢?答案是:不知道。

  沒有錯,當你在宣告變數的時候,電腦會隨便從記憶體裡面挑出一個「已經沒有人在使用的空間」來用,這個空間可能先前曾經被別的程式使用過,該處的資料就一直維持那樣,就好像你在學校上廁所的時候,可能會遇到某間廁所的馬桶沒有沖乾淨(或是根本沒沖)。

  所以,我們在使用變數的時候,務必注意它的「初始值」。我們可以使用等號來替它指定好一個初始值:

    int x, y;
    x = 3;
    y = 9;

也可以在宣告的同時就指定好:

    int x=3, y=9;

  沒錯,這個等號的意義是「指定值」,而不是「等於」。注意!程式是由上往下、一行一行運作的,因此前者分成三行的時候,宣告變數的那一行必須要放在最上面,這樣編譯器才能看得懂這個 x 和 y 是什麼。

  接著我們回頭來複習上次用過的 printf 吧!在指定好兩個變數的值以後,我們可以利用 printf 把它印出來:

    printf("x+y = %d\n", x+y);
    printf("x-y = %d\n", x-y);
    printf("x*y = %d\n", x*y);
    printf("%d, %d, %d", x, y, x+y);

  這比上次的「Hello, world!」還要複雜得多。其實 printf 的規則是這樣子的:我們在括號之中必須先用半形雙引號引出一個字串(例如上次的「Hello, world!」),如果需要顯示變數的值,就必須在字串裡面先標好位置,之後以逗號分隔依序填入。在字串中我們通常會用 %d 這樣的符號,表示我想要顯示一個十進位的整數,如下圖底線所示:



  一切都是照順序來的。圖中紅色底線的 x 會被填入紅色底線的 %d、綠色底線的 y 會被填入綠色底線的 %d、藍色底線的 x+y 會被填入藍色底線的 %d。所以引號裡面的其他內容都是自由填寫的,哪怕今天你寫成:

    int x=3, y=9;
    printf("a+b = %d\n", x*y);

  顯示出來的仍然會是「a+b = 27」。所以請注意,字串裡只要跟 % 符號無關的東西,通通只是表面的文字,不會影響計算結果。

  簡單來說它的形式就是這樣:printf(字串, 運算式1, 運算式2, ...);

  這裡要注意一點,上述的各種例子當中,我們使用的 x+y、x-y 或 x*y 的計算結果,因為是計算完直接傳給 printf 這個函式,所以電腦會在這過程中,另外再找一個合適的暫存空間來存放該計算結果,用完就丟。在這之後,x 的值仍然是 3,y 的值仍然是 9,不會因為我單純把它們拿出來用而造成數值改變。

  如果想要對值進行操作,一樣利用等號就可以了。在大部分的程式語言當中,這些加(+)、減(-)、乘以(*)、除以(/)、代入(=)等運算符號都有各自的優先權高低,所以如果你用了「x = x+y;」,電腦會先把等號右邊的東西都算完,最後才把結果丟進 x。

  另外,在 C 語言的字串當中,「\n」代表著「換行符號」,你可以試試看把 \n 拿掉以後會發生什麼事。在字串裡,這個反斜線稱為「跳脫字元」,而它和其他字搭配而產生特殊功能的組合,我們稱為「跳脫序列」。某些特殊、不能直接貼在程式碼裡的東西,我們就必須利用跳脫序列,這樣才不會造成程式設計師和編譯器對於程式碼內容混淆的情形。想要更多跳脫字元的相關資料嗎?我強調過很多次了,你知道該怎麼做的。

  接著如下範例做做看吧!你也可以自己動點手腳,對程式碼加一些變化來驗證電腦是否有先乘除後加減的概念:

#include <stdio.h>

int main(void){
    int x=3, y=9;
    printf("%d, %d\n", x, y);
    x = x+y;
    y = y+5;
    printf("%d, %d\n", x, y);
    x = x-3;
    y = x;
    printf("%d, %d\n", x, y);
    return 0;
}

  值得注意的是,a = a+b 這類的寫法,我們可以簡化為 a += b,也就是說如果要讓 a 的值增加 1 的話,我們可以使用 a += 1;(其實 a++; 或 ++a; 也可以讓 a 往上加 1,這點我想留到之後講迴圈的時候再提)。當然不只「+=」,其他的減、乘以、除以等運算符號,都可以如法炮製。

  關於 printf 的用法以及如何宣告變數,大致上就是這樣。希望這篇有助於你建立基本觀念以及邊寫程式邊 Google 的好習慣。
 
引用網址:https://home.gamer.com.tw/TrackBack.php?sn=4120840
All rights reserved. 版權所有,保留一切權利

相關創作

同標籤作品搜尋:第一次踏入墳場就上手|從入門到入墳|從入門到放棄|C語言|程式設計|C|C++|寫程式|程式|回收業者

留言共 19 篇留言

哥布林鎖鍊旋轉者
跟著豬腳學計算機概論

09-06 13:57

雲淡・風清 偵探模式
終於等到了

09-06 14:05

雲淡・風清 偵探模式
等等公民課來看

09-06 14:05

呆某
程式猿支持

09-06 15:53

るい♑
真D厲害

09-06 16:22

梓月
U質文 下次就可以進指標了>< 開心

09-06 16:29

笑死人了
吸起來,用電腦來監控雷雷吧

09-06 16:39

M@B
推推

09-06 16:53

病嬌控+腿控=MRabbitPG
上課無聊就寫程式

09-06 18:45

熊哥(´・ω・`)
推個,受益良多><

09-06 19:49

超猛禿頭佬
優秀

09-06 20:27

Eolico
下一堂是線段樹ㄇ>\\\< 期待<3

09-06 22:02

阿辰
熱騰騰好文出爐!
話說a++,++a的運算結果有順序之分XD

09-06 23:50

章魚茶
優質
樓上上這個線段樹也跳太快XD

09-07 01:17

>д<
厲害

09-07 10:38

頹廢。米蟲┘
可以補充 ++a, a++
sequence point, side effect的概念

10-04 21:15

腦內模擬
我認為應該稍微提到system ("PAUSE")

10-15 12:02

雞塊
關於1byte 有256的可能是沒錯 可是平常都應該是-128~127 而不是0~255

10-24 18:19

G36_maid
下一堂課是函式嗎><

11-17 18:34

解凍豬腳
我也正在思考接下來該從哪裡繼續,畢竟資料型態講得不夠完全11-17 18:49
我要留言提醒:您尚未登入,請先登入再留言

101喜歡★johnny860726 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:[達人專欄] 來向大家分... 後一篇:瘦瘦可愛的男孩子...

追蹤私訊切換新版閱覽

作品資料夾

------------------ (0)

豬腳生活 (1)
日常雜談、巴哈大小事 (193)
煞氣a國中生 (7)
高中生活日誌 (55)
大學生活日誌 (34)
冬令營回憶錄 (19)
也許藏有一些小祕密吧? (3)
各式各樣的開箱文 (11)
貓科動物時間 (15)

------------------ (0)

繪圖創作 (1)
電繪插圖、草稿 (199)
短篇漫畫、單幅標語 (61)
上課太無聊的手繪塗鴉 (8)
不知道該怎麼分類的綜合作品 (18)

文字創作 (1)
草莓兵的國軍紀實 (14)
我與らい的點點滴滴 (12)
那些榮耀的時刻與心跳加速的瞬間 (60)
有感而發的隨筆之作、無法分類的短文 (17)

------------------ (0)

語言學習 (1)
日語:天気がいいから (5)
粵語:唔好再淨係識講粗口喇 (6)
英語:Hey, you! (1)

程式設計及電腦網路 (1)
系列文:跟著豬腳 C 起來 (10)
系列文:論壇網站運作原理 (3)
Go(Golang) (11)
Ruby / RGSS (7)
Visual Basic (13)
JavaScript (1)
各種原理 (17)

思想:多思考一下,世界會更不一樣 (1)
網路經驗、社會觀察 (23)
檸檬庫 (21)

數學:我來拯救你的期中考了 (1)
各類基礎觀念 (5)
國中生也能懂的微積分 (9)
微分方程 (0)

小說:用筆鋒劃出新世界的入口 (1)

繪圖:我也想畫出私巴拉西的美圖 (10)

------------------ (0)

施工中 (22)

不堪回首的痕跡、雜物堆放 (31)

------------------ (0)

未分類 (0)

robert286 ლ(´•д• ̀ლ
ლ(´•д• ̀ლ看更多我要大聲說昨天23:18


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

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