VS C++ 初學者日記(2)輸入流緩存清空

輸入流緩存不清空會導致的問題

在這個系列的上一篇中(已經過去好久了哈),經過研究寫了一個駐屏的段落。當時其時還留有一些尾巴,今天在這裏探討一下。


首先回顧一下上次的駐屏程序:寫成一個staycreen函數:
stayscreen.h

// stayscreen.h -- stayscreen programming head file
#include <iostream>
#include <string>

using std::cout;
using std::cin;
using std::string;
using std::getline;
using std::get;
using std::endl;

void stayscreen();

stayscreen.cpp

// stayscreen.cpp -- stayscreen cpp file
#include "stayscreen.h"

void stayscreen()
{
    string exitflag("\n");
    cout << "Press Q or q key to quit...\n";
    getline(cin, exitflag);
    while (exitflag.find('q') == string::npos && exitflag.find('Q') == string::npos)
    {
        cout << "Press Q or q key to quit...\n";
        getline(cin, exitflag);
    }
}

調用格式大體上爲

blablabla
#include "stayscreen.h"
blablabla

int main()
{
   blablabla
   stayscreen();
   return 0;
}

大多數情況下這個程序運轉是正常的,偶爾會出現問題,這也是爲什麼說“留有尾巴”的原因。那麼會出現什麼問題呢?
你可能會注意到,在stayscreen.cpp裏有一些奇怪的地方:用於讀取輸入的

    cout << "Press Q or q key to quit...\n";
    getline(cin, exitflag);

在後面的while循環裏明明已經寫過一次了。爲什麼又在循環外補了一個?
這在當時其實是無奈之舉,因爲在讀入輸入的時候,有時候會讀到前面main程序輸入輸出流尾巴上的回車符,從而導致判斷exitflag是否爲“Q/q”的程序段落始終讀到的是一個回車符,從而陷入死循環,現象就是不停地輸出”Press Q or q key to quit…”
爲了解決這個問題,只好在進入while循環之前先讀取一次,目的是如果讀到了緩衝區裏的回車符,可以通過循環外的這一次讀取洗掉。可是並不是每段程序都能適應(尤其是緩衝區裏可能有一個以上回車符的時候)。這個問題一直沒有得到很好的解決。


當然了,作爲初學者,階段性的問題解決不好是很正常的事情。這兩天剛好在學習輸入和輸出部分相關的知識。看到cin.clear()和cin.ignore()的用法時,突然豁然開朗。在最後的讀取判斷前,爲了防止前置程序的干擾,最好的辦法可不就是把緩衝區的內容清空嗎?
在c語言風格里,用的是fflush(stdin)這一句,但是在c++裏,用的是

cin.clear();
cin.ignore();

於是stayscreen.cpp改成

// stayscreen.cpp -- stayscreen cpp file
#include "stayscreen.h"

void stayscreen()
{
    string exitflag("\n");
    cin.clear();
    cin.ignore();
    while (exitflag.find('q') == string::npos && exitflag.find('Q') == string::npos)
    {
        cout << "Press Q or q key to quit...\n";
        getline(cin, exitflag);
    }
}

這樣就不會發生邏輯上明明沒問題,卻總是因爲緩衝區內回車符的影響,導致的讀取錯位了。
特別值得注意的是,cin.clear()會導致下一個cin流不讀取輸入,所以需要用cin.ignore()處理一次,這兩句共同使用就相當於是一次完整的流清空和重置了。

發佈了45 篇原創文章 · 獲贊 60 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章