5.1.4 再來一個C庫函式getchar吸收Enter鍵
Enter鍵也是一個字元,在使用scanf的時候,輸入完畢要按下Enter鍵,這時候Enter鍵也會被輸入到stdin流中,會搞亂我們的程式。
注意:stdin是輸入流,stdout是輸出流,這兩個流就是在記憶體中流進流出的資料,根據流向不同命名也不同。
比如以下程式碼執行後,
#include <stdio.h> void main() { int b; char f; printf("please input int:"); scanf("%d", &b); printf("please input char:"); scanf("%c", &f); printf("b = %d, f = %c", b, f); }
執行結果如圖5.7,
圖5.7 Enter鍵被變數f吸收的結果
原本以為,根據程式碼的邏輯操作:先輸入變數b的值,然後按下回車,再輸入變數f的值,然後再回車,最後printf這兩個變數的值,皆大歡喜!
沒想到實際操作中:輸入了100賦值給變數b,再按下回車就輸出瞭如圖5.7的結果。
仔細想想,輸出結果中,“f = ” 後面感覺換了一行,聯想到平時在使用word或者txt打字的時候,Enter鍵也有換行的作用,那麼現在就有理由相信,Enter鍵賦值給了變數f。可能筆者之前沒有講明,Enter鍵也是一個字元,就像a、b、c、d一樣,是可以賦值的。為了吸收這個Enter鍵,可以使用C庫函式getchar,更改後,程式碼如下,其實就是在scanf後面新增一句getchar來吸收輸入流,
#include <stdio.h> void main() { int b; char f; printf("please input int:"); scanf("%d", &b); getchar(); printf("please input char:"); scanf("%c", &f); printf("b = %d, f = %c", b, f); }
結果如圖5.8,
圖5.8 新增getchar吸收Enter鍵
讀者肯定這時候會有困惑,到底什麼是標準輸入流stdin,什麼是標準輸出流stdout,為啥使用了scanf後要用Enter鍵,筆者一時半會也解釋不清,先把疑問擱著,說不定後續慢慢就能明白這些概念了,先明白怎麼使用吧,在多次使用中瞭解它們的用意。
5.1.4 第一次自主練習題,做個簡單的註冊功能
學習寫程式,一定要多練習,多上機,機你太美!這是肺腑之言,更是經驗之談。
題目:做個註冊功能介面,輸入賬戶,輸入密碼,輸入性別,然後顯示出來。
思路:第一次使用微信,第一次使用抖音,第一次使用部落格園的時候,都會有個註冊功能,註冊功能就是填寫基本資訊。
由於現在掌握的知識有限,做不到輸入姓名名字,也做不到輸入一長串數字如身份證號碼等,所以加了個限制,就讓賬戶名是一串數字吧,並且要在int的可容許範圍內,也就是第四章檢視錶4.1中,整型範圍在-2,147,483,648 到 2,147,483,647之內的數字,密碼也是如此,至於性別就暫時用‘m’(male)代表男性,‘f’(female)代表女性。很簡單吧,開始練習吧。練習完以後,可以檢視筆者給出的參考程式碼,如下:
#include <stdio.h> void main() { int account; int passwd; char sex; printf("歡迎進入註冊介面!\n"); printf("請輸入賬戶名:"); scanf("%d", &account); getchar(); printf("請輸入密碼:"); scanf("%d", &passwd); getchar(); printf("請輸入性別,m代表男性,f代表女性:"); scanf("%c", &sex); printf("註冊成功,賬戶名是%d, 密碼是%d, 性別是%c \n", account, passwd, sex); }
執行結果圖5.9,
圖5.9 執行結果
程式碼解析:
1. 變數名,可以是單詞account還有sex等?之前有講過,變數名可以使用英文單詞或者自己建立的字母組合,如果不想用英語的話,可以給變數名取名為zhanghu,但是變數名不可以用C語言關鍵詞,比如int,char等。變數名也可以新增下劃線,這個看個人口味了。
2. 可以輸出中文?因為有的編譯器支援中文輸出,很榮幸,Dev-C++是支援的,之前不用是為了鼓勵使用英文。現在還是建議儘量使用英文。
3. 在printf中,“\n”是啥?在ASCII中,它代表換行符,是轉義字元中的一個,有了它,就能輸出一個Enter鍵的效果。C語言中有多個轉義字元,後續逐步介紹。
5.2 運算子
5.2.1 加減乘除取餘運算
回顧之前的變數,printf,scanf,有了它們,就能夠製作簡單的計算器了。
在鍵盤中,找幾個按鍵,其中,“+”可以用在加法上,“-”可以用在減法上,“*”用在乘法上,“/”用在除法上,“%”用在取餘數上,“=”表示賦值。
小學學習加減法的時候,一般這麼寫運算表示式:x1+x2=y;
在C語言中,由於“=”這個賦值表示式是從右往左邊賦值,所以要這麼寫y=x1+x2;體現在程式碼中,如下:
#include <stdio.h> void main() { int x1, x2; int y; x1 = 100; x2 = 50; y = x1 + x2; printf("x1 + x2 = %d \n", y); }
執行後輸出結果是:x1 + x2 = 150
注意:C語言支援變數名後面加數字。
讀者可以自行吧“+”改為“-”或者改為“*”或者改為“/”或者改為“%”,試試看結果,就能夠知道“-”為減法運算子,“*”為乘法運算子,“/”為除法運算子,“%”為取餘運算子。
注意:取餘的意思就是求兩個數相除的餘數,比如100除以50的餘數為0,100除以49的餘數為2。
掌握了以上,就可以做個簡單的加減乘除計算器了,希望讀者自行完成,功能就是輸入兩個數,然後輸出這兩個數的運算結果。
5.2.2 混合表示式及運算優先順序
小學題,已知表示式y = x1 + x2 * x3,且x1等於10,x2等於5,x3等於7,求y值?
結果是多少,一目瞭然,按照正常思維,乘法運算的優先順序高於加法運算,所以應該先計算x2*x3得35,然後再計算加法,得到y值等於45。
C語言中也是如此,運算子那麼多,應該誰先誰後,都是規定的死死的,如表5.1,
優先順序 | 運算子 | 結合律 | |
---|---|---|---|
1 | 字尾運算子:[] () · -> ++ --(型別名稱){列表} | 從左到右 | |
2 | 一元運算子:++ -- ! ~ + - * & sizeof_Alignof | 從右到左 | |
3 | 型別轉換運算子:(型別名稱) | 從右到左 | |
4 | 乘除法運算子:* / % | 從左到右 | |
5 | 加減法運算子:+ - | 從左到右 | |
6 | 移位運算子:<< >> | 從左到右 | |
7 | 關係運算子:<<= >>= | 從左到右 | |
8 | 相等運算子:== != | 從左到右 | |
9 | 位運算子 AND:& | 從左到右 | |
10 | 位運算子 XOR:^ | 從左到右 | |
11 | 位運算子 OR:| | 從左到右 | |
12 | 邏輯運算子 AND:&& | 從左到右 | |
13 | 邏輯運算子 OR:|| | 從左到右 | |
14 | 條件運算子:?: | 從右到左 | |
15 | 賦值運算子: = += -= *= /= %= &= ^= |= <<= >>= |
從右到左 | |
16 | 逗號運算子:, | 從左到右 |
表5.1 運算子優先順序規定表
哇塞,運算子那麼多,還有的沒用過呢?記不住啊,我太難了,好累啊!
沒辦法,這些都得記住,但不是現在馬上全部記住,用著用著就能夠記住的,相信我,先把這份表收藏,用的時候拿出來看,要死記硬背也行,看個人習慣怎麼記憶了。
請記住,C語言運算子遵循一個原則,優先順序最高先運算,同級別的從左往右運算。
比如,一個表示式 (x1+x2*x3)/(x4-x5+x6-x7)中,
括號等級最高,所以先運算括號運算子,有兩個括號運算子,所以這是同級別運算,先運算左邊的括號,在左邊的括號中(x1+x2*x3),有加法有乘法,先執行高等級的乘法,然後再執行加法。然後執行右邊的括號運算裡面的表示式(x4-x5+x6-x7),有加法有減法,是同級別的運算,所以先運算左邊的減法再依次運算加法和減法,最終把兩邊運算的值進行除法計算即可。
5.2.3 表示式練習題之求平均數
要求:輸入三個整數,求它們的平均值。簡單吧,程式碼如下:
#include <stdio.h> void main() { int x1, x2, x3; int y; printf("please input three data: \n"); scanf("%d, %d, %d", &x1, &x2, &x3); getchar(); y = (x1 + x2 + x3)/3; printf("average y = %d\n", y); }
編譯執行後,輸入2,4,6得到結果:average y = 4。
但是如果輸入3,5,6得到的結果居然也是:average y = 4。開啟計算器,計算出平均值為3.666666......
這是由於計算機計算精度不同導致的,由於整型int只能精確到小數點左邊,也就是int取值範圍在-2,147,483,648 到 2,147,483,647,所以為了精度高一些,可以用上float型別,它的取值範圍是1.2E-38 到 3.4E+38。
改進後,程式碼如下:
#include <stdio.h> void main() { float x1, x2, x3; float y; printf("please input three data: \n"); scanf("%f, %f, %f", &x1, &x2, &x3); getchar(); y = (x1 + x2 + x3)/3; printf("average y = %f\n", y); }
這時候,再輸入3,5,6得到的結果就是:average y = 4.666667。
修改的部分有,1. 宣告的型別由int改為float。
2. scanf中,%d改為%f。
3. printf中,%d改為%f。
有了這些修改就能夠支援精度高的浮點型float資料運算了。
5.2.4 表示式練習題之求個位數和萬位數的和
出這個題純粹練習思維,題:輸入一個5位數的整型,求個位數和萬位數的和。
希望讀者自行編寫完程式後,再看參考程式碼。
大體思路:通過scanf輸入一個5位數,比如輸入的是32145,取個位5,取萬位數3,求和。
具體思路:
1. 定義一個變數用來存放上面所說的32145,定義一個變數用來存放個位數,定義一個變數用來存放萬位數,定義一個變數用來存放個位和萬位的和,總共需要定義四個變數。
2. 求個位數,需要用到取餘表示式,即32145%10。開啟草稿紙,如圖5.10所示,計算32145除以10的餘數為5,剛好就是獲得的個位數,
圖5.10 計算32145%10的結果
3. 求萬位數,只需要用到除法表示式,即32145/10000,要開啟草稿紙算也行,筆者就不發圖了。
4. 計算個位數和萬位數的和。程式碼如下:
#include <stdio.h> void main() { int data; int first, fifth; int getAddWorth; printf("please input a 5 digit data\n"); scanf("%d", &data); getchar(); first = data % 10; fifth = data / 10000; getAddWorth = first + fifth; printf("data = %d, first = %d, fifth = %d, getAddWorth = %d \n", data, first, fifth, getAddWorth); }
執行後,輸入32145可得getAddWorth的值為8,正解!
注意:變數命名也可以由大寫字母和小寫字母的組合,如getAddWorth。
關鍵的擴充,為了自身打鐵能力過硬,可以給自己出些更苛刻的題,剛才的題給出了思路,以下的題建議自行完成,如果實在完成不了,讀者可以在評論區索要正確答案。
題1:一個六位數中,取千位數和十位數的和。
題2:一個六位數中,個位數和萬位數調換位置,輸出結果。