日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

scanf函数详解(下)

發布時間:2023/11/29 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 scanf函数详解(下) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題一

如何讓scanf()函數正確接受有空格的字符串?如: I love you!

#include <stdio.h>

int main()

{

? ?char str[80];

? ?scanf("%s",str);

? ?printf("%s",str);

? ?return 0;

}

輸入:I love you!

上述程序并不能達到預期目的,scanf()掃描到"I"后面的空格就認為對str的賦值結束,并忽略后面的"love you!".這里要注意是"love you!"還在鍵盤緩沖區(關于這個問題,網上我所見的說法都是如此,但是,我經過調試發現,其實這時緩沖區字符串首尾指針已經相等了,也就是說緩沖區清空了,scanf()函數應該只是掃描stdin流,這個殘存信息是在stdin中)。我們改動一下上面的程序來驗證一下:

#include <stdio.h>

#include<windows.h>

int main()

{

? ?char str[80], str1[80], str2[80];

? ?scanf("%s", str); /*此處輸入:I love you! */

? ?printf("%s\n", str);

? ?Sleep(5000); /*這里等待5秒,告訴你程序運行到什么地方*/

? ?/*不是sleep(5)

? ?1,函數名是Sleep不是sleep。

? ?2,C/C++中,unsigned Sleep(unsigned)應該是毫秒ms.

? ?*/

? ?scanf("%s", str1); /*這兩句無需你再輸入,是對stdin流再掃描*/

? ?scanf("%s", str2); /*這兩句無需你再輸入,是對stdin流再掃描*/

? ?printf("%s\n", str1);

? ?printf("%s\n", str2);

? ?return 0;

}

輸入:I love you!

輸出:

I

love

you!

好了,原因知道了,所以結論是:殘留的信息love you是存在于stdin流中,而不是在鍵盤緩沖區中。那么scanf()函數能不能完成這個任務?回答是:能!別忘了scanf()函數還有一個%[]格式控制符(如果對%[]不了解的請查看本文的上篇),請看下面的程序:

#include <stdio.h>

int main()

{

? ?char str[50];

? ?scanf("%49[^\n]", str); /* scanf("%s",string);不能接收空格符*/

? ?printf("%s\n", str);

? ?return 0;

}

問題二

鍵盤緩沖區殘余信息問題

#include <stdio.h>

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');

? ?return 0;

}

scanf("%c", &c);這句不能正常接收字符,什么原因呢?我們用printf("c = %d\n", c);將C用int表示出來,啟用printf("c = %d\n", c);這一句,看看scanf()函數賦給C到底是什么,結果是c=10 ,ASCII值為10是什么?換行即\n.對了,我們每擊打一下"Enter"鍵,向鍵盤緩沖區發去一個“回車”(\r),一個“換行"(\n),在這里\r被scanf()函數處理掉了(姑且這么認為吧^_^),而\n被scanf()函數“錯誤”地賦給了c.解決辦法:可以在兩個scanf()函數之后加個fflush(stdin);,還有加getch(),getchar()也可以,但是要視具體scanf()語句加那個,這里就不分析了,讀者自己去摸索吧。但是加fflush(stdin);不管什么情況都可行。

函數名:fflush

能:清除一個流

法: intfflush(FILE *stream);

)

#include <stdio.h>

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');

? ?return 0;

}

這里再給一個用“空格符”來處理緩沖區殘余信息的示例:

/版本1//運行出錯的程序///

#include <stdio.h>

int main()

{

? ?int i;

? ?char j;

? ?for (i = 0; i < 10; ++i)

? ?scanf("%c", &j); /*這里%前沒有空格*/

? ?printf("%c", j); /*在輸入十個字符之后

? ?return 0;

}

//

/版本2//使用了空格控制符后///

#include <stdio.h>

int main()

{

? ?int i;

? ?char j;

? ?for (i = 0; i < 10; ++i)

? ?scanf(" %c", &j);/*注意這里%前有個空格*/

? ?printf("%c", j);/*在輸入十個字符之后,驗證打印出來的字符是否是自己輸入的最后一個字符(即輸入的第十個字符)*/

? ?return 0;

}

接著,我們運行看看,首先,運行第一個版本(錯誤的程序)

我們輸入:0 1 2 3 4 5 6 7 8 9

結果是一個空字符

再運行第二個版本(正確的程序)

同樣輸入:0 1 2 3 4 5 6 7 8 9

這一次就顯示字符9,故此程序正確。

那么為什么第二個程序就正確呢,原因何在,在%前面加一個空格就這么有用,答案是肯定的,就是%前面的空格在起作用,讀者看看此文章的前面部分,在scanf的使用過程中應注意的問題中已經指出:“scanf()的格式控制串可以使用空白字符或其它非空白字符,使用空白字符會使scanf()函數在讀操作中略去輸入中的一個或多個空白字符。”

所以在%前面加上了空格(空格屬于空白字符,此外還有像制表符等也屬于空白字符),在輸入過程中,將略去輸入中的一個或多個空白字符,所以我們輸入的0 1 2 3 4 5 6 7 8 9這些字符中的空白字符就被略去了,字符9也就正確的打印出來了,這樣子解釋,相信大家都看明白勒吧!

問題三

如何處理scanf()函數誤輸入造成程序死鎖或出錯?

#include <stdio.h>

int main()

{

? ?int a, b, c;

? ?scanf("%d,%d", &a, &b);

? ?c = a + b; /*計算a+b*/

? ?printf("%d + %d = %d", a, b, c);

? ?return 0;

}

如上程序,如果正確輸入a,b的值,那么沒什么問題,但是,你不能保證使用者每一次都能正確輸入,一旦輸入了錯誤的類型,你的程序不是死鎖,就是得到一個錯誤的結果,呵呵,這可能所有人都遇到過的問題吧?解決方法:scanf()函數執行成功時的返回值是成功讀取的變量數,也就是說,你這個scanf()函數有幾個變量,如果scanf()函數全部正常讀取,它就返回幾。但這里還要注意另一個問題,如果輸入了非法數據,鍵盤緩沖區就可能還個有殘余信息問題。正確的例程:

#include <stdio.h>

int main()

{

? ?int a,b,c;

? ?while (scanf("%d,%d", &a, &b) != 2)

? ?fflush(stdin);

? ?c = a + b;

? ?printf("%d + %d = %d", a, b, c);

? ?return 0;

}

補充

fflush(stdin)這個方法在GCC下不可用。(在VC6.0下可以)

以下是C99fflush函數的定義:

int fflush(FILE *stream);

如果stream指向輸出流或者更新流(update stream),并且這個更新流

執行的操作不是輸入,那么fflush函數將把任何未被寫入的數據寫入stream

指向的文件(如標準輸出文件stdout)。否則,fflush函數的行為是不確定的。

C和C++的標準里從來沒有定義過fflush(stdin)。

fflush(NULL)清空所有輸出流和上面提到的更新流。如果發生寫錯誤,fflush

函數會給那些流打上錯誤標記,并且返回EOF,否則返回0。

由此可知,如果stream指向輸入流(如stdin),那么fflush函數的行為是不確定的。故而使用

fflush(stdin)是不正確的,至少是移植性不好的。

可采用如下方法:

方法一:

/*此函數可以和scanf函數一起使用,但使用%c輸入時要注意,即此函數只能用于緩沖區非空的情況*/

#include <stdio.h>

void flush()

{

? ?char c;

? ?while ((c =getchar()) != '\n' && c != EOF) ;

}

int main()

{

? ?int a,b,c; /*計算a+b*/

? ?while (scanf("%d,%d", &a, &b) != 2)

? ?flush();

? ?c = a + b;

? ?printf("%d + %d = %d", a, b, c);

}

方法二:

使用getchar()代替fflush(stdin)

程序示例:

#include <stdio.h>

int main()

{

? ?int i, c;

? ?while (1 )

? ?{

? ? ? ?printf("Please input an integer: ");

? ? ? ?scanf("%d", &i);

? ? ? ?if (feof(stdin) || ferror(stdin))

? ? ? ?{

? ? ? ? ? ?/*如果用戶輸入文件結束標志(或文件已被讀完),*/

? ? ? ? ? ?/*或者發生讀寫錯誤,則退出循環*/

? ? ? ? ? ?/* do something */

? ? ? ? ? ?break;

? ? ? ?}

? ? ? ?/*沒有發生錯誤,清空輸入流。*/

? ? ? ?/*通過while循環把輸入流中的余留數據“吃”掉*/

? ? ? ?while ( (c =getchar()) != '\n' && c != EOF ) ; /*可直接將這句代碼當成fflush(stdin)的替代,直接運行可清除輸入緩存流*/

? ? ? ?/*使用scanf("%*[^\n]");也可以清空輸入流,*/

? ? ? ?/*不過會殘留\n字符。*/

? ? ? ?printf("%d\n", i);

? ?}

? ?return 0;

}

發展

使用scanf函數進行輸入,必須指定輸入的數據的類型和格式,不僅繁瑣復雜,而且很容易出錯.C++保留scanf只是為了和C兼容,以便過去用C語言寫的程序可以在C++的環境下運行。C++的編程人員都愿意使用cin進行輸入,很少使用scanf。


轉載于:https://blog.51cto.com/fancong/1293303

總結

以上是生活随笔為你收集整理的scanf函数详解(下)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。