c语言 - 检查表示浮点/无符号 int 的字符串是否太大



我有一个文件,其中包含表示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是否有带有非零返回值的减号(可能在前导空格之后)。

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

  • 如果该值为正且太大,则返回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;
}

相关内容

  • 没有找到相关文章

最新更新