【问题标题】:strtod not recognizing infstrtod 无法识别 inf
【发布时间】:2018-05-26 09:49:13
【问题描述】:

我有以下代码:

int check_for_non_number(char *input, int lineNum)
{
    errno = 0;
    char *endptr;
    printf("%s\n",input);
    double xnum = strtod(input, &endptr);
    // IF endptr FOUND A NON-VALID ENTRY AND THAT ENTRY IS NOT THE NEW LINE CHARACTER THEN ITS AN ERROR
    if((*endptr) && (*endptr != '\n'))
    {
        return 1;
    }
    // We still want to process this number, even if it is represented as inf, so inform the user in the terminal and then return 0
    else if (errno == ERANGE)
    {
        printf("\nOPERAND IS OUT OF RANGE ON LINE %d\n",lineNum);
        return 0;
    }
    // ELSE IF endptr FOUND A NON-VALID ENTRY AND THAT ENTRY IS THE NEW LINE CHARACTER THEN RETURN 2 TO CHECK IF IT SHOULD BE A NEW LINE
    else if((*endptr) && (*endptr == '\n'))
    {
        return 2;
    }
    else
    {
        return 0;
    }
}

input 的值来自strtok(),并被传递到check_for_non_number 函数中...

问题是当 strtok 从文本文件中读取“inf”时,我的函数返回 1,暗示第一个参数为真... 为清楚起见,文本文件中的“inf”位于文本文件行的中间,因此前后都有文本,前后都使用了strtok。

如果有人能解释为什么strtod() 没有将“inf”作为输入来处理,将不胜感激!

【问题讨论】:

  • 尝试printf("{%s}\n",input);(注意大括号)以更清楚地了解函数传递的内容。
  • 你的平台是什么?也许您平台上的strtod 实现没有实现"INF" 的转换。
  • 旁白:在strtod() 之前而不是在printf() 之前编码errno = 0; 更谨慎
  • double xnum = strtod(input, &endptr); 之后,添加printf("<%s> <%s> %.20e %d\n", input, endptr, xnum, errno); 并报告结果以提供更多信息。

标签: c strtod


【解决方案1】:

C11 标准要求strtod() 识别INF

主题序列的预期形式是可选的加号或减号,然后是以下之一:

  • 一个非空的十进制数字序列,可选地包含一个小数点字符,然后是 6.4.4.2 中定义的可选指数部分;
  • 一个 0x 或 0X,然后是一个非空的十六进制数字序列,可选地包含一个小数点字符,然后是一个可选的二进制指数部分,如 6.4.4.2 中所定义;
  • INF 或 INFINITY,忽略大小写
  • NAN 或 NAN(n-char-sequenceopt),忽略 NAN 部分的大小写,其中:

     n-char-sequence:
             digit
             nondigit
             n-char-sequence digit
             n-char-sequence nondigit
    

主题序列被定义为输入字符串的最长初始子序列,从第一个非空白字符开始,即预期形式。如果输入字符串不是预期的形式,则主题序列不包含任何字符。

如果您可以证明(通过使用诸如 "inf" 之类的字符串调用您的函数)它无法将其转换为无穷大,那么您的实现提供的 strtod() 中存在错误 - 或者它符合 C90但不是 C99 或更高版本。 strtod() 的 C90 规范没有提到十六进制格式(这些是在 C99 中添加到语言中的),也没有提到无穷大或 NaN 处理。从 C99 开始,需要支持这些符号。

如果您无法使用 C90 运行时库,则必须升级到具有支持的较新版本,或者实现您自己的 strtod() 变体,或者选择开源实现。请注意开源实现还需要多少额外的支持代码才能正确处理语言环境等。

请注意,Microsoft Visual Studio 2017 运行时似乎支持 strtod() 的 C11 规范,2015 版本(这是 Microsoft Docs 网站上最早可用的版本)也是如此。如果您使用的是旧版本的 MSVS,则需要升级。

【讨论】:

  • OP的系统不兼容,即他的C运行时库没有正确实现printfstrtod。很可能是旧的 Microsoft C 库。有没有办法解决这个问题?
  • @chqrlie:“修复”它的唯一方法是编写自己的 strtod() 或下载不需要太多其他支持代码的开源版本(语言环境支持可能是一个问题,例如)。或者升级到更新的系统。
  • 题后的cmets太啰嗦了(实在太多了),不利于全文阅读。
  • 是的,这是我的问题:有没有办法升级 Microsoft C 运行时库并支持标头?
  • 令我惊讶的是,没有人在 cmets 中提到缺乏一致性的明显根本原因。您的答案是正确的:实现不符合标准,重新实现 printfstrtod 不适合胆小的人,即使来自开源库代码也是如此。如果可能的话,升级运行时环境似乎是一个更好的选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-18
  • 2013-04-19
相关资源
最近更新 更多