[C++ 非規範輸入的檢測和處理]

本文首先給出對”非規範輸入“一詞的定義:指用戶沒有按照程序設計者的期望規範而產生的輸入。

例如,程序要求輸入數字,用戶卻輸入了字母,而程序設計之初卻只考慮了對數字的處理;並沒有考慮到對字母的處理,於是在用戶輸入字母時,就有可能引發程序的錯誤執行乃至崩潰。

場景1:

輸入數字,判斷是否爲特定數字,但用戶非規範輸入了非數字如字母等。

代碼:

#include <iostream>
using namespace std;
int main(){
	int a;
	while(a != 1) {
		cin >> a;
		cout << "not a" << endl;
	}	
	return 0;
}

循環判斷a是否爲1,若不爲1,彈出提示。

運行:

如圖依次輸入4 3 2 1,運行正常。

但是如果遇到非規範輸入:

如圖輸入a,程序陷入輸出"not 1"的死循環中。

分析:

因爲語句int a = 0;將a聲明成數值型,則語句cin >> a;將會從緩衝區中提取一個數值賦值給a。

但是,用戶輸入字母a後,緩衝區中並沒有數值,只有字母a和一個回車符。

因此,語句cin >> a;將不會從此緩衝區中提取內容,也不會改變緩衝區的內容,緩衝區裏就一直是字母a和一個回車符。

如何解決這個問題呢?每次新的cin命令執行時,殘留在緩衝區中的內容都會干擾程序的正確執行,於是,不妨在每次cin前,先將緩衝區清空,即使用cin.clear()和cin.sync()命令。

cin.sync()命令用於清輸入流(緩衝區)。

cin.clear()命令用於清標誌位,包括failbit標誌位。

代碼修改:

#include <iostream>
using namespace std;
int main(){
	int a = 0;
	while(a != 1) {
		cout << "not 1" << endl;
        //增加以下兩行代碼
		cin.clear();
		cin.sync();
        //增加以上兩行代碼
		cin >> a;
	}
	cout << "is 1" << endl;
	return 0;
}

運行:

輸入非數字的a a b c ! 程序就不會陷入死循環了。

 

場景2:

循環使用stoi()函數將用戶輸入的數字字符串轉換爲數字類型,但用戶非規範輸入了字母等。

代碼:

#include <iostream>
#include <string>
using namespace std;
int main() {
	string a;
	int i;
	while(1) {
		cout << "請輸入一串數字:"; 
		cin >> a;
		i = stoi(a);
		cout << "您輸入的數字爲:" << i << endl;
	} 
	return 0;
} 

運行:

對一般的數字輸入,程序都能正常運行。

但是遇到用戶的非規範輸入abc時,程序就出錯崩潰了。

分析:

其實,在cmd中我們就可以看到這種錯誤的類型爲std::invalid_argument(無效實參),那麼我們就可以利用C++提供的try...catch...異常處理機制來解決。

使用try包含到可能觸發異常的代碼行,使用catch捕獲無效實參異常exception invalid argument,使用引用&。

代碼:

#include <iostream>
#include <string>
using namespace std;
int main() {
	string a;
	int i;
	while(1) {
		try {
			cout << "請輸入一串數字:"; 
			cin >> a;
			i = stoi(a);
		}
		catch (exception& invalid_argument) {
			cout << "輸入的不是數字。請檢查!" << endl;
			continue;
		}
		cout << "您輸入的數字爲:" << i << endl;
	} 
	return 0;
} 

運行:

這樣,程序遇到用戶的非規範輸入時,就不會崩潰,而是輸出提示信息後,跳向下一輪循環,繼續執行。 

 

參考資料:

cppconference

C++ Primer Plus

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章