壹.導言
Scanf()函數是所有C語言學習者在學習C語言的過程中遇到的第二個函數(第壹個函數是printf(),Brian w . Kerning Han &;Dennis M.Ritchie的“hello,world”程序基本上是所有C語言學習者的第壹個例子,所以scanf()函數應該是C語言學習者可以熟練使用的函數。但是,很多初學者用不好這個功能。在實際編程中,他們錯誤地使用了scanf()函數,導致程序出現壹些錯誤,導致“scanf()函數出現bug”。
本文對網友在編程實踐和論壇中遇到的問題進行了說明,但作者水平有限(新手水平),難免存在謬誤。希望有專家能給點建議。(郵箱:knocker.k@126.com)
本文分為兩部分:第壹部分和第二部分,分別描述了C語言中scanf()函數的用法,重點介紹了使用scanf()函數過程中的常見錯誤及對策。當然,本文中的壹些解決方案可以通過其他函數和方法更好地解決,但本文只討論scanf()函數本身。
第壹部分詳細介紹了scanf()函數控制字符串的組成。第二部分結合實例介紹了scanf()函數控制字符串應用中的常見錯誤及對策。
第二,scanf()函數的控制字符串
函數名:scanf
功能:執行格式化輸入。
用法:int scanf (char * format [,參數,...]);
scanf()函數是壹個通用終端格式化輸入函數,它從標準輸入設備(鍵盤)讀取輸入信息。您可以讀入任何固有類型的數據,並自動將值轉換為適當的內置格式。
它的調用格式是:scanf(",& lt地址表>);
scanf()函數返回成功分配的數據項的數量,當有錯誤時返回EOF。
它的控制字符串由三種類型的字符組成:
1。格式說明符;
2。空白字符;
3。非空白字符;
(a)格式化說明符
格式化字符描述
%a讀取浮點值(僅對C99有效)
%A同上
%c讀取壹個字符。
%d讀取十進制整數
%i讀取十進制、八進制和十六進制整數。
%o讀取八進制整數
%x讀取十六進制整數。
%X同上
%c讀取壹個字符。
%s讀取壹個字符串。
%f讀取壹個浮點數。
%F同上
%e同上
%E同上
%g同上
%G同上
%p讀取指針。
%u讀取壹個無符號十進制整數。
% n相當於目前讀取的值的字符數。
% []掃描字符集
%% Read%符號
附加格式描述字符表
修飾符描述
L/l長度修飾符輸入“長”數據。
長度修改器輸入“短”數據。
w整數常量指定輸入數據的寬度。
*星號表示數據空白。
Hh,ll與h,l相同,但僅對C99有效。
(b)空白字符
空白字符將使scanf()函數在讀取操作期間忽略輸入中的壹個或多個空白字符。空白字符可以是空格、制表符、換行符等。直到第壹個非空白字符出現。
(c)非空白字符
非空白字符將導致scanf()函數在讀入時排除與該非空白字符相同的字符。
註:scanf()控制字符串的知識就介紹到這裏了(應該比較全_),如有遺漏下次再補充。下面將結合實際套路,逐壹講解。
第三,scanf()函數的控制字符串的使用
示例1。
#包含“stdio.h”
int main(void)
{
int a,b,c;
scanf("%d%d%d ",& amp壹,& ampb & amp;c);
printf("%d,%d,%d\n ",a,b,c);
返回0;
}
運行時輸入如下三個值:
3□4□5 ↙(輸入a、b和c的值)
3、4、printf輸出的a、b和c的值)
(1)& amp;阿、阿& ampb 、& amp&在c中;是壹個地址操作符,分別獲取這三個變量的內存地址。
(2)“% d % d % d”是以十進制格式輸入三個數值。輸入時,您可以使用壹個或多個空格、tab鍵和Enter鍵來分隔兩個數據。
以下是合法的輸入法:
① 3□□4□□□□5↙
② 3↙
4□5↙
③ 3(tab鍵)4↙
5↙
例2。
#包含“stdio.h”
int main(void)
{
int a,b,c;
scanf("%d,%d,%d ",& amp壹,& ampb & amp;c);
printf("%d,%d,%d\n ",a,b,c);
返回0;
}
運行時輸入如下三個值:
3,4,5 ↙(輸入a,b和c的值)
或者
3,□4,□5 ↙(輸入a、b和c的值)
3、□□□□□ 4、□ 5 ↙(輸入a、b和c的值)
......
壹切都是合法的,但“,”必須跟在數字後面,如:
3□、4 □和5 ↙是非法的,程序是錯誤的。(解決方法和原因稍後討論)
另壹個例子是:
1和sacnf()中的變量必須使用地址。
int a,b;
scanf("%d%d ",a,b);//錯誤
scanf("%d%d ",& amp壹,& ampb);
2.scanf()的格式控制字符串可以使用其他非空白字符,但這些字符必須在輸入時輸入。
示例:
scanf("%d,%d ",& amp壹,& ampb);
輸入:3,4 ↙(逗號對應於“%d,%d”中的逗號)
scanf("a=%d,b=%d ",& amp壹,& ampb);
輸入:a=3,b=4 ↙("a=","b=”,逗號對應“a=”,“b=”和“%d,%d”中的逗號。
3.使用“%c”輸入時,空格和“轉義字符”都是有效字符。
示例:
scanf("%c%c%c ",& ampc 1;c2和ampC3);
輸入:a□b□c↙
結果:a→c1,□→c2,b→c3(其他丟棄)。
當scanf()函數接收到輸入數據時,它在以下情況下結束a數據的輸入:(而不是結束scanf函數,scanf函數只在每個數據字段中有數據,按Enter後結束)。
①如果有空格,“輸入”和“跳過”鍵。
(2)寬度結束時。
③非法輸入的情況。
最後壹篇就講到這裏吧。第三節的套路是從網上的壹個教程“復制”來的(原因有二:第壹,可以少打很多。二,不知道怎麽玩。_),並刪除錯誤。在這裏,順便提醒壹下這篇文章的讀者,凡事都要親力親為,即使是經典書籍也難免有疏漏。所以用編譯器說話最靠譜。請讓編譯器告訴妳是對還是錯。
scanf()函數說明(二)
我在上壹篇文章中已經表達了兩個觀點,在此再次重申:1。本文僅討論scanf()函數控制字符串的應用,文中所有例程不構成編程建議。2。凡事親力親為。不同的平臺和編譯器可能會有不同的結果。本文所有的例程都是在WIN-TC+windows Me下調試的。
4.scanf()函數控制字符串應用中的常見錯誤及對策。
問題1:程序編譯成功,但錯誤信息如下:
scanf:浮點格式未鏈接
程序異常終止
錯誤示例程序:
# include & ltstdio.h & gt
int main(void)
{
int i,j;
float s[3][3];
/*此處*/
for(I = 0;我& lt3;i++)
for(j = 0;j & lt3;j++)
scanf("%f ",& amps[I][j]);
for(I = 0;我& lt3;i++)
for(j = 0;j & lt3;j++)
printf("%f ",s[I][j]);
}
這其實是壹個與本文主題無關的問題,也不是scanf()函數的問題,而是編譯器的問題。
原因很清楚:沒有鏈接的浮點庫。早期系統內存資源不足,多維浮點數組占用內存量大(壹維浮點數組沒有這個問題),所以TC在編譯時盡量不添加無關部分,在沒有發現浮點轉換程序需要的情況下,也不在可執行程序中安裝這部分。有時候TC不能正確識別出實際需要浮點轉換,所以會出現上面的錯誤。
解決方法:告訴TC需要浮點數輸入轉換。將以下語句添加到上述程序中標有/* here */的位置。
方法壹:浮動c;
scanf("%f ",& ampc);
方法二:浮動c,* t;//這裏有個手誤,已經改正了&;t = = = " * t;
t = & ampc;
.....
也就是說,只要編譯器有浮點轉換的線索,TC就會連接浮點轉換,所以在更大的程序中會有浮點變量,但不存在這個問題。
但問題並沒有到此結束。我上面有壹句話,“壹維浮點數沒有這個問題”,那我們來看看這個行不行:
# include & ltstdio.h & gt
int main(void)
{
int i,j;
float s[3][3],* ptr
ptr = & amps[0][0];
for(I = 0;我& lt3;i++)
for(j = 0;j & lt3;j++)
scanf("%f ",ptr+I * 3+j);
for(I = 0;我& lt3;i++)
for(j = 0;j & lt3;j++)
printf("%7.2f\n ",s[I][j]);
}
這樣我們就把多維浮點數組化簡為壹維浮點數組來處理,調試,程序正常運行。這說明TC編譯器只有在處理多維浮點組(結構)的時候才有這個“無鏈接浮點庫”的問題。
問題scanf()函數不能正確接受帶空格的字符串?如:我愛妳!
# include & ltstdio.h & gt
int main()
{
字符串[80];
scanf("%s ",str);
printf("%s ",str);
返回0;
}
投入:我活妳!
輸出:I
當scanf()函數接收到輸入數據時,它在以下情況下結束a數據的輸入:(而不是結束scanf函數,scanf函數只在每個數據字段中有數據,按Enter後結束)。
①如果有空格,“輸入”和“跳過”鍵。
(2)寬度結束時。
③非法輸入的情況。
因此,上述方案無法達到預期目的。當scanf()掃描到“I”後面的空格時,認為str的賦值已經結束,下面的“愛妳!”被忽略。這裏註意是“愛妳!”還是在鍵盤緩沖區裏(我在網上看到的是壹樣的,但是調試後發現緩沖字符串的首末指針此時其實是相等的,也就是說緩沖區是空的,scan()函數應該只是掃描stdin流,這個殘留信息在stdin裏)。讓我們更改上面的程序來驗證它:
# include & ltstdio.h & gt
int main()
{
字符串[80];
char str 1[80];
char str 2[80];
scanf("%s ",str);/*在這裏輸入:我愛妳!*/
printf("%s ",str);
睡眠(5);/*在這裏等5秒,告訴妳程序在哪裏運行*/
scanf("%s ",str 1);/*這兩句不用再輸入了,就是再掃描壹遍鍵盤緩沖區*/
scanf("%s ",str 2);/*這兩句不用再輸入了,就是再掃描壹遍鍵盤緩沖區*/
printf("\n%s ",str 1);
printf("\n%s ",str 2);
返回0;
}
輸入:我愛妳!
輸出:I
愛
妳!
好了,原因已知,那麽scanf()函數能完成這個任務嗎?答案是:有!別忘了scanf()函數還有% []格式控制器(如果妳不了解% [],請看本文第壹部分)。請參見以下程序:
#包含“stdio.h”
int main()
{
char string[50];
/*scanf("%s ",字符串);不能接收空格字符*/
scanf("%[^\n]",string);
printf("%s\n ",string);
返回0;
}
問題三:鍵盤緩沖區殘留信息的問題。
# include & ltstdio.h & gt
int main()
{
int a;
char c;
做
{
scanf("%d ",& ampa);
scanf("%c ",& ampc);
printf("a=%d c=%c\n ",a,c);
/*printf("c=%d\n ",c);*/
}while(c!= ' N ');
}
scanf("%c ",& ampc);這句話不能正常接收字符。原因是什麽?我們用printf("c=%d\n ",c);用int表示c,啟用printf("c=%d\n ",c);這句話,看看scanf()函數給C賦值什麽,結果是C = 10,ASCII值是10。這是什麽?換行符的意思是\n .對了,我們每按壹次“Enter”鍵,就向鍵盤緩沖區發送壹個“Enter”(\r)和壹個“Line feed”(\n),其中\ r由scanff()函數處理(我們這麽想_),而\ n被掃描()。
解決方法:可以在兩個scanf()函數後添加fflush(stdin);並添加getch();getchar();還可以,但是要看具體的scanf()語句加上那個,這裏就不分析了,讀者自己去探索吧。但是加fflush(stdin);不管什麽情況,都是可行的。
函數名:fflush
工作能量:清理壹條小溪。
用法:int fuzzy(file * stream);
# include & ltstdio.h & gt
int main()
{
int a;
char c;
做
{
scanf("%d ",& ampa);
fflush(stdin);
scanf("%c ",& ampc);
fflush(stdin);
printf("a=%d c=%c\n ",a,c);
}while(c!= ' N ');
}
下面是另壹個使用“空格字符”來處理緩沖區中剩余信息的例子:
運行錯誤的程序:
# include & ltstdio.h & gt
int main()
{
int I;
char j;
for(I = 0;我& lt10;i++)
{
scanf("%c ",& ampj);/*此處%之前沒有空格*/
}
}
使用空格控制字符後:
# include & ltstdio.h & gt
int main()
{
int I;
char j;
for(I = 0;我& lt10;i++)
{
scanf(" %c ",& ampj);/*註意% */前有壹個空格
}
}
您可以運行它來查看兩個程序之間的差異。
問題4:如何處理scanf()函數輸入錯誤導致的程序死鎖或錯誤?
# include & ltstdio.h & gt
int main()
{
int a,b,c;/*計算a+b*/
scanf("%d,%d ",& amp壹,& ampb);
c = a+b;
printf("%d+%d=%d ",a,b,c);
}
和上面的程序壹樣,如果A和B的值輸入正確,就沒有問題。但是,妳不能保證用戶每次都能正確輸入。壹旦輸入了錯誤的類型,妳的程序要麽被死鎖,要麽得到錯誤的結果。呵呵,這可能是大家都遇到過的問題。
解決方案:成功執行scanf()函數時,返回值是成功讀取的變量個數。也就是說,妳的scanf()函數有幾個變量。如果正常讀取所有scanf()函數,它將返回幾個變量。但是,這裏要註意另壹個問題。如果輸入非法數據,可能會出現鍵盤緩沖區殘留信息的問題。
正確的程序:
# include & ltstdio.h & gt
int main()
{
int a,b,c;/*計算a+b*/
while(scanf("%d,%d ",& amp壹,& ampb)!= 2)fflush(stdin);
c = a+b;
printf("%d+%d=%d ",a,b,c);
}
讓我們結束這篇文章。最後,我還得像往常壹樣謙虛。我的水平有限(真的有限_ _,這是真的),難免會希望有專家給我指點迷津。我在這裏謝謝妳。
(全文結束)