搜索
bottom↓
回复: 22

找一个代替sprintf函数的办法

[复制链接]

出5入4汤圆

发表于 2019-4-8 17:33:20 | 显示全部楼层 |阅读模式
我的一个工程中连续用到了30个sprint函数,用来把变量转换成字符的呈现格式发送出去,但是发现耗时达到了500us
效率挺低的,有什么办法能替换这个函数吗?

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入22汤圆

发表于 2019-4-8 17:42:42 来自手机 | 显示全部楼层
itoa?itoa

出10入0汤圆

发表于 2019-4-8 18:23:15 | 显示全部楼层
如果你自己实现一个弱功能的sprintf,比如限制浮点转整数的位数,不支持高级的格式控制字符,那应该会快些。

出0入90汤圆

发表于 2019-4-8 18:25:27 | 显示全部楼层
自己用多个函数合成吧。合成自己需要的特定内容得了。
你自己去写个可能效率很差,说不定更慢

出0入0汤圆

发表于 2019-4-8 18:39:32 | 显示全部楼层
自己写,快过sprint很多。sprint,会考虑各种情况,所以很多重复动作。

出0入0汤圆

发表于 2019-4-8 19:30:40 | 显示全部楼层
自己写,很容易的

出870入263汤圆

发表于 2019-4-8 17:33:21 | 显示全部楼层
  1. static int xvprintf(char buff[], char const * fmt, va_list arp)
  2. {
  3.   unsigned int r, i, j, w, f;
  4.   unsigned long v;
  5.   char s[16], c, d, *p;
  6.   char *out = buff;

  7.   for (;;) {
  8.     c = *fmt++;                 /* Get a char */
  9.     if (!c) {
  10.       break;                    /* End of format? */
  11.     }
  12.     if (c != '%') {             /* Pass through it if not a % sequense */
  13.       *out++ = c;
  14.       continue;
  15.     }
  16.     f = 0;
  17.     c = *fmt++;                 /* Get first char of the sequense */
  18.     if (c == '0') {             /* Flag: '0' padded */
  19.       f = 1;
  20.       c = *fmt++;
  21.     } else {
  22.       if (c == '-') {           /* Flag: left justified */
  23.         f = 2;
  24.         c = *fmt++;
  25.       }
  26.     }
  27.     for (w = 0; c >= '0' && c <= '9'; c = *fmt++) {
  28.       w = w * 10 + c - '0';     /* Minimum width */
  29.     }
  30.     if (c == 'l' || c == 'L') { /* Prefix: Size is long int */
  31.       f |= 4;
  32.       c = *fmt++;
  33.     }
  34.     if (!c) {
  35.       break;                    /* End of format? */
  36.     }
  37.     d = c;
  38.     if (d >= 'a') {
  39.       d -= 0x20;
  40.     }
  41.     switch (d) {                /* Type is... */
  42.     case 'S' :                  /* String */
  43.       p = va_arg(arp, char*);
  44.       for (j = 0; p[j]; j++);
  45.       if (!(f & 2) && j < w) {
  46.         memset(out, ' ', w - j);
  47.         out += w - j;
  48.         memcpy(out, p, j);
  49.         out += j;
  50.         j = w;
  51.       } else {
  52.         memcpy(out, p, j);
  53.         out += j;
  54.       }
  55.       if (j < w) {
  56.         memset(out, ' ', w - j);
  57.         out += w - j;
  58.       }
  59.       continue;
  60.     case 'C' :                  /* Character */
  61.       *out++ = (char)va_arg(arp, int);
  62.       continue;
  63.     case 'B' :                  /* Binary */
  64.       r = 2;
  65.       break;
  66.     case 'O' :                  /* Octal */
  67.       r = 8;
  68.       break;
  69.     case 'D' :                  /* Signed decimal */
  70.     case 'U' :                  /* Unsigned decimal */
  71.       r = 10;
  72.       break;
  73.     case 'X' :                  /* Hexdecimal */
  74.       r = 16;
  75.       break;
  76.     default:                    /* Unknown type (passthrough) */
  77.       *out++ = c;
  78.       continue;
  79.     }
  80.     /* Get an argument and put it in numeral */
  81.     if(f & 4){
  82.         v = va_arg(arp, long);
  83.     }else{
  84.         if(d == 'D'){
  85.             v = (long)va_arg(arp, int);
  86.         }else{
  87.             v = va_arg(arp, unsigned int);
  88.         }
  89.     }
  90.     if (d == 'D' && (v & 0x80000000)) {
  91.       v = 0 - v;
  92.       f |= 8;
  93.     }
  94.     i = 0;
  95.     do {
  96.       d = (char)(v % r);
  97.       v /= r;
  98.       if (d > 9) {
  99.         d += (c == 'x') ? 0x27 : 0x07;
  100.       }
  101.       s[i++] = d + '0';
  102.     } while (v && i < sizeof(s));
  103.     if (f & 8) {
  104.       s[i++] = '-';
  105.     }
  106.     j = i;
  107.     d = (f & 1) ? '0' : ' ';
  108.     if (!(f & 2) && j < w) {
  109.       memset(out, d, w - j);
  110.       out += w - j;
  111.       do {
  112.         *out++ = s[--i];
  113.       } while(i);
  114.       j = w;
  115.     } else {
  116.       do {
  117.         *out++ = s[--i];
  118.       } while(i);
  119.     }
  120.     if (j < w) {
  121.       memset(out, ' ', w - j);
  122.       out += w - j;
  123.     }
  124.   }
  125.   return ((int)(out - buff));
  126. }

  127. int xsprintf(char* buff, char const * fmt, ...)
  128. {
  129.   va_list arp;
  130.   int len;

  131.   va_start(arp, fmt);
  132.   len = xvprintf(buff, fmt, arp);
  133.   va_end(arp);
  134.   buff[len] = 0;
  135.   return len;
  136. }
复制代码

出0入34汤圆

发表于 2019-4-8 20:11:48 | 显示全部楼层
推荐自己写个,将较常用的判断放在较前面,效率估计会快很多,有点类似手机跑分作弊的方法。

出0入362汤圆

发表于 2019-4-8 21:16:35 | 显示全部楼层
试试elm-chan的xprintf库?不过他的不支持浮点。

出0入0汤圆

发表于 2019-4-8 22:05:47 | 显示全部楼层
我一般自己写,标准库动辄引入1~2kB甚至更多,占用空间而且非常慢

出0入0汤圆

发表于 2019-4-8 23:11:54 | 显示全部楼层

我找了半天,特地在找'f' , 好象没找到。。是不是不支持浮点数。。

出0入8汤圆

发表于 2019-4-8 23:44:44 来自手机 | 显示全部楼层
同求,我现在用的库里面的,而且还不支持浮点数

出5入4汤圆

 楼主| 发表于 2019-4-9 17:23:58 | 显示全部楼层

实测好用,500us变成了180us
今天做了一回伸手党

出0入0汤圆

发表于 2019-4-9 19:16:28 | 显示全部楼层
kinsno 发表于 2019-4-8 23:11
我找了半天,特地在找'f' , 好象没找到。。是不是不支持浮点数。。

好像是没有看到‘f’

出0入0汤圆

发表于 2019-4-9 19:18:43 | 显示全部楼层
tim4146 发表于 2019-4-9 17:23
实测好用,500us变成了180us
今天做了一回伸手党


浮点数呢? 是不是你目前暂时用不上了,还是。。。

出5入4汤圆

 楼主| 发表于 2019-4-10 17:22:42 来自手机 | 显示全部楼层
kinsno 发表于 2019-4-9 19:18
浮点数呢? 是不是你目前暂时用不上了,还是。。。

昨天只测了时间,阴差阳错忘记测数据了,然后今天发现所有的浮点数还有uint64类型数据出不来,已经全改好了,改了一下午……

出0入0汤圆

发表于 2019-4-10 17:29:34 | 显示全部楼层
tim4146 发表于 2019-4-10 17:22
昨天只测了时间,阴差阳错忘记测数据了,然后今天发现所有的浮点数还有uint64类型数据出不来,已经全改好 ...

果然是没有浮点数的啊,看来我上面没有眼花啊。。
你修改后,带浮点数的版本,方便分亨一下吗。



出0入8汤圆

发表于 2019-4-10 17:51:31 来自手机 | 显示全部楼层
找gayhub,很多

出0入0汤圆

发表于 2019-4-10 17:55:10 | 显示全部楼层
写个精简的,去掉各种不要的东西。

出5入4汤圆

 楼主| 发表于 2019-4-10 22:45:14 | 显示全部楼层
kinsno 发表于 2019-4-10 17:29
果然是没有浮点数的啊,看来我上面没有眼花啊。。
你修改后,带浮点数的版本,方便分亨一下吗。

下午写了但是公司代码加密了
说说思路,首先确定整形是可以用的,那么浮点数我就简单一点了,比如123.456需要保留3位小数,那就先乘以1000变成123456 然后当做int去处理了,过程中把小数点在千位前面加上就可以了

出0入0汤圆

发表于 2019-4-10 23:20:18 | 显示全部楼层
简单好用就可以了,不必那么强大;

出140入115汤圆

发表于 2019-4-29 14:50:30 | 显示全部楼层
在github.com找到一个简化:

  1. // mini-printf.h
  2. #ifndef __MINI_PRINTF__
  3. #define __MINI_PRINTF__

  4. #ifdef __cplusplus
  5. extern "C" {
  6. #endif

  7. #include <stdarg.h>

  8. int mini_vsnprintf(char* buffer, unsigned int buffer_len, const char *fmt, va_list va);
  9. int mini_snprintf(char* buffer, unsigned int buffer_len, const char *fmt, ...);

  10. #ifdef __cplusplus
  11. }
  12. #endif

  13. #define vsnprintf mini_vsnprintf
  14. #define snprintf mini_snprintf

  15. #endif
复制代码


  1. #include "mini-printf.h"

  2. static unsigned int
  3. mini_strlen(const char *s)
  4. {
  5.         unsigned int len = 0;
  6.         while (s[len] != '\0') len++;
  7.         return len;
  8. }

  9. static unsigned int
  10. mini_itoa(int value, unsigned int radix, unsigned int uppercase, unsigned int unsig,
  11.          char *buffer, unsigned int zero_pad)
  12. {
  13.         char        *pbuffer = buffer;
  14.         int        negative = 0;
  15.         unsigned int        i, len;

  16.         /* No support for unusual radixes. */
  17.         if (radix > 16)
  18.                 return 0;

  19.         if (value < 0 && !unsig) {
  20.                 negative = 1;
  21.                 value = -value;
  22.         }

  23.         /* This builds the string back to front ... */
  24.         do {
  25.                 int digit = value % radix;
  26.                 *(pbuffer++) = (digit < 10 ? '0' + digit : (uppercase ? 'A' : 'a') + digit - 10);
  27.                 value /= radix;
  28.         } while (value > 0);

  29.         for (i = (pbuffer - buffer); i < zero_pad; i++)
  30.                 *(pbuffer++) = '0';

  31.         if (negative)
  32.                 *(pbuffer++) = '-';

  33.         *(pbuffer) = '\0';

  34.         /* ... now we reverse it (could do it recursively but will
  35.          * conserve the stack space) */
  36.         len = (pbuffer - buffer);
  37.         for (i = 0; i < len / 2; i++) {
  38.                 char j = buffer[i];
  39.                 buffer[i] = buffer[len-i-1];
  40.                 buffer[len-i-1] = j;
  41.         }

  42.         return len;
  43. }

  44. struct mini_buff {
  45.         char *buffer, *pbuffer;
  46.         unsigned int buffer_len;
  47. };

  48. static int
  49. _putc(int ch, struct mini_buff *b)
  50. {
  51.         if ((unsigned int)((b->pbuffer - b->buffer) + 1) >= b->buffer_len)
  52.                 return 0;
  53.         *(b->pbuffer++) = ch;
  54.         *(b->pbuffer) = '\0';
  55.         return 1;
  56. }

  57. static int
  58. _puts(char *s, unsigned int len, struct mini_buff *b)
  59. {
  60.         unsigned int i;

  61.         if (b->buffer_len - (b->pbuffer - b->buffer) - 1 < len)
  62.                 len = b->buffer_len - (b->pbuffer - b->buffer) - 1;

  63.         /* Copy to buffer */
  64.         for (i = 0; i < len; i++)
  65.                 *(b->pbuffer++) = s[i];
  66.         *(b->pbuffer) = '\0';

  67.         return len;
  68. }

  69. int
  70. mini_vsnprintf(char *buffer, unsigned int buffer_len, const char *fmt, va_list va)
  71. {
  72.         struct mini_buff b;
  73.         char bf[24];
  74.         char ch;

  75.         b.buffer = buffer;
  76.         b.pbuffer = buffer;
  77.         b.buffer_len = buffer_len;

  78.         while ((ch=*(fmt++))) {
  79.                 if ((unsigned int)((b.pbuffer - b.buffer) + 1) >= b.buffer_len)
  80.                         break;
  81.                 if (ch!='%')
  82.                         _putc(ch, &b);
  83.                 else {
  84.                         char zero_pad = 0;
  85.                         char *ptr;
  86.                         unsigned int len;

  87.                         ch=*(fmt++);

  88.                         /* Zero padding requested */
  89.                         if (ch=='0') {
  90.                                 ch=*(fmt++);
  91.                                 if (ch == '\0')
  92.                                         goto end;
  93.                                 if (ch >= '0' && ch <= '9')
  94.                                         zero_pad = ch - '0';
  95.                                 ch=*(fmt++);
  96.                         }

  97.                         switch (ch) {
  98.                                 case 0:
  99.                                         goto end;

  100.                                 case 'u':
  101.                                 case 'd':
  102.                                         len = mini_itoa(va_arg(va, unsigned int), 10, 0, (ch=='u'), bf, zero_pad);
  103.                                         _puts(bf, len, &b);
  104.                                         break;

  105.                                 case 'x':
  106.                                 case 'X':
  107.                                         len = mini_itoa(va_arg(va, unsigned int), 16, (ch=='X'), 1, bf, zero_pad);
  108.                                         _puts(bf, len, &b);
  109.                                         break;

  110.                                 case 'c' :
  111.                                         _putc((char)(va_arg(va, int)), &b);
  112.                                         break;

  113.                                 case 's' :
  114.                                         ptr = va_arg(va, char*);
  115.                                         _puts(ptr, mini_strlen(ptr), &b);
  116.                                         break;

  117.                                 default:
  118.                                         _putc(ch, &b);
  119.                                         break;
  120.                         }
  121.                 }
  122.         }
  123. end:
  124.         return b.pbuffer - b.buffer;
  125. }


  126. int
  127. mini_snprintf(char* buffer, unsigned int buffer_len, const char *fmt, ...)
  128. {
  129.         int ret;
  130.         va_list va;
  131.         va_start(va, fmt);
  132.         ret = mini_vsnprintf(buffer, buffer_len, fmt, va);
  133.         va_end(va);

  134.         return ret;
  135. }
复制代码


链接:https://github.com/mludvig/mini-printf

出140入115汤圆

发表于 2019-4-29 14:53:47 | 显示全部楼层
还有一个 可裁剪全功能小型 printf / sprintf
链接:https://github.com/mpaland/printf
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 19:35

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表