【问题标题】:return value of strtod() if string equals to zero如果字符串为零,则返回 strtod() 的值
【发布时间】:2015-03-14 10:56:19
【问题描述】:

根据 MSDN:

  • 如果无法执行转换或发生下溢,strtod 返回 0。

如果我的字符串等于零(即 0.0000)怎么办?我如何知道转换是否没有错误?

好的,我用下面的代码来验证一下思路:

char    *Y = "XYZ";
double  MyNum;
char    *MyEndPtr;
int     Err_Conversion = 0;

errno = 0;  //reset
MyNum = strtod (Y, &MyEndPtr);

if ( (MyNum == 0) && (errno != 0) && (strcmp(Y, MyEndPtr) == 0) )
        { Err_Conversion = 1;   }

我看到 MyNum = 0,但从来没有看到 Y 的内容复制到 MyEnPtr,或者在这个强制错误中 errno = 0。有什么想法吗?

【问题讨论】:

  • 检查errno。下溢时errno 设置为ERANGE
  • 是的,但我的情况与下溢无关。它是关于转换一个数值为零的字符串。
  • strtod(nptr, endp); : 检查*endp 如果是无效字符。
  • 为什么将MyEndPtr 设为100 的数组?你为什么使用strcmp?我确实发布了有效的代码。
  • @Cornstalks,你是对的。我不需要 100 那里。顺便说一句,我意识到即使转换是强制错误,errno 也将始终为 0。

标签: c error-handling strtod


【解决方案1】:

签名是(给或取restrict关键字):

 double strtod(const char *nptr, char **endptr);

如果你传递一个非空指针作为第二个参数,如果它不能执行转换,它将返回nptr 的值。如果它在输入字符串中发现一个真正的零,那么存储在*endptr 中的值将不是nptr

char *end;
const char *data = "0.00000";

errno = 0;
double d = strtod(data, &end);
if (end != data)
    ...a conversion was performed...
else
    ...trouble...

您也可以查看errno,但您需要在调用之前将其归零,因为标准 C 库或 POSIX 库中没有函数将 errno 设置为零。

标准说:

如果主题序列为空或不具有预期形式,则不进行转换; nptr 的值存储在endptr 指向的对象中,前提是endptr 不是空指针。

返回

函数返回转换后的值(如果有)。如果无法执行转换,则返回零。如果正确的值溢出并且默认舍入生效(7.12.1),则返回正负 HUGE_VAL、HUGE_VALF 或 HUGE_VALL(根据值的返回类型和符号),并存储宏 ERANGE 的值在errno。如果结果下溢 (7.12.1),则函数返回一个值,其大小为 不大于返回类型中最小的归一化正数; errno 是否获取 ERANGE 值是实现定义的。

【讨论】:

  • 所以你是说如果我的输入字符串等于0,它会返回一个零,但是endptr和输入字符串的内容不一样?
  • @Leffler,我意识到即使转换是强制错误,errno 也将始终为 0。
  • 唯一一次总是设置 errno 是当数字是可识别的数字但绝对值太大而无法适应类型时。如果数字太小,即使它不为零,也无法表示,您可能会或可能不会获得errno 中设置的值。但是如果你用"@#$()"呈现它,函数就会失败,返回0.0,但是endptr的值将是指向字符串中@符号的指针;没有发生转换。如果字符串包含"-0@Gadzooks",则返回值为0.0endptr 将指向@ 符号;发生了有效的转换。
【解决方案2】:

使用函数的str_end 参数。例如:

const char* str = "123junk";
char* str_end;
double d = strtod(str, &str_end);
// Here:
//   d will be 123
//   str_end will point to (str + 3) (the 'j')

// You can tell the string has some junk data if *str_end != '\0'
if (*str_end != '\0') {
    printf("Found bad data '%s' at end of string\n", str_end);
}

如果转换完全失败,str 将等于 str_end

const char* str = "junk";
char* str_end;
double d = strtod(str, &str_end);
// Here:
//   d will be 0 (conversion failed)
//   str_end will equal str

if (str == str_end) {
    printf("The string doesn't start with a number!\n");
}

您可以结合这两种方法来确保字符串(完全)成功转换(即通过检查str != str_end && *str_end == '\0'

【讨论】:

  • 嘿,在我的代码中,我指定了 MyEndPtr [100],因为原始代码进行了多次比较。 sn-p 被回收 - 不能使用您的 1-timed char 声明。另外,输入字符串的长度是可变的。我实际上在我的代码中指定了 MyEndPtr [maxlength]。有什么解决办法吗?
猜你喜欢
  • 2021-04-04
  • 2021-11-30
  • 1970-01-01
  • 2013-12-11
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 2016-05-30
相关资源
最近更新 更多