繁体   English   中英

检查表示 float/unsigned int 的字符串是否太大

[英]Check if a string representing float/unsigned int is too big

我有一个文件,其中包含表示floatuint64_t值的字符串。

我确切地知道哪个字符串包含float值,哪个字符串包含uint64_t值——这不是我面临的问题。

以下是我如何将它们转换为各自的数据类型:

char* t, v; 
uint64_t cn; 


cn = strtoull(t, &v, 10);

char* tt, vv; 
float cn2; 

cn2 = strtof(tt, vv); 

但是问题出现在我想捕捉的以下边缘情况:

假设uint64_t的字符串是"99999999999999999999999999999999999999999999999999"

这不能在 8 个字节内表示,因此会导致溢出,导致cn = 18446744073709551615

float cn2有同样的问题。

怎样才能捕捉到这种行为?

strtoull指示该值超出范围。 考虑这段代码:

#include <errno.h>
…
errno = 0; // Set error code to zero before call.
unsigned long long x = strtoull(t, &v, 10);
if (errno == ERANGE)
{
    // Handle out-of-range error.
}

如果t中的数字太大,这将达到错误情况。

请注意,如果t包含一个减号(但幅度不是太大), strtoull将返回一个在unsigned long long类型中“取反”的值(即环绕ULLONG_MAX +1 的值),即使是负数值超出类型范围; 不会提供错误指示。 所以,如果你想检测所有超出范围的情况,你必须检查t是否有一个非零返回值的减号(可能在前导空格之后)。

根据 C 2018 7.22.1.3 10, strtof提供了足够的信息来区分案例:

  • 如果该值为正且太大,则返回HUGE_VALF并将errno设置为ERANGE
  • 如果该值为负数且太大,则返回-HUGE_VALF并将errno设置为ERANGE
  • 如果该值下溢正常范围,则返回一个小值并将errno设置为ERANGE

根据这个strtoull参考,当发生溢出时,它将返回ULLONG_MAX并且errno设置为ERANGE

因此,您应该在调用之前将errno为零,之后可以检查ULLONG_MAXerrno == ERANGE以查看是否发生溢出。

strtof类似,它将返回HUGE_VALF

如果值小于 0 需要检测

strtoull("-1", ..., ...) “换行”并返回ULLONG_MAX

strto(u)ll()至少转换为 64 位整数。 unsigned long long可能超过 64 位的未来增长做计划。

例子:

#include <errno.h>
#include <stdint.h>
#include <stdlib.h>

uint64_t convert_str_uint64(const char *s, char **endptr, int base) {
  errno = 0;
  long long ival = strtoll(s, endptr, base);
  // Look for negative numbers
  if (ival < 0) {
    errno = ERANGE;
    return 0;
  }
  // We are done for many positive numbers
  if (*endptr > s && ival <= INT64_MAX && errno == 0) {
    return (uint64_t) ival;
  }

  // Input may still be a valid value more than INT64_MAX.
  errno = 0;
  unsigned long long uval = strtoull(s, endptr, base);

#if ULLONG_MAX > UINT64_MAX
  if (uval > UINT64_MAX) {
    uval = UINT64_MAX;
    errno = ERANGE;
  }
#endif

  return (uint64_t) uval;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM