寫這篇博客的起因是最近博主自己學習中總是遇到類似的錯誤,并曾百思不得其解。
今天分享出來是希望幫助大家在寫代碼時避免這些錯誤。話不多說,我們直接開始吧!
勤時當勉勵 歲月不待人
C/C++ 游戲開發(fā)
一.scanf的用法
- 我們先來看看再MSDN里對scanf的解釋
- scanf 的功能用一句話來概括就是“通過鍵盤給程序中的變量賦值”。 - 下面來講講它的兩種基本用法:
1. scanf(“輸入控制符”, 輸入參數);
功能:將從鍵盤輸入的字符轉化為“輸入控制符”所規(guī)定格式的數據,然后存入以輸入參數的值為地址的變量中。
- 在通常情況下,我們不希望某個值是由我們程序員指定的,而是在程序運行中由用戶從鍵盤輸入的,這更能滿足在日常使用時用戶的需要,提高我們程序的靈活性
- 用 scanf 即可實現即可很好的滿足我們的要求:
# include <stdio.h>
int main()
{
int n=0;
scanf("%d", &n); //&n 表示取變量 n 的地址,&是取地址符
printf("n = %d\n", i);
return 0;
}
-
上面這個基本的程序中,有以下兩點需要注意:
-
(1)我們從鍵盤輸入的全部都是字符。比如從鍵盤輸入 125,它表示的并不是數字 125,而是字符 ‘1’、字符 ‘2’ 和字符 ‘5’。
操作系統(tǒng)在接收鍵盤數據時會將它當成字符來接收。這時就需要用“輸入控制符”把它轉化成相應的內容(如%d 是有符號十進制數 %f 是浮點數)。 -
上面代碼中的%d就是要將從鍵盤輸入的這些合法的字符轉化成對應的十進制數字。比如經過 %d 轉化之后,字符 125 就是數字 125 了。
-
(2)&是一個取地址運算符,&加變量名表示“該變量的地址”,所以&n就表示變量 n 的地址。又稱為“取地址n”,相當于將數據存入以變量 n 的地址為地址的變量中(即存入變量n的地址中)。也就是把轉化后的數字125放到變量 n 中
-
總的來說
scanf 語句的意思就是:從鍵盤上輸入字符 125,然后%d將這三個字符轉化成十進制數 125,“&n” 找到變量 n 的地址,把數字 125 放到以變量 n 的地址為地址的變量中,即變量 i 中,所以最終的輸出結果就是n=125。
注意:
int main()
{
char n[20] = {0};
printf("請輸入:>");
scanf("%s", n);
}
- 很多初學者看到這段代碼可能會想:這個scanf中沒有加&n,會不會是錯的?
- 恭喜你?。?!---------------------------------------------------回答錯誤
- 我們要透過代碼看到其本質,這段代碼在使用時,是把輸入的字符串放到一個名字為n的char類型的數組的首地址中,而不是變量n中,把輸入值放在地址里,當然是對的。
2.scanf(“輸入控制符非輸入控制符”, 輸入參數)
這種用法我是墻裂建議大家在平時敲代碼時不要去使用的,因為在使用過程中對用戶非常不友好。但咱們這里是介紹用法,還是簡單介紹一下,順便講講改進的方法。
# include <stdio.h>
int main(void)
{
int n;
scanf("n = %d", &i);
printf("n = %d\n", i);
return 0;
}
- 在 scanf 中,所有的“非輸入控制符”都要原樣輸入。
- 接下來我來講講為什么不推薦使用這種用法
- 這種輸入方法必須滿足原樣輸入,當用戶使用時,但凡輸入的和你設置的格式有一點不同都不行,哪怕只是多或者少了一個空格。
- 比如要從鍵盤給變量 n 賦值 123,那么必須要輸入n=123才正確,少一個或者多一個都是錯誤的。
改進方法:
int main()
{
int n;
printf("請輸入 n = ");
scanf("%d", &n);
printf("n = %d\n", n);
return 0;
}
-
通常在輸入前我們加上類似“請輸入 n = ”這種代碼的目的是提示用戶應該輸入什么內容,改善用戶的使用體驗。
-
具體效果
-
這樣改進既改進了我們的輸入格式,又不至于在使用scanf時出錯。
輸入多個參數
# include <stdio.h>
int main(void)
{
int m, n;
scanf("%d%d", &m, &n);
printf("m = %d, n = %d\n", m, n);
return 0;
}
-
通過鍵盤給多個變量賦值與給一個變量賦值其實是一樣的。比如給兩個變量賦值就寫兩個 %d,然后“輸入參數”中對應寫上兩個 “取地址變量” ;給三個變量賦值就寫三個 %d,然后“輸入參數”中對應寫上三個 “取地址變量” ……
-
從鍵盤輸入數據時,給多個變量賦的值之間一定要用空格、回車或者 Tab 鍵隔開,用以區(qū)分給不同變量賦的值。而且空格、回車或 Tab 鍵的數量不限。一般使用一個空格即可。
3.scanf的返回值
- scanf的返回值我有一篇博客有具體介紹,這里不過多綴敘,博客鏈接如下:關于C語言中scanf多組輸入的實現
二.getchar的用法
1.getchar的返回類型及使用效果
- getchar常用來讀取字符
- 以下為msdn中的解釋
int getchar(void)
返回類型為int,參數為void.
getchar返回的其實是字符的ASCII碼值(整數)。
getchar在讀取結束或者失敗的時候,會返回EOF(end of file,本質上是-1.)。
- 接下來通過代碼簡單解釋一下
#include<stdio.h>
int main()
{
int n = 0;
while ((n = getchar()) != EOF)//判斷返回值是否是EOF
{
putchar(n);//打印輸入的n
}
return 0;
}
注意:
- 使用getchar時,每次getchar只會讀取一個字符
- 如果上面的代碼不用while循環(huán)的話,輸入123,putchar就只會輸出1。
三.幾種常見錯誤詳解
1.不理解原理導致的錯誤
- 下面以getchar為例具體講解一下這種錯誤的產生及解決方法
- 代碼如下:
#include<stdio.h>
int main()
{
char password[20] = {0};
printf("請輸入密碼:");
scanf("%s", password);//以字符串的形式輸入
printf("請確認密碼(Y/N):>");//用戶輸入Y/N確認
int ch = getchar();
if (ch == 'Y')
{
printf("確認成功\n");
}
else
{
printf("確認失敗\n");
}
return 0;
}
- 來看看這段代碼運行的結果
- 嗯?什么情況,我還沒輸入Y或N怎么就確認失敗了??
- 好了,這里我就不賣關子了。
- scanf和getchar這兩個輸入函數,它們都是從鍵盤上得到我們的數據,而不是直接從鍵盤上來讀取我們的數據。它們和鍵盤之間有一個區(qū)域叫輸入緩沖區(qū)。所有輸入的數據都會先放在輸入緩沖區(qū)中。
- 在存放輸入的數據時,輸入函數先來看看輸入緩沖區(qū)中是否有數據,如果有,它就直接拿走并儲存,而不需要從鍵盤再輸入數據,如果輸入緩沖區(qū)中什么都沒有,則需要從鍵盤輸入,再拿走。
- 帶入上面的代碼試試
- 當我們輸入123456時,為了把“123456”放進去,其實還敲了一個回車,因此實際上輸入緩沖區(qū)中存放的是“123456\n”。
-
程序繼續(xù)運行,此時它把“123456”提取出來,輸入緩沖區(qū)中還留有一個“\n”.
-
注意:
程序走到這一步后,進行第二次從鍵盤中讀取( int ch = getchar() ),此時輸入緩沖區(qū)中還滯留有上次未提前出來的“\n”,因此不再從鍵盤上讀取數據,直接把“\n”從輸入緩沖區(qū)提取出來。此時ch的地址中存放的就是“\n”,顯然不等于’Y’,所以輸出為“確認失敗”
看了上面的講解,你弄懂了嗎?接下來我們來講講改進方法
- 其實改進很簡單,它不是在輸入緩沖區(qū)中還滯留有“\n”嗎?我再使用一個輸入函數把它給讀走不就行啦?
int main()
{
char password[20] = { 0 };
printf("請輸入密碼:");
scanf("%s", password);
printf("請確認密碼(Y/N):>");
getchar();//把多余的\n取走
int ch = getchar();
if (ch == 'Y')
{
printf("確認成功\n");
}
else
{
printf("確認失敗\n");
}
return 0;
}
- 這種方法雀氏可行,但是如果這樣呢?
請輸入密碼:12345 6(中間加空格)
- ?怎么又這樣了??我不是把“\n”讀走了嗎?
- 解釋億下:
- 此時輸入緩沖區(qū)中是這樣的。
- 輪到scanf來取緩沖區(qū)中的數據,當它讀到空格的時候,它就不再繼續(xù)往下讀了(這是scanf的一個作用性質)。
- 所以scanf就只取走了12345,而緩沖區(qū)中還剩下(空格)6\n。
- 此時,getchar()讀取一個字符,它把空格給讀走了,輸入緩沖區(qū)中剩下6\n.
- 最后,int ch = getchar()把6給讀走,不等于’Y’,于是打印“確認失敗”
- 難道沒有什么辦法避免這種錯誤嗎?
- 什么話,沒有辦法我會把這種錯誤寫出來嗎??這不是自己打自己臉嗎?
- 解決方案
介于輸入緩沖區(qū)中一直存放有數據未被清理,我們需要把緩沖區(qū)中多余的數據先全部清走。 - 方式:
采用一個循環(huán),只要沒讀到\n,我們就一直用getchar讀。 - 代碼實現如下:
#include<stdio.h>
int main()
{
char password[20] = {0};
printf("請輸入密碼:");
scanf("%s", password);
while ( getchar() != '\n');//把緩沖區(qū)中多余的內容全讀走,直到\n停止
printf("請確認密碼(Y/N):>");
int ch = getchar();
if (ch == 'Y')
{
printf("確認成功\n");
}
else
{
printf("確認失敗\n");
}
return 0;
}
- 結果:
- 完美解決
2.輸入參數不符合輸入控制符要求
- 比如以下代碼:
# include <stdio.h>
int main(void)
{
char m;
int n;
scanf("%c%d", &m);
printf("m = %c, n = %d\n", m, n);
return 0;
}
- 不做過多解釋,scanf中輸入控制符要求你輸入兩個數據,結果你的輸入參數只輸入了一個,你覺得這可能正確嗎?
- 但其實對于多組輸入來說,不輸入正確個數的數據也有一定意義,詳情可以看看我的這篇博客:關于C語言中scanf多組輸入的實現
- 需要注意的是:
- 一但發(fā)生這種錯誤時,編譯器可能并不會報錯,但是從程序上來說它是絕對錯誤的,當發(fā)現異常時,一定要多多注意認真檢查一下輸入函數。
總結
-
以上就是今天要講的所有內容啦
有任何疑問歡迎在評論區(qū)或者私信博主指出哦。 -
大噶(家)下次見啦!
如果感覺有幫助的話不妨三連一下這個新人博主。你們的支持就是我更新的動力。文章來源:http://www.zghlxwxcb.cn/news/detail-745674.html
(可莉請求你們三連支持一下博主?。?!點擊下方評論點贊收藏幫幫可莉吧)文章來源地址http://www.zghlxwxcb.cn/news/detail-745674.html
參考博客
- C語言中scanf函數用法詳解
- 關于getchar的用法及實例解析
到了這里,關于關于【C語言】中scanf與getchar的用法和常見錯誤詳解的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!