这是使用浮点值进行输入验证的正确方法吗?

发布于 2024-12-09 06:42:49 字数 1297 浏览 0 评论 0原文

在花费了大量时间研究输入验证之后,我结合了一些想法并提出了这个:

检查字符串是否为有效双精度的函数...

bool isDouble(double& destination, string& source)
{ // 64 bit
  bool goodValue = false;

  if (!source.empty()) {
    errno = 0;
    char *garbage = nullptr;
    destination = strtod(source.c_str(), &garbage);

    if (*garbage == '\0' && errno != ERANGE)
      goodValue = true;
  }

  return goodValue;
}

>用于检查字符串是否为有效 32 位整数...

bool isLong(long& destination, string& source)
{ // 32 bit (base 10)
  const short BASE = 10;
  bool goodValue = false;

  if (!source.empty()) {
    errno = 0;
    char* garbage = nullptr;
    destination = strtol(source.c_str(), &garbage, BASE);

    if (*garbage == '\0' && errno != ERANGE)
      goodValue = true;
  }

  return goodValue;
}

示例实现的函数

using namespace std;

int main() {
  string buffer;
  double value;

  cout << "Enter a value: ";
  getline(cin, buffer, '\n');

  if (isDouble(value, buffer))
    cout << "Value: " << value << endl;
  else
    cout << "ERROR: Invalid input\n";

  return 0;
}

如果我忽略了这种方法的任何内容,任何人都可以发表评论吗?

After spending a good amount of time researching input validation, I combined a few ideas and came up with this:

Function to check a string for a valid double...

bool isDouble(double& destination, string& source)
{ // 64 bit
  bool goodValue = false;

  if (!source.empty()) {
    errno = 0;
    char *garbage = nullptr;
    destination = strtod(source.c_str(), &garbage);

    if (*garbage == '\0' && errno != ERANGE)
      goodValue = true;
  }

  return goodValue;
}

Function to check a string for a valid 32 bit integer...

bool isLong(long& destination, string& source)
{ // 32 bit (base 10)
  const short BASE = 10;
  bool goodValue = false;

  if (!source.empty()) {
    errno = 0;
    char* garbage = nullptr;
    destination = strtol(source.c_str(), &garbage, BASE);

    if (*garbage == '\0' && errno != ERANGE)
      goodValue = true;
  }

  return goodValue;
}

Sample Implementation

using namespace std;

int main() {
  string buffer;
  double value;

  cout << "Enter a value: ";
  getline(cin, buffer, '\n');

  if (isDouble(value, buffer))
    cout << "Value: " << value << endl;
  else
    cout << "ERROR: Invalid input\n";

  return 0;
}

Can anyone comment on if I am overlooking anything with this approach?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

倾听心声的旋律 2024-12-16 06:42:49

我不确定“正确”的方法,但这肯定不是我会做的。首先,也许是最明显的,这段代码:

    for (i = 0, d = 0; i < BUFFSIZE && buffer[i] != 0 && buffer[i] >= '0' &&
             buffer[i] <= '9' || (buffer[i] == '.' && d == 0); i++)
            if (buffer[i] == '.') ++d;

在几个地方重复(至少我认为另一个实例是相同的,并且可能应该是相同的)。

其次,您似乎不允许使用诸如 1e23-1.2 之类的数字,这些数字通常被接受为浮点数。

顺便说一句,我想我会使用 strtod 来尝试转换输入。您可以使用其第二个参数来检测转换是否到达输入字符串的末尾(如果没有,您将知道至少部分输入未被接受)。然后(显然)您会想要检查返回的值是否在所需的范围内。

I'm not sure about "the" correct way, but it's certainly not how I'd do it. First and probably most obvious, this chunk of code:

    for (i = 0, d = 0; i < BUFFSIZE && buffer[i] != 0 && buffer[i] >= '0' &&
             buffer[i] <= '9' || (buffer[i] == '.' && d == 0); i++)
            if (buffer[i] == '.') ++d;

is duplicated in a couple of places (at least I think the other instance is identical, and probably should be anyway).

Second, you don't appear to allow numbers like 1e23 or -1.2, which are usually accepted as floating point.

Offhand, I think I'd use strtod to attempt to convert the input. You can use its second parameter to detect whether a conversion reached the end of the input string (if not, you'll know at least part of the input wasn't accepted). You'll then (apparently) want to check that the returned value was in the desired range.

沙沙粒小 2024-12-16 06:42:49

也许 strtod() 函数可以是在这里提供帮助,因为它告诉您已转换了多少:

const char * buf = get_raw_data(); // somehow

char * endptr;
const double value = strtod(buf, &endptr);

if (endptr != buf + std::strlen(buf))  { /* ... error ... */ }

作为 buf 的源,您可以使用 std::string token 标记您的输入; std::cin>> token; 或类似的东西并使用 token.c_str()

Perhaps the strtod() function can be of help here, as it tells you how much has been converted:

const char * buf = get_raw_data(); // somehow

char * endptr;
const double value = strtod(buf, &endptr);

if (endptr != buf + std::strlen(buf))  { /* ... error ... */ }

As the source for buf you could tokenize your input with std::string token; std::cin >> token; or something like that and use token.c_str().

九命猫 2024-12-16 06:42:49

如果这是您想要的练习,这是可以理解的。但除此之外,您可以使用 istringstream 来避免重新发明轮子:

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int main () {

  int n,val;
  string stringvalues;

  stringvalues = "3.14159254 f01fhasfljk";
  istringstream iss(stringvalues);

  float x,y;
  iss >> x;

  cout << x * 2 << endl;

  iss >> y;
  if ( ! iss.fail() )
    {
      cout << y * 2 << endl;
    }
  else
    {
      cout << "second value not a number..." << endl;
    }

  return 0;
}

If it's an exercise you want, that's understandable. But otherwise, you can use istringstream to avoid reinventing the wheel:

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int main () {

  int n,val;
  string stringvalues;

  stringvalues = "3.14159254 f01fhasfljk";
  istringstream iss(stringvalues);

  float x,y;
  iss >> x;

  cout << x * 2 << endl;

  iss >> y;
  if ( ! iss.fail() )
    {
      cout << y * 2 << endl;
    }
  else
    {
      cout << "second value not a number..." << endl;
    }

  return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文