Различение между int и double

Я искал этот ответ, и никто, кажется, не знает, как исправить эту ошибку. Я хочу, чтобы вход был строго int. Если ввод двойной, я хочу отправить ошибку.

int creatLegs = 0;
string trash;
bool validLegs = true;
do
{
    cout << "How many legs should the creature have? ";
    cin >> creatLegs;

    if(cin.fail())
    {
        cin.clear();
        cin >> trash; //sets to string, so that cin.ignore() ignores the whole string.
        cin.ignore(); //only ignores one character
        validLegs = false;
    }

    if (creatLegs > 0)
    {

        validLegs = true;
    }

    if (!validLegs)
    {
        cout << "Invalid value, try again.\n";
    }

} while (!validLegs);

Кажется, почти работает. Он отправляет ошибку, но только после перехода на следующий цикл. Как я могу это исправить? И почему он по-прежнему показывает сообщение об ошибке, но продолжает отображаться перед его отображением?

4 ответа

Решение

Я думаю, что вы должны прочитать данные как строку, а затем проверить их как char за char, чтобы убедиться, что они целочисленные - если каждый символ является цифрой, то у нас есть целое число, и мы можем его проанализировать.

Проблема с потоками заключается в том, что если вы пытаетесь прочитать целое число, но передается десятичное число, оно читает число до точки. И эта часть является правильным целым числом, поэтому cin.fail() возвращается false,

Образец кода:

#include <iostream>
#include <string>
#include <cctype>
#include <cstdlib>

using namespace std;

int main() {
    int creatLegs = 0;
    bool validLegs = true;
    do
    {
        cout << "How many legs should the creature have? ";
        string input;
        getline(cin, input);

        validLegs = true;
        for (string::const_iterator i = input.begin(); validLegs && i != input.end(); ++i) {
            if (!isdigit(*i)) {
                validLegs = false;
            }
        }

        if (!validLegs)
        {
            cout << "Invalid value, try again.\n";
        } else {
            creatLegs = atoi(input.c_str());
        }

    } while (!validLegs);

    cout << creatLegs << endl;
}

Это, конечно, не идеальное решение. Если есть начальные или конечные пробелы (или любые другие символы, такие как + или же -), программа потерпит неудачу. Но вы всегда можете добавить некоторый код для обработки этих ситуаций, если вам нужно.

Входные данные могут быть чем-то иным, кроме представления целого числа или числа с плавающей запятой.

Помните, что числа не являются их представлением (ями): 9 (десятичный), 017 (восьмеричное, а-ля C), 0b1001 (бинарный, а-ля Ocaml), IX (Римская запись), 8+1 (арифметическое выражение), neuf (Французский) все представления одного и того же числа девять.

Таким образом, вы должны решить, если вы принимаете вход как 9 x, или же 9 (с несколькими пробелами после цифры),... В более общем случае вы должны определить, какие допустимые входные данные (и если ввод заканчивается в конце строки или нет, если должны быть приняты пробелы или знаки пунктуации и т. д...),

Вы можете прочитать всю строку (например, с помощью std:: getline) и использовать, например, sscanf (где %n полезен управляющий формат, а также счетчик элементов, возвращаемый sscanf) или std:: stol (где вы используете указатель конца) для его анализа

Заметьте также, что формулировка вашего вопроса ("Различение между int и double") неверна. Там нет ни одного " int или же double "введите в C++ (но int является скалярным типом, и double является скалярным типом в C++, и вы можете определить class с помеченным объединением для удержания любого из них). AFAIU, если вы объявите int x; затем используйте std::cin >> x; с пользовательским вводом 12.64 точка и цифры 64 после того, как он не будет проанализирован и x станет 12.

На этот вопрос уже есть принятый ответ, однако я внесу решение, которое обрабатывает все целые числа, даже те, которые выражены как числа с плавающей запятой (без дробной части), и отклоняет ввод, который содержит что-либо, кроме пробелов, следующих за число.

Примеры принятых значений, все они представляют число 4:

4
4.
4.0
+4
004.0
400e-2

Примеры отклоненных значений:

3.999999
4.000001
40e-1x
4,
#include <iostream>
#include <sstream>
#include <cctype>
#include <string>

using namespace std;

bool get_int( const string & input, int & i ) {
    stringstream ss(input);
    double d;
    bool isValid = ss >> d;
    if (isValid) {
        char c;
        while( isValid && ss >> c ) isValid = isspace(c);
        if (isValid) { 
            i = static_cast<int>(d);
            isValid = (d == static_cast<double>(i));
        }
    }
    return isValid;
}

int main( int argc, char *argv[] )
{
    int creatLegs = 0;
    bool validLegs = false;

    do
    {
        string line;
        do {
            cout << "How many legs should the creature have? ";
        } while (not getline (cin,line));

        validLegs = get_int( line, creatLegs );

        if (creatLegs <= 0)
        {
            validLegs = false;
        }

        if (not validLegs)
        {
            cout << "Invalid value, try again." << endl;
        }

    } while (not validLegs);

    cout << "Got legs! (" << creatLegs << ")" << endl;

    return 0;
}

Если вам нужны строго целые числа (без десятичного периода и без научных обозначений), используйте следующую более простую функцию get_int:

bool get_int( const string & input, int & i ) {
    stringstream ss(input);
    bool isValid = ss >> i;
    if (isValid) {
        char c;
        while(isValid && ss >> c) isValid = isspace(c);
    }
    return isValid;
}
int creatLegs = 0;
do
{
    cout << "How many legs should the creature have? ";
    cin >> creatLegs;    // trying to get integer
    if(!cin.fail())      // if cin.fail == false, then we got an int and leave loop
        break;
    cout << "Invalid value, try again.\n"; // else show err msg and try once more
    cin.clear();
} while (1);
Другие вопросы по тегам