C函数源码解读:atof

el/2024/4/13 14:27:11
作用:将一个asii字符串转化为double类型的数据 
头文件:stdlib.h 

C代码   收藏代码
  1. /* Convert a string to a double.  */  
  2. double  
  3. atof (const char *nptr)  
  4. {  
  5.   return strtod (nptr, (char **) NULL);  
  6. }  


C代码   收藏代码
  1. #if HAVE_CONFIG_H  
  2. # include <config.h>  
  3. #endif  
  4.   
  5. #include <errno.h>  
  6. #ifndef errno  
  7. extern int errno;  
  8. #endif  
  9.   
  10. #include <ctype.h>  
  11.   
  12. #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))  
  13. # define IN_CTYPE_DOMAIN(c) 1  
  14. #else  
  15. # define IN_CTYPE_DOMAIN(c) isascii(c)  
  16. #endif  
  17.   
  18. #define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))  
  19. #define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))  
  20. #define TOLOWER(c) (IN_CTYPE_DOMAIN (c) ? tolower(c) : (c))  
  21.   
  22. #include <math.h>  
  23.   
  24. #include <float.h>  
  25. #include <stdlib.h>  
  26. #include <string.h>  
  27.   
  28. /* Convert NPTR to a double.  If ENDPTR is not NULL, a pointer to the 
  29.    character after the last one used in the number is put in *ENDPTR.  */  
  30. double  
  31. strtod (const char *nptr, char **endptr)  
  32. {  
  33.   register const char *s;  
  34.   short int sign;  
  35.   
  36.   /* The number so far.  */  
  37.   double num;  
  38.   
  39.   int got_dot;                  /* Found a decimal point.  */  
  40.   int got_digit;                /* Seen any digits.  */  
  41.   
  42.   /* The exponent of the number.  */  
  43.   long int exponent;  
  44.   
  45.   if (nptr == NULL) /*如果为空串,则结束转换*/  
  46.     {  
  47.       errno = EINVAL;  
  48.       goto noconv; /*转向处理无法转换的代码*/  
  49.     }  
  50.   
  51.   s = nptr;  
  52.   
  53.   /* Eat whitespace.  */  
  54.   while (ISSPACE (*s))  
  55.     ++s;  
  56.   
  57.   /* Get the sign.  */  
  58.   sign = *s == '-' ? -1 : 1;  
  59.   if (*s == '-' || *s == '+')  
  60.     ++s;  
  61.   
  62.   num = 0.0;  
  63.   got_dot = 0;  
  64.   got_digit = 0;  
  65.   exponent = 0;  
  66.   for (;; ++s)  
  67.     {  
  68.       if (ISDIGIT (*s))  
  69.         {  
  70.           got_digit = 1;  
  71.   
  72.           /* Make sure that multiplication by 10 will not overflow.  */  
  73.           if (num > DBL_MAX * 0.1)  
  74.             /* The value of the digit doesn't matter, since we have already 
  75.                gotten as many digits as can be represented in a `double'. 
  76.                This doesn't necessarily mean the result will overflow. 
  77.                The exponent may reduce it to within range. 
  78.  
  79.                We just need to record that there was another 
  80.                digit so that we can multiply by 10 later.  */  
  81.             ++exponent;  
  82.           else  
  83.             num = (num * 10.0) + (*s - '0');  
  84.   
  85.           /* Keep track of the number of digits after the decimal point. 
  86.              If we just divided by 10 here, we would lose precision.  */  
  87.           if (got_dot)  
  88.             --exponent;  
  89.         }  
  90.       else if (!got_dot && *s == '.')  
  91.         /* Record that we have found the decimal point.  */  
  92.         got_dot = 1;  
  93.       else  
  94.         /* Any other character terminates the number.  */  
  95.         break;  
  96.     }  
  97.   
  98.   if (!got_digit)  
  99.     goto noconv;  
  100.   
  101.   if (TOLOWER (*s) == 'e')  
  102.     {  
  103.       /* Get the exponent specified after the `e' or `E'.  */  
  104.       int save = errno;  
  105.       char *end;  
  106.       long int exp;  
  107.   
  108.       errno = 0;  
  109.       ++s;  
  110.       exp = strtol (s, &end, 10);  
  111.       if (errno == ERANGE)  
  112.         {  
  113.           /* The exponent overflowed a `long int'.  It is probably a safe 
  114.              assumption that an exponent that cannot be represented by 
  115.              a `long int' exceeds the limits of a `double'.  */  
  116.           if (endptr != NULL)  
  117.             *endptr = end;  
  118.           if (exp < 0)  
  119.             goto underflow;  
  120.           else  
  121.             goto overflow;  
  122.         }  
  123.       else if (end == s)  
  124.         /* There was no exponent.  Reset END to point to 
  125.            the 'e' or 'E', so *ENDPTR will be set there.  */  
  126.         end = (char *) s - 1;  
  127.       errno = save;  
  128.       s = end;  
  129.       exponent += exp;  
  130.     }  
  131.   
  132.   if (endptr != NULL)  
  133.     *endptr = (char *) s;  
  134.   
  135.   if (num == 0.0)  
  136.     return 0.0;  
  137.   
  138.   /* Multiply NUM by 10 to the EXPONENT power, 
  139.      checking for overflow and underflow.  */  
  140.   
  141.   if (exponent < 0)  
  142.     {  
  143.       if (num < DBL_MIN * pow (10.0, (double) -exponent))  
  144.         goto underflow;  
  145.     }  
  146.   else if (exponent > 0)  
  147.     {  
  148.       if (num > DBL_MAX * pow (10.0, (double) -exponent))  
  149.         goto overflow;  
  150.     }  
  151.   
  152.   num *= pow (10.0, (double) exponent);  
  153.   
  154.   return num * sign;  
  155.   
  156. overflow:  
  157.   /* Return an overflow error.  */  
  158.   errno = ERANGE;  
  159.   return HUGE_VAL * sign;  
  160.   
  161. underflow:  
  162.   /* Return an underflow error.  */  
  163.   if (endptr != NULL)  
  164.     *endptr = (char *) nptr;  
  165.   errno = ERANGE;  
  166.   return 0.0;  
  167.   
  168. noconv:  
  169.   /* There was no number.  */  
  170.   if (endptr != NULL)  
  171.     *endptr = (char *) nptr;  
  172.   return 0.0;  
  173. }  


http://www.ngui.cc/el/4967903.html

相关文章

遍历系统中的所有进程,根据szName杀死指定的程序

遍历系统中的所有进程&#xff0c;根据szName杀死指定的程序&#xff08;这个是在Qt下运行的&#xff0c;如果要放到Visual Studio下&#xff0c;只需删掉qDebug&#xff0c;换成cout即可&#xff09;。这段代码是网友写的&#xff0c;我之所以写本文章是因为&#xff0c;这段代…

QWT库的编译及配置

1. QWT的sourcecode 下载&#xff1a; 压缩包&#xff1a;https://sourceforge.net/projects/qwt/files/qwt/ SVN&#xff1a;svncheckout svn://svn.code.sf.net/p/qwt/code/branches/qwt-6.1 选用哪个方式&#xff0c;皆可。 2. 编译source code a) 打开Qt的命令…

mingw32编译Qt5.6.2动态库

&#xff08;1&#xff09;mingw32 手动编译Qt库&#xff1a; configure.bat -opensource -debug-and-release -platform win32-g -prefix E:\Qt\build -no-openssl -cstd c11 -opengl desktop -no-icu -skip qt3d -skip qtandroidextras -skip qtquickcontrols -skip qtquick…

C++串口操作以及串口模拟测试

串口一般分为同步操作和异步操作&#xff0c;串口编程一般分为以下几个步骤&#xff1a;打开串口&#xff0c;配置串口&#xff0c;串口读写和关闭串口。 &#xff08;1&#xff09;打开串口 Win32系统把文件的概念进行了扩展。无论是文件、通信设备、命名管道、邮件槽、磁盘…

Linux SVN 提交忽略指定类型文件

Linux SVN 提交时忽略一些文件方法&#xff1a; &#xff08;1&#xff09;修改 ~/.subversion/config 在config文件中把global-ignores前的注释去掉&#xff0c;注意&#xff1a;命令要顶格写&#xff0c;前不能有空格&#xff0c;在后面添加需要忽略的文件&#xff0c;保存…

AlexNet 参数计算

FeatureMap大小计算公式&#xff1a; No Padding&#xff1a; 长&#xff08;Input长-过滤器长2x填充数目&#xff09;/步长 1 宽&#xff08;Input宽-过滤器宽2x填充数目&#xff09;/步长 1 Padding&#xff1a; 长Input长/步长1 宽Input宽/步长1 AlexNet&#xff1a; Inp…

判别模型和生成模型

1 生成式模型 朴素贝叶斯 K近邻(KNN) 混合高斯模型&#xff08;Mixtures of Gaussians&#xff09; 隐马尔科夫模型(HMM) 贝叶斯网络 Sigmoid Belief Networks 马尔科夫随机场(Markov Random Fields) 深度信念网络(DBN) 2 判别式模型 线性回归(Linear Regression) 线性判别分…

获取最新人工智能,机器学习论文网址入口

https://medium.com/i.oleks/where-to-find-the-latest-machine-learning-papers-f6633168629

nRF51中关于SVCALL的使用

SVCall 一个特殊的中断&#xff1a;SVCall 简述&#xff1a;一种由程序进行触发的中断&#xff0c;默认开启 起源&#xff1a;SVC&#xff08;系统服务调用&#xff0c;亦简称系统调用&#xff09;多用于在操作系统之上的软件开发中。SVC 用于产生系统函数的调用请求。例如&…

nrf51822 keil地址设置

options fof target----target 可以看到下面的IROM1 和 IRAM1前面已经勾上&#xff0c;这就是设置ROM / RAM空间的地方。 我们假设现在要烧写的协议栈是6.0&#xff0c;根据官方文档&#xff0c;占用 80K ROM 和 8K RAM。 NRF51822的ROM为256K &#xff0c;RAM为16K&#xff0…