簡體   English   中英

只接受用戶的數字輸入

[英]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之前自己驗證字符串內容。

您可能想知道為什么我將charunsigned 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 ,並且不保證返回值是01 它可以返回任何非零值來表示一個數字,例如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" };
}

https://godbolt.org/z/75efEP9Y8

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM