[英]Only accepting numeric input from user
我目前正試圖在我的程序中只接受來自用戶的數字輸入。 我做了很多研究,但給出的所有示例代碼仍然可以接受諸如10abc
之類的輸入。
這是一個英尺到米轉換器。
include <iostream>
using namespace std;
bool isNumber(string feet){
for (int i = 0; i < feet.length(); i++){
if (isdigit(feet[i]) == false){
return false;
}
return true;
}
}
int main(){
string feet;
beginning:
cout << "Enter the feet: ";
cin >> feet;
if (isNumber(feet))
cout << "The meter is: " << (double)stod(feet) * 0.3048 << endl;
else {
cout << "Invalid input. Please try again" << endl;
goto beginning;
}
return 0;
}
這段代碼接近完美,但它不接受小數點(無語),因為小數點會破壞“isdigit”功能。
那么,是否有任何方法只接受純數字並包括小數點?
那么,是否有任何方法只接受純數字並包括小數點?
函數std::strspn
將返回僅包含在另一個字符串中找到的字符的字符串的長度。 因此,如果您想同時允許十進制數字和小數點,則可以使用以下內容進行輸入驗證:
bool isNumber( string feet )
{
return strspn( feet.c_str(), "0123456789." ) == feet.length();
}
然而,正如評論部分已經指出的,轉換函數std::stod
本身提供了可用於輸入驗證的信息。 如果您為該函數提供第二個參數,它將向提供的變量寫入匹配的字符數。
函數std::stod
在轉換值之前自動消耗所有前導空白字符(例如空格和制表符)。 如果您還想允許尾隨空白字符,但不允許其他類型的字符,那么您可能需要使用以下代碼:
std::size pos;
double d;
//attempt the conversion
d = stod( feet, &pos );
//make sure that at least one character was converted
if ( pos == 0 )
throw "Input was invalid!";
//make sure that all remaining characters are whitespace
while ( feet[pos] != '\0' )
{
if ( !isspace( (unsigned char)feet[pos] ) )
throw "Input was invalid!";
pos++;
}
如果您根本不想允許任何空格,包括前導空格,那么您必須在將字符串內容傳遞給std::stod
之前自己驗證字符串內容。
您可能想知道為什么我將char
為unsigned char
。 有關為什么需要這樣做的原因,請參閱此問題。 出於同樣的原因,您代碼中的以下行是錯誤的:
if (isdigit(feet[i]) == false){
應該改為:
if (isdigit((unsigned char)feet[i]) == false){
此外,您的代碼中的以下問題似乎值得一提:
線
cin >> feet;
將讀取輸入的單個單詞。 因此,如果用戶輸入例如2318 sijslnej
,那么該行代碼只會將2318
寫入feet
。 我懷疑這就是你想要的。 您可能想要使用feet.getline
代替,因為它會讀取整行而不是僅讀取第一個單詞。
我強烈建議你改掉這樣寫的習慣:
if ( isdigit(...) == false )
雖然這條線會一直奏效,但它仍然是一個非常糟糕的習慣,因為這個習慣也會導致你寫出以下內容:
if ( isdigit(...) == true )
這條線相當於
if ( isdigit(...) == 1 )
這是錯誤的。 函數std::isdigit
返回一個int
類型的值,而不是bool
,並且不保證返回值是0
或1
。 它可以返回任何非零值來表示一個數字,例如20
。 在這種情況下,上面提到的if
條件表達式將等價於20 == 1
,其計算結果為 false。 這不是你想要的。
因此,代替
if ( isdigit(...) == false )
你應該寫
if ( !isdigit(...) )
而不是
if ( isdigit(...) == true )
你應該寫:
if ( isdigit(...) )
template <typename T>
T readFromLine(std::istream& in)
{
std::string line;
while (std::getline(in, line)) { // read whole line until it is possible
std::istringstream line_stream { line }; // initialize string stream to parse line read
T x;
// try read `x` then discard white spaces then check if end of lien was reached
if (line_stream >> x >> std::ws && line_stream.eof()) {
// stop since reading was successful and line do not contain anything extra
return x;
}
// continue if reading `x` was unsuccessful or when line contains something extra
}
// while loop ended since end of file was reached or error on input stream
throw std::invalid_argument { "stream to short" };
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.