中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

使用C語言清空輸入緩沖區的方法

發布時間:2020-09-29 16:32:29 來源:億速云 閱讀:202 作者:小新 欄目:編程語言

這篇文章主要介紹使用C語言清空輸入緩沖區的方法,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

 C語言中有幾個基本輸入函數:

//獲取字符系列
int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar(void);
//獲取行系列
char *fgets(char * restrict s, int n, FILE * restrict stream);
char *gets(char *s);//可能導致溢出,用fgets代替之。
//格式化輸入系列
int fscanf(FILE * restrict stream, const char * restrict format, …);
int scanf(const char * restrict format, …);
int sscanf(const char * restrict str, const char * restrict format, …);

這里僅討論輸入函數在標準輸入(stdin)情況下的使用。縱觀上述各輸入函數,

  • 獲取字符系列的的前三個函數fgetc、getc、getchar。以getchar為例,將在stdin緩沖區為空時,等待輸入,直到回車換行時函數返回。若stdin緩沖區不為空,getchar直接返回。getchar返回時從緩沖區中取出一個字符,并將其轉換為int,返回此int值。

MINGW 4.4.3中FILE結構體源碼

  _iobuf
{
	char*	_ptr;//指向當前緩沖區讀取位置
	int	_cnt;//緩沖區中剩余數據長度
	char*	_base;
	int	_flag;
	int	_file;
	int	_charbuf;
	int	_bufsiz;
	char*	_tmpfname;
} FILE;

各編譯器實現可能不一樣,這里獲取字符系列函數只用到_ptr和_cnt。

MINGW 4.4.3中getchar()實現

__CRT_INLINE int __cdecl __MINGW_NOTHROW getchar (void)
{
  return (--stdin->_cnt >= 0)
    ?  (int) (unsigned char) *stdin->_ptr++
    : _filbuf (stdin);
}

其中stdin為FILE指針類型,在MINGW 4.4.3中,getc()和getchar()實現為內聯函數,fgetc()實現為函數。順便說一句,C99標準中已經加入對內聯函數的支持了。

  • 獲取行系列的fgets和gets,其中由于gets無法確定緩沖區大小,常導致溢出情況,這里不推薦也不討論gets函數。對于fgets函數,每次敲入回車,fgets即返回。fgets成功返回時,將輸入緩沖區中的數據連換行符’\n’一起拷貝到第一個參數所指向的空間中。若輸入數據超過緩沖區長度,fgets會截取數據到前n-1(n為fgets第二個參數,為第一個參數指向空間的長度),然后在末尾加入’\n’。因此fgets是安全的。通常用fgets(buf, BUF_LEN, stdin);代替gets(buf);。

  • 格式化輸入系列中,fscanf從文件流進行格式化輸入很不好用。常用的還是scanf,格式化輸入系列函數舍去輸入數據(根據函數不同可能是標準輸入也可能是字符串輸入,如:sscanf)前的空白字符(空格、制表符、換行符)直至遇到非空白字符,然后根據格式參數嘗試對非空白字符及后續字符進行解析。該系列函數返回成功解析賦值的變量數,若遇文件尾或錯誤,返回EOF。

=================分 割 線=================

提到緩沖區,就不得不提setbufsetvbuf兩個緩沖區設置函數,其聲明如下:

 setbuf(FILE * restrict stream,  * restrict buf);
int setvbuf(FILE * restrict stream, char * restrict buf, int mode, size_t size);

setvbuf的mode參數有:

  • _IOFBF(滿緩沖):緩沖區空時讀入數據;緩沖區滿時向流寫入數據。

  • _IOLBF(行緩沖):每次從流讀入一行數據或向流寫入數據。如:stdio,stdout

  • _IONBF(無緩沖):直接從流讀入數據,或者直接向流寫入數據,而沒有緩沖區。如:stderr

setbuf(stream, buf);在:

  • buf == NULL:等價于(void)setvbuf(stream, NULL, _IONBF, 0);

  • buf指向長度為BUFSIZ的緩沖區:等價于(void)setvbuf(stream, buf, _IOFBF, BUFSIZ);

注:BUFSIZ宏在stdio.h中定義。

這里還要提一下傳說中的setbuf經典錯誤,在《C陷阱和缺陷》上有提到:

 main()
{
    int c;
    char buf[BUFSIZ];

    setbuf(stdout,buf);
    while((c = getchar()) != EOF)
        putchar(c);
    
    return 0;
}

問題是這樣的:程序交回控制給操作系統之前C運行庫必須進行清理工作,其中一部分是刷新輸出緩沖,但是此時main函數已經運行完畢,buf緩沖區作用域在main函數中,此時buf字符數組已經釋放,導致輸出詭異亂碼。

解決方案:可以將buf設置為static,或者全局變量,或者調用malloc來動態申請內存。

=================分 割 線=================

下面來看看幾種流行的緩沖區清空方法:

  • fflush(stdin);式

由C99標準文檔中:

If stream points to an output stream or an update stream in which the most recent
operation was not input, the fflush function causes any unwritten data for that stream
to be delivered to the host environment to be written to the ?le; otherwise, the behavior is
unde?ned.

可以看出fflush對輸入流為參數的行為并未定義。但由MSDN上的fflush定義:

If the file associated with stream is open for output, fflush writes to that file the
contents of the buffer associated with the stream. If the stream is open for input,
fflush clears the contents of the buffer.

可以看出fflush(stdin)在VC上還是有效地!鑒于各編譯器對fflush的未定義行為實現不一樣,不推薦使用fflush(stdin)刷新輸入緩沖區。

  • setbuf(stdin, NULL);式

由前面對setbuf函數的介紹,可以得知,setbuf(stdin, NULL);是使stdin輸入流由默認緩沖區轉為無緩沖區。都沒有緩沖區了,當然緩沖區數據殘留問題會解決。但這并不是我們想要的。

  • scanf("%*[^\n]");式(《C語言程序設計 現代方法 第二版》中提到)

這里用到了scanf格式化符中的“*”,即賦值屏蔽;“%[^集合]”,匹配不在集合中的任意字符序列。這也帶來個問題,緩沖區中的換行符’\n’會留下來,需要額外操作來單獨丟棄換行符。

  • 經典式

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

由代碼知,不停地使用getchar()獲取緩沖區中字符,直到獲取的字符c是換行符’\n’或者是文件結尾符EOF為止。這個方法可以完美清除輸入緩沖區,并且具備可移植性。

以上是使用C語言清空輸入緩沖區的方法的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

高陵县| 宽城| 孟州市| 武山县| 化德县| 绥阳县| 扶绥县| 阜平县| 开平市| 昌江| 伊金霍洛旗| 宁津县| 崇信县| 新乐市| 望城县| 商城县| 高要市| 西充县| 营山县| 安化县| 西林县| 临沂市| 进贤县| 义马市| 建昌县| 巴里| 邮箱| 墨竹工卡县| 伊宁县| 麟游县| 临颍县| 卓资县| 资兴市| 永清县| 望城县| 和龙市| 蓬溪县| 关岭| 广丰县| 错那县| 丹东市|