scanf使用前怎么定義?
簡(jiǎn)介 scanf函數(shù),與printf函數(shù)一樣,都被定義在stdio.h里,因此在使用scanf函數(shù)時(shí)要加上#include。它是格式輸入函數(shù),即按用戶(hù)指定的格式從鍵盤(pán)上把數(shù)據(jù)輸入到指定的變量之中,其關(guān)鍵字最末一個(gè)字母f即為“格式”(format)之意。 [編輯本段]scanf函數(shù)的一般形式 scanf(格式控制,地址表列) int scanf(char *format[,argument,...]); “格式控制”的含義同printf函數(shù);“地址表列”是由若干個(gè)地址組成的表列,可以是變量的地址,或字符串首地址。 scanf()函數(shù)返回成功賦值的數(shù)據(jù)項(xiàng)數(shù),出錯(cuò)時(shí)則返回EOF。 例:使用scanf函數(shù)輸入數(shù)據(jù)。 #include void main() { int a,b,c; printf("input a,b,c\n"); scanf("%d%d%d",&a,&b,&c); printf("a=%d,b=%d,c=%d",a,b,c); } [編輯本段]格式字符說(shuō)明 %a,%A 讀入一個(gè)浮點(diǎn)值(僅C99有效) %c 讀入一個(gè)字符 %d 讀入十進(jìn)制整數(shù) %i 讀入十進(jìn)制,八進(jìn)制,十六進(jìn)制整數(shù) %o 讀入八進(jìn)制整數(shù) %x,%X 讀入十六進(jìn)制整數(shù) %c 讀入一個(gè)字符 %s 讀入一個(gè)字符串,遇空格、制表符或換行符結(jié)束。 %f,%F,%e,%E,%g,%G 用來(lái)輸入實(shí)數(shù),可以用小數(shù)形式或指數(shù)形式輸入。 %p 讀入一個(gè)指針 %u 讀入一個(gè)無(wú)符號(hào)十進(jìn)制整數(shù) %n 至此已讀入值的等價(jià)字符數(shù) %[] 掃描字符集合 %% 讀%符號(hào) 附加格式說(shuō)明字符表修飾符說(shuō)明 L/l 長(zhǎng)度修飾符 輸入"長(zhǎng)"數(shù)據(jù) h 長(zhǎng)度修飾符 輸入"短"數(shù)據(jù) W 整型常數(shù) 指定輸入數(shù)據(jù)所占寬度 * 表示本輸入項(xiàng)在讀入后不賦值給相應(yīng)的變量 [編輯本段]scanf的返回值 scanf的返回值有后面的參數(shù)決定 scanf("%d%d", &a, &b); 如果a和b都被成功讀入,那么scanf的返回值就是2 如果只有a被成功讀入,返回值為1 如果a和b都未被成功讀入,返回值為0 如果遇到錯(cuò)誤或遇到end of file,返回值為EOF。 且返回值為int型. [編輯本段]使用scanf函數(shù)時(shí)應(yīng)該注意的問(wèn)題 1、sacnf()中的變量必須使用地址。 2、scanf()的格式控制串可以使用其它非空白字符,但在輸入時(shí)必須輸入這些字符。 3、在用"%c"輸入時(shí),空格和“轉(zhuǎn)義字符”均作為有效字符。 問(wèn)題一:scanf()函數(shù)不能正確接受有空格的字符串?如: I love you! #include int main() { char str[80]; scanf("%s",str); printf("%s",str); return 0; } 輸入:I love you! 輸出:scanf()函數(shù)接收輸入數(shù)據(jù)時(shí),遇以下情況結(jié)束一個(gè)數(shù)據(jù)的輸入:(不是結(jié)束該scanf函數(shù),scanf函數(shù)僅在每一個(gè)數(shù)據(jù)域均有數(shù)據(jù),并按回車(chē)后結(jié)束)。 ① 遇空格、“回車(chē)”、“跳格”鍵。 ② 遇寬度結(jié)束。 ③ 遇非法輸入。 所以,上述程序并不能達(dá)到預(yù)期目的,scanf()掃描到"I"后面的空格就認(rèn)為對(duì)str的賦值結(jié)束,并忽略后面的"love you!".這里要注意是"love you!"還在鍵盤(pán)緩沖區(qū)(關(guān)于這個(gè)問(wèn)題,網(wǎng)上我所見(jiàn)的說(shuō)法都是如此,但是,我經(jīng)過(guò)調(diào)試發(fā)現(xiàn),其實(shí)這時(shí)緩沖區(qū)字符串首尾指針已經(jīng)相等了,也就是說(shuō)緩沖區(qū)清空了,scanf()函數(shù)應(yīng)該只是掃描stdin流,這個(gè)殘存信息是在stdin中)。我們改動(dòng)一下上面的程序來(lái)驗(yàn)證一下: #include int main() { char str[80]; char str1[80]; char str2[80]; scanf("%s",str);/*此處輸入:I love you! */ printf("%s",str); sleep(5);/*這里等待5秒,告訴你程序運(yùn)行到什么地方*/ scanf("%s",str1);/*這兩句無(wú)需你再輸入,是對(duì)鍵盤(pán)盤(pán)緩沖區(qū)再掃描 */ scanf("%s",str2);/*這兩句無(wú)需你再輸入,是對(duì)鍵盤(pán)盤(pán)緩沖區(qū)再掃描 */ printf("\n%s",str1); printf("\n%s",str2); return 0; } 輸入:I love you! 輸出: I love you! 好了,原因知道了,那么scanf()函數(shù)能不能完成這個(gè)任務(wù)?回答是:能!別忘了scanf()函數(shù)還有一個(gè) %[] 格式控制符(如果對(duì)%[]不了解的請(qǐng)查看本文的上篇),請(qǐng)看下面的程序: #include "stdio.h" int main() { char string[50];/*scanf("%s",string);不能接收空格符*/ scanf("%[^\n]",string); printf("%s\n",string); return 0; } 問(wèn)題二:鍵盤(pán)緩沖區(qū)殘余信息問(wèn)題 #include int main() { int a; char c; do { scanf("%d",&a); scanf("%c",&c); printf("a=%d c=%c\n",a,c);/*printf("c=%d\n",c);*/ }while(c!='N'); } scanf("%c",&c);這句不能正常接收字符,什么原因呢?我們用printf("c=%d\n",c);將C用int表示出來(lái),啟用printf("c=%d\n",c);這一句,看看scanf()函數(shù)賦給C到底是什么,結(jié)果是c=10 ,ASCII值為10是什么?換行即\n.對(duì)了,我們每擊打一下"Enter"鍵,向鍵盤(pán)緩沖區(qū)發(fā)去一個(gè)“回車(chē)”(\r),一個(gè)“換行"(\n),在這里\r被scanf()函數(shù)處理掉了(姑且這么認(rèn)為吧^_^),而\n被scanf()函數(shù)“錯(cuò)誤”地賦給了c.解決辦法:可以在兩個(gè)scanf()函數(shù)之后加個(gè)fflush(stdin);,還有加getch() , getchar()也可以,但是要視具體scanf()語(yǔ)句加那個(gè),這里就不分析了,讀者自己去摸索吧。但是加fflush(stdin);不管什么情況都可行。 ( 函數(shù)名: fflush 功 能: 清除一個(gè)流 用 法: int fflush(FILE *stream); ) #include int main() { int a; char c; do { scanf("%d",&a); fflush(stdin); scanf("%c",&c); fflush(stdin); printf("a=%d c=%c\n",a,c); }while(c!='N'); } 這里再給一個(gè)用“空格符”來(lái)處理緩沖區(qū)殘余信息的示例:運(yùn)行出錯(cuò)的程序: #include int main() { int i; char j; for(i = 0;i < 10;i++) { scanf("%c",&j);/*這里%前沒(méi)有空格*/ } } 使用了空格控制符后: #include int main() { int i; char j; for(i = 0;i < 10;i++) { scanf(" %c",&j);/*注意這里%前有個(gè)空格*/ } } 可以運(yùn)行看看兩個(gè)程序有什么不同。 問(wèn)題三: 如何處理scanf()函數(shù)誤輸入造成程序死鎖或出錯(cuò)? #include int main() { int a,b,c; /*計(jì)算a+b*/ scanf("%d,%d",&a,&b); c=a+b; printf("%d+%d=%d",a,b,c); } 如上程序,如果正確輸入a,b的值,那么沒(méi)什么問(wèn)題,但是,你不能保證使用者每一次都能正確輸入,一旦輸入了錯(cuò)誤的類(lèi)型,你的程序不是死鎖,就是得到一個(gè)錯(cuò)誤的結(jié)果,呵呵,這可能所有人都遇到過(guò)的問(wèn)題吧?解決方法:scanf()函數(shù)執(zhí)行成功時(shí)的返回值是成功讀取的變量數(shù),也就是說(shuō),你這個(gè)scanf()函數(shù)有幾個(gè)變量,如果scanf()函數(shù)全部正常讀取,它就返回幾。但這里還要注意另一個(gè)問(wèn)題,如果輸入了非法數(shù)據(jù),鍵盤(pán)緩沖區(qū)就可能還個(gè)有殘余信息問(wèn)題。正確的例程: #include int main() { int a,b,c; /*計(jì)算a+b*/ while(scanf("%d,%d",&a,&b)!=2)fflush(stdin); c=a+b; printf("%d+%d=%d",a,b,c); } 補(bǔ)充: fflush(stdin)這個(gè)方法在GCC下不可用。(在VC6.0下可以) 以下是 C99 對(duì) fflush 函數(shù)的定義: int fflush(FILE *stream); 如果stream指向輸出流或者更新流(update stream),并且這個(gè)更新流 最近執(zhí)行的操作不是輸入,那么fflush函數(shù)將把任何未被寫(xiě)入的數(shù)據(jù)寫(xiě)入stream 指向的文件(如標(biāo)準(zhǔn)輸出文件stdout)。否則,fflush函數(shù)的行為是不確定的。 fflush(NULL)清空所有輸出流和上面提到的更新流。如果發(fā)生寫(xiě)錯(cuò)誤,fflush 函數(shù)會(huì)給那些流打上錯(cuò)誤標(biāo)記,并且返回EOF,否則返回0。 由此可知,如果 stream 指向輸入流(如 stdin),那么 fflush 函數(shù)的行為是不確定的。故而使用 fflush(stdin) 是不正確的,至少是移植性不好的。 可采用如下方法: void flush() /* 只適用于鍵盤(pán)緩沖區(qū)有殘余信息的情況,若鍵盤(pán)緩沖區(qū)為空則不能使用 */ { while (getchar() != '\n') ; } #include int main() { int a,b,c; /*計(jì)算a+b*/ while(scanf("%d,%d",&a,&b)!=2) flush(); c=a+b; printf("%d+%d=%d",a,b,c); }