c++ 尝试将双精度型仅验证为数字

o4tp2gmn  于 2022-12-30  发布在  其他
关注(0)|答案(2)|浏览(177)

我刚开始学习C++,需要一些帮助。
基本上,我的代码是按照我想要的方式工作的。然而,正如你在下面看到的,当我键入一个数字和一个字母时,代码仍然只把变量当作一个数字。
我想看到同样的错误信息,当有人键入一个字母,然后一个数字相同的方式为这一点。我知道这与我的函数,但当我尝试做isNaN(Not-a-Number)同样的问题发生。我做错了什么?
我已经包含了我的函数验证代码,问题是:

#include "functions.h"
#include <iostream>

using namespace std;

double getNumber(){
    double temperature = 0;
    while (cout << "Please enter a temperature between -40 and 40 degrees Celsius: " && !(cin>>temperature))
    {  
        cin.clear();
        cin.ignore(1000, '\n');
        cin.fail();
        cout << "Bad value, try again..." << endl;
        cout <<"\n";
    }

    return temperature;
}

double validRange(double min, double max){
    double temperature = 0;
    while(true){
        temperature = getNumber();
        if(temperature >= min && temperature <= max)
            break;
        else
        {
           cout << "Out of range, value must be between " << min << " and " << max << endl;
        }
    }
    return temperature;
}
mznpcxlj

mznpcxlj1#

要检查输入的有效性,我建议使用斯托德()和异常处理。因为cin接受尽可能多的可以解释为数字的表达式,并且如果发生这种情况,则返回非零值。但是,stod()可以检查解析的字符数,如果检查是否解析了整个表达式,如果没有,则throw,我们可以执行有效性检查。下面是修改后的getnumber():

double getNumber() {
    double temperature;
    bool got_the_value = false;
    while (!got_the_value) {
        try {
            cout << "Please enter a temperature between -40 and 40 degrees Celsius: ";
            string tmpstring;
            cin >> tmpstring;
            size_t pos;
            temperature = stod(tmpstring,&pos);
            if (tmpstring.size() != pos) {
                cerr << "Bad value, try again..." << endl;
                continue;
            }
            got_the_value = true;
        }
        catch (exception& e) {
            cerr << "Bad value, try again..." << endl;
        }
    }
    return temperature;
}
y4ekin9u

y4ekin9u2#

用户输入总是一件痛苦的事。你应该:

  • 从用户处获取 * 字符串 *
  • 将 * 整个 * 字符串转换为您想要的格式
  • 失败时中止(带有错误消息)

我保留了一个小函数来实现这个目的:

#include <optional>
#include <sstream>
#include <string>

template <typename T>
auto string_to( const std::string & s )
{
  T value;
  std::istringstream ss( s );
  return ((ss >> value) and (ss >> std::ws).eof())
    ? value
    : std::optional<T> { };
}

它可以用作:

#include <ciso646>
#include <iostream>

int main()
{
  std::cout << "Please enter a temperature between -40 and 40: ";
  std::string s;
  getline( std::cin, s );
  auto temperature = string_to <double> ( s );
  if (!temperature or (*temperature < -40) or (*temperature > 40))
  {
    std::cerr << "That was not a valid temperature.\n";
    return 1;
  }

  std::cout << "Good job!\nYou entered " << *temperature << "°.\n";
}

如果你打算经常使用它,你甚至可以把普通代码(比如要求一个特定范围内的数值) Package 成一个小函数:

#include <ciso646>
#include <cstdlib>
#include <iostream>

double ask_for_number(
  const std::string & prompt,
  double minimum,
  double maximum,
  const std::string & error_message )
{
  std::cout << prompt;
  std::string s;
  getline( std::cin, s );
  auto number = string_to <double> ( s );
  if (!number or (*number < minimum) or (*number > maximum))
  {
    std::cerr << error_message << "\n";
    exit( 1 );
  }
  return *number;
}

int main()
{
  double temperature = ask_for_number(
      "Please enter a temperature between -40 and 40: ",
      -40, 40,
      "That was not a valid temperature." );
  std::cout << "Good job!\nYou entered " << temperature << "°.\n";
}

这看起来像是大量的输入,但关键是所有的输入都集中在一个地方,它可以一遍又一遍地重复使用,* 而且 * 它工作正常,期望用户为一个提示提供一个输入,并在无效输入时正确地失败。

相关问题