創作內容

54 GP

[達人專欄] 跟著豬腳 C 起來:程式如果不能輸入資料,那有什麼用?

作者:解凍豬腳│2020-10-08 09:18:20│巴幣:108│人氣:2372
 
  前篇:跟著豬腳 C 起來:條件分歧,邏輯整個都出來了

  其實這篇正常來說早在當初最前面講 printf 的時候就該一起寫,但我個人覺得如果不先把條件分歧之類的基礎工具講完,那麼就算能讓使用者輸入資料進來,好像也沒有什麼意義,所以擺到今天才講。

  大部分的 3C 產品,正常來說總會有個螢幕(顯示面板)或是按鈕,讓你能夠對機器下達指令,而你也能同時透過顯示面板知道目前機器的狀態——這兩種基本元素,正是現代電腦具備的 I/O(input / output)功能。

  我們平時在電腦上面操作的程式也同理。撇除完全自動化的程式不談,很多時候我們總是需要按照使用者的需求來決定程式應該如何執行,這個程式才能夠真的算是有用。

  回憶一下上次示範的簡易身分證字號檢查器。你想想,如果程式設計師把想檢查的那組身分證字號寫死在 code 裡面,那這個程式不就只能檢查這麼一組身分證字號嗎?只能檢查一組身分證字號的檢查器,跟垃圾有什麼兩樣呢?

  所以,我們今天要來講的是 printf 的好兄弟——scanf!

  它的用法跟 printf 長得很像,先擺個字串把要讓使用者輸入的格式排出來,然後再把負責接收輸入資料的變數們依序放在後面:

    int x, y;
    printf("請輸入 x, y 的值並以空格隔開:");
    scanf("%d %d", &x, &y);

  這種時候使用者只要輸入「100 200」然後按下 enter,x 的值就會被設為 100、y 的值就會被設為 200。

  這裡值得注意的是,scanf 和 printf 有個地方不同,那就是負責接收資料的變數前面必須加上一個「&」符號,不過這裡涉及記憶體位址在函數的傳遞問題,這個就留到以後再一起講吧,總之現階段只要記得使用 scanf 的時候變數前面必須加上「&」就好了。

  也可以接收浮點數:

    float m;
    printf("請輸入 m 的值:");
    scanf("%f", &m);

  你也可以把 scanf 用來接收字串,然後以「%10s」來限定只能輸入 10 個字元(例如用在上次示範的身分證字號檢查器上面):

    char str[16];
    printf("請輸入要檢查的身分證字號:");
    scanf("%10s", &str);

  關於字串這裡要補充一點。我們知道字串實際上就是很多個 char 組成的 char 陣列,而且裡面每個位元存的都是一個 0~255 的數字,只是經由 ASCII 碼表轉換而已(這點我在《跟著豬腳 C 起來:各式各樣的資料型態》有講過),比如我們在一個長度為 16 的 char 陣列存入「A123456789」,這個陣列的內容就會是:

  {65, 49, 50, 51, 52, 53, 54, 55, 56, 57, 0, 0, 0, 0, 0, 0}

  (以上用十進制表示)

  一般來說,0 在 ASCII 碼表上的意義是空字元,用在 C 語言的字串的時候可以表示一個字串的結束點,也就是說系統只要讀取到 0 就會認為這個字串已經讀取完畢,後半段的東西就會完全當作沒看見,你可以實驗看看:

    char str[16] = "ABC123456789";
    str[4] = 0;
    printf("%s", str);

  我們把 str[4] 這個 byte 的值強制歸零,使得這個陣列的內容變成:

  {65, 66, 67, 49, 0, 51, 52, 53, 54, 55, 56, 57, 0, 0, 0, 0}

  我們再直接把 str 的內容 print 出來,會得到「ABC1」的結果——系統發現 str[4] 的值是 0,認為這個字串已經結束了,因此只會把 str[0]、str[1]、str[2]、str[3] 當作是這個字串的有效部分。

  這個 0 很重要!在 C 語言裡,任何的字串都需要用到 0 來當作結束標誌。如果你宣告了一個長度為 16 bytes 的字串,那就代表它只能存 15 個字元,因為你必須留一個空間給 0 作為結束標誌來使用。

  如果我們把最後一個 byte 強制填入有效的字元,就會導致系統繼續讀取下去,有一定的概率接著輸出相鄰記憶體的內容:



  這當然是一件很危險的事情。寫程式的時候,最害怕的事情就是 overflow(溢位),如果是自己寫來跑點簡單任務的東西或許無傷大雅,但如果想寫的程式有重要用途或有一定安全性的需求,我們就應該在開發階段就先避免任何可能會導致溢位的設計,因為有能力的駭客會利用這種記憶體的溢位來挖掘漏洞,甚至藉此取得系統控制權限,而且這種事情在程式設計的領域已不鮮見。

  如果是想寫個「堪用的程式」,這篇已經可以算是最後一片拼圖了(當然這不是本系列的最後一篇)。不管寫得醜不醜,至少你已經把初級工具包蒐集完畢:輸出、輸入、變數、資料型態、條件分歧、陣列、迴圈。這些就算拿到不同的程式語言上面一樣通用,只是寫法或用法細節稍有不同而已。

  ——C 語言系列搞了這麼多篇,學寫程式怎麼可能不做題目呢?有興趣的話可以利用這系列到目前為止教過的內容,試著做做看:

  【第一題】
  1. 令使用者輸入一串文字(用 32 bytes 的 char 陣列儲存)
  2. 讓程式自動計算該串文字裡面有幾個大寫英文字母、幾個小寫英文字母、幾個數字

  【第二題】
  1. 令使用者輸入 5 組整數(直接用 int 儲存)
  2. 讓程式自動找出 5 組數字裡面最大的數和最小的數

  【第三題】
  1. 令使用者輸入兩組正整數,分別存入 x 和 y
  2. 讓程式自動計算 x+y 的值並顯示出來,不能有精確度的遺失
  3. x 和 y 各可以達到最多 50 位數,位數可以不同(比如 x 有 37 位、y 有 42 位)
  4. 全程不使用到 float、double、long

  做完不會有獎品,但你一定會有收穫。

  やらないか。

  
 
引用網址:https://home.gamer.com.tw/TrackBack.php?sn=4941702
All rights reserved. 版權所有,保留一切權利

相關創作

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

留言共 20 篇留言

雪之王女‧F‧巧可奈
純推

10-08 09:18

1
感覺這篇會紅,先卡

10-08 09:19

萬念俱灰的人最強
勃起

10-08 09:20

腦內模擬
fputs fgets是c裡面自由格式解析最重要的函數,在c++則是getline/*因為這個是範圍讀入中對資料操作最小的*/

10-08 09:27

我喜歡吃飯

10-08 10:03

迷幻啾啾
啊…豬腳好會C哦…

10-08 10:05

Albert阿伯

10-08 10:06

雞塊
scanf("%d%d")跟scanf("%d %d")好像都能輸入 但我不知道有沒有差

10-08 10:10

以下揭曉
學到了,謝謝豬腳

10-08 10:10

美好的過去漸行漸遠
回樓上上,我記得沒差==

10-08 11:13

福利熊送幸福
我一直在思考第一台電腦怎麼輸入程式ㄉ

10-08 13:06

解凍豬腳
最早期的「程式」是實體的、物理的,簡單來說這會建立在工程師的電路設計上
之後發展一陣子,工程師會直接用機器碼/組合語言去寫,弄好編譯器的雛形以後才有現代的程式語言10-08 13:53
熾心凝
字串最後面不是應該是'\n'嗎

10-08 16:40

芊芊∣ㄑㄑ
完全看不懂,但用心給推...

10-08 20:45

阿狐八逼蹦
int ans;
printf("請問豬腳484甲?(yes or no)");
scanf("%d",&ans);

10-08 22:49

解凍豬腳
yes/no 這樣的答案必須用 char[] 來儲存10-09 08:49
羊奶
你是不是在刷leetcode

10-08 23:10

解凍豬腳
我才沒有這麼勤奮 [e6]10-09 09:16
LeoKuo
回上*4 我記得\n 應該是表示換行
字串如果不足設定的 通常後面都會省略補0

10-08 23:24

熾心凝
我打錯,是'\0'

10-09 03:45

解凍豬腳
"\0" 的意義就是空字元,一樣的概念(只是差在你有沒有特地把它打出來而已)
以控制字元「\」來表示 ASCII 字碼,通常用八進位或十六進位
例如「A」的 ASCII 字碼編號是 65,十六進制表示是 41,八進制是 101
那你可以用 "\x41" 或 "\101" 來表示 "A"10-09 09:16
梧優
LAO超會C

10-09 09:22

鹹粥´・ω・)
豬腳好會C

10-09 14:06

我不是丁守中
菜雞想問個第三題怎麼解

10-19 23:16

我要留言提醒:您尚未登入,請先登入再留言

54喜歡★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)

未分類 (1)

e12344888各位讀者
都市奇幻懸疑喜劇《魔都妖探》Case 9連載開始。歡迎舊雨新知都來小屋坐坐!看更多我要大聲說昨天16:51


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

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