Валидация и конвертация поплавка

0

Я пишу программу, где я должен проверить, что введенное значение пользователем является допустимым числом с плавающей запятой. Итак, я пробовал этот метод:

string test;
cin >> test;
float n;
n = atof(test.c_str());
cout << n << endl;

Но, похоже, это не делает работу; когда он выполняет преобразование, числа после . потеряны. Как я могу проверить, что допустимый номер с плавающей запятой используется в C++ (не 11)?

Примеры:

INPUT: 32.e
OUTPUT: 32 (should be error)

INPUT: 2a.1234
OUTPUT: 2 (should be error)
  • 0
    Прочитайте данные (строку) в строку. Используйте функцию strtod() (из <cstdlib> или более <cstdlib> на C ++ альтернативы), чтобы выполнить преобразование. Учитывая адрес подходящего указателя на char, strtod() также сообщает, где он прекратит преобразование. Вы можете решить, хотите ли вы возражать против того, что появляется после этого (например, разрешены ли пробелы, табуляции, новые строки).
Теги:
string
floating-point
validation

3 ответа

3
Лучший ответ

Когда вы используете форматированные чтения в сочетании с проверкой, читается ли все, вы можете определить, является ли значение [complete] допустимым числом с плавающей запятой, например:

int main()
{
    for (std::string test; std::cin >> test; ) {
        std::istringstream in(test);
        double value;
        if (in >> value >> std::ws && in.eof()) {
            std::cout << "the string '" << test << "' is a valid floating point number\n";
        }
        else {
            std::cout << "the string '" << test << "' is not a valid floating point number\n";
        }
    }
}

Тест игнорирует пробелы, окружающие строку. Если это нежелательно, можно использовать манипулятор std::noskipws, и использование std::ws может быть опущено. В качестве альтернативы вы можете использовать strtod() чтобы определить, является ли все значение числом с плавающей запятой.

Какой atof() должен просто увидеть, является ли исходная строка его аргумента допустимым числом с плавающей запятой, которое имеет место для примеров, которые вы указали.

  • 0
    Хорошее решение, похоже, работает на все случаи, о которых я мог подумать. Мне нужна мысль с плавающей точкой, которая отлично справляется со своей задачей, поэтому strtod () не подходит, если я не выполняю много преобразований.
  • 0
    Несколько вопросов, чтобы убедиться, что я правильно понимаю ваш пример, так как я новичок. Во-первых, мы используем цикл for (может быть типа while или другого типа, чтобы поддерживать ввод), затем мы объявляем поток строк, вызванный со значением строки. Затем мы пытаемся записать значение строки в значение переменной типа double, и std :: ws игнорирует любые пробелы в строке, а in.eof () идет до конца строки (чтобы записать все элементы), и если это правда (не провалился до конца), он возвращает истину, иначе это ложь?
Показать ещё 1 комментарий
1
int main() {
    float f;
    cin >> f;
    if (!cin.fail()) {
        cout << f << endl;
    } else {
        cout << "Invalid input" << endl;
    }
    // your code goes here
    return 0;
}

Функция fail() проверяет failbit и badbit в потоке. сигналы failbit что вы хотите, если была логическая ошибка при операции ввода-вывода (пример: попытаться прочитать поплавок, но не смог разобрать токен для поплавка) и сигналы badbit если была ошибка чтения/записи на i/o (не умеет читать/записывать токен вообще).

  • 0
    Это примет две строки, которые считались недействительными, как действительные тоже!
  • 0
    @ DietmarKühl приведи пример
Показать ещё 7 комментариев
0

Ответ действительно зависит от того, хотите ли вы проверить всю строку ввода. atof будет работать, даже если только начало ввода является поплавком (например, 3.3a, 4.72abc). Если вы хотите, чтобы весь входной поток был проверен, вам придется использовать getline для чтения строки и ее анализа. Просто проверьте наличие только цифр плюс один ".".

Я благодарю C++ faq lite за основную идею. http://www.parashift.com/C++-faq/istream-and-ignore.html

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

#include <iostream>
#include <limits>

int main()
{
    while(true)
    {
      double value = 0;

      while ((std::cout << "Enter a floating point number\n ")
             && !(std::cin >> value)) {
        std::cout << "\nThat not a floating point number\n ";
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
      }

      std::cout << "You entered " << value << "\n";
    }
    return 0;
}
  • 0
    Это довольно хорошо, но не получается, если вы наберете, например, 2 ... 55 или 2.5.5
  • 0
    Помните, что -3.21e + 46 является допустимой double константой в большинстве систем. То есть вам нужно учесть знаки, а может быть и показатели. И это еще до того, как вы начнете учитывать шестнадцатеричные константы.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню