[原创] 浮点数转字符串函数的实现讨论

lcofjp   2017-4-15 04:22 楼主
今晚,还在继续调试我的430+LCD12832的串口屏,不过,遇到了一个小小的麻烦,就是浮点数转成字符串显示的问题,通常都是走snprintf的捷径,但是在小容量单片机面前就失灵了,在使用snprintf函数的时候,会提示空间不足的错误,看来这printf类的函数还是个空间杀手,没办法了,只能自己写个函数实现了。我在此献个小丑,把代码贴出来,代码肯定是存在不足的,例如我说两点:1. 某些数在计算过程中会引入误差,导致输出不准确。如输入-0.1234f,输出会变成-0.12339
2. 小数部分结尾的0没有做特殊处理,不过代码稍微改动一下即可实现。
欢迎大家讨论与指教,有没有更精确的实现方法?
下面贴出代码:
  1. #include <stdio.h>

  2. void recurParse(int n, char** str, unsigned int* restSize) {
  3.         if (n < 10) {
  4.                 if (*restSize > 1) {
  5.                         **str = n + '0';
  6.                         (*str)++;
  7.                         *restSize -= 1;
  8.                 }
  9.                
  10.         }
  11.         else {
  12.                 recurParse(n / 10, str, restSize);
  13.                 if (*restSize > 1) {
  14.                         **str = n % 10 + '0';
  15.                         (*str)++;
  16.                         *restSize -= 1;
  17.                 }
  18.         }
  19. }
  20. /*
  21. *outBuffer: 输出字符串的缓冲区
  22. *bufferSize: 输出字符串缓冲区的大小
  23. *in: 要转换的浮点数
  24. *decCount: 输出字符串保留的小数位数
  25. *返回值: 写入到缓冲区中的字符个数(不包含\0)
  26. */
  27. int float2String(char* outBuffer, unsigned int bufferSize, float in, unsigned int decCount) {
  28.         int n;
  29.         float dec;
  30.         unsigned int restSize = bufferSize;
  31.         if (restSize == 0) return 0;
  32.         n = (int)in;
  33.         dec = in - n;
  34.         if (in < 0) {
  35.                 if (restSize > 1 && !(n == 0 && decCount == 0)) {
  36.                         *outBuffer++ = '-';
  37.                         --restSize;
  38.                 }
  39.                 n = -n;
  40.         }
  41.         if (dec < 0) {
  42.                 dec = -dec;
  43.         }
  44.         recurParse(n, &outBuffer, &restSize);
  45.         if (decCount != 0) {
  46.                 if (restSize > 1) {
  47.                         *outBuffer++ = '.';
  48.                         --restSize;
  49.                 }
  50.         }
  51.         while (decCount) {
  52.                 dec *= 10;
  53.                 n = (int)dec;
  54.                 dec -= n;
  55.                 if (restSize > 1) {
  56.                         *outBuffer++ = n + '0';
  57.                         --restSize;
  58.                 }
  59.                 else {
  60.                         break;
  61.                 }
  62.                 decCount -= 1;
  63.         }
  64.         *outBuffer++ = NULL;
  65.         return bufferSize - restSize;
  66. }

  67. int main() {
  68.         char o[100];
  69.         float test[] = { -123.456, 1987.9998, -0.1234f, -9999.876, 0.1, 0.00002, 0.33, -0.08, -9.99, 10.04, -100.63, 1001.332 };
  70.         int i, n;
  71.         for (i = 0; i < sizeof(test) / sizeof(float); i++) {
  72.                 n = float2String(o, sizeof(o)/sizeof(char), test[i], 6);
  73.                 printf("%d: %s\n", n, o);
  74.         }
  75.         printf("%f\n", -0.1234f);
  76.         return 0;
  77. }



此内容由EEWORLD论坛网友lcofjp原创,如需转载或用于商业用途需征得作者同意并注明出处


回复评论 (9)

赞,有空研究一下。
点赞  2017-4-15 09:58
在空间有限的处理器上运行递归也不大合适,可以用循环实现,
亚里士缺德
点赞  2017-4-15 14:48
引用: 汤权 发表于 2017-4-15 14:48
在空间有限的处理器上运行递归也不大合适,可以用循环实现,

有道理!
点赞  2017-4-15 15:36
有空研究一下
点赞  2017-6-8 13:30
snprintf生成了多大体积?
点赞  2017-8-11 09:33

你居然用递归?!
强者为尊,弱者,死无葬身之地
点赞  2017-8-11 09:34
引用: 辛昕 发表于 2017-8-11 09:33
snprintf生成了多大体积?

不知道,我看不出来,但是我的MCU是8K空间的
点赞  2017-8-11 11:09
MARK              
点赞  2017-8-11 11:26
为了字符串指针移动后位置能被更改用上了 char** str 指针的指针,这样通过指针作为形参可以修改 char *str。 本帖最后由 damiaa 于 2017-9-25 15:17 编辑
点赞  2017-9-25 14:40
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复