搜尋此網誌

2022年3月11日 星期五

C 語言作業 - 身份證是否合法之輸入部份

緣起:


    昨天有同學 LINE 我,拿了 C 的題目給我看,是大一同學的作業,跟我們那時一樣,大一下要學程式設計,題目應該也是差不多啦,只是會再做些變化,可能是要避免學弟妹直接抄學長姐的程式碼。

    總之,這次的題目有個小麻煩的地方,就在輸入部份。


    不能用字串輸入還滿麻煩的,要想點別的方法,而且換了方法後也會碰上些問題,花了我不少時間在想要怎麼解決那些問題,所以就打算寫文章來記錄下。


分別輸入字元與數字:


    不能輸入字串的話,那就分成 "輸入一個字元跟九個數字" 就好啦,首先要有個字元變數跟整數陣列,大小為 9。


    由於程式要能一直輸入,所以我們要用一個 while(1) 迴圈把我們程式要做的事都包起來,首先讀字元的部份很好處理,輸入後我們還能先判斷輸入是否合法,不合法的話就直接用 continue 來回到 while 的開始。

    
    PS: C 的輸入是原本是要寫 scanf,不過在 visual studio 裡,它們的編譯器要我寫成 scanf_s,就... 它有自己推薦的一套寫法。

輸入一位的整數:


    我沒辦法輸入完字元後,直接用 for 迴圈來把接下來輸入的數字都依序放到 input_numbers 裡,因為假如我寫這樣。


    我輸入 A123456789 後,它還會繼續等待我的輸入,因為 123456789 被視為一個數字,所以我只完成了 1 個數字的輸入,還有 8 個要輸入。那要怎麼讓 C 每次就只讀一個位數的整數 ?

    其實不難,我在這裡找到解答,scanf 那邊寫成 "%1d" 就 OK 了。

最後多個 printf 看看結果

輸入 A123456789,每個數字都有成功讀入


如何判斷輸入的型態錯誤:


    就我所知,C 好像沒有 try catch 那種例外處理的東東,所以,如果有人在程式要他輸入數字時,他卻輸入字元的話,要怎麼辦呢 ?

我在輸入 9 個數字中間插入一個字元,程式就整個亂了

    一樣在 stackoverflow 找到方法,他說,scanf 會回傳 "成功輸入的參數的個數",所以我可以用 scanf 的回傳值是否小於 1 來判斷輸入是否合法。

    在進入 for 迴圈前,我弄個 bool 變數,is_numbers_ok ,用來判斷 9 個數字的輸入是否都合法,在 for 迴圈裡,如果發現有一個輸入不合法,那就把 is_numbers_ok 設成 false,然後跳出 for 迴圈,跳出 for 迴圈後,可以用 is_numbers_ok 來判斷整個數字的輸入是否都合法,不合法的話,一樣,用 continue 回到最外層 while 迴圈的開始。


oh ya ~ 中間輸入非數字時,程式能找錯了


讀取到多餘的輸出:


    最後一個問題了,如果我的程式輸入的開頭不是字母,像是輸入 1234567890,結果會變這樣。


    它讀到的第一個 1 不是字母,就回報輸入錯誤,然後回到 while 一開始,繼續要求使用者輸入,然而,我一開始打的數字,後面的 23456789,甚至是換行,也被它當成是接續的輸入值,重覆又讀了好幾次,就變成上面看到的樣子。

    說實在的,我也不太清楚這問題叫什麼,印象中有聽老師說過,好像是跟鍵盤的 buffer 有關,所以我就去找有沒有什麼方法可以清除 scanf 的 buffer,有人說要用 fflush(stdin),不過我把它加到程式裡面後,還是沒什麼變化。最後,我找到了一個有用的方法,那就是在 while 最後加上這個。


    getchar() 可以得到一個輸入的字元,用 while 重複讀取,把那些多餘的輸入給吃掉。由於我們是按 Enter 來輸入的,所以你不管輸入什麼,最後都一定會有一個 '\n',讀到它就結束。


2022/3/16 更新:


    對了,判斷輸入正不正確那邊,在 continue 前也要記得加個 while 迴圈來抓那些多餘的輸入,不然程式會出錯。




沒有留言:

張貼留言