打印
[技术问答]

实现 vsprintf

[复制链接]
550|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
minzisc|  楼主 | 2023-5-21 15:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


#define va_start(ap, v) ap = (va_list)&v  // 把ap指向第一个固定参数v
#define va_arg(ap, t) *((t*)(ap += 4))          // ap指向下一个参数并返回其值
#define va_end(ap) ap = NULL                  // 清除ap

/* 将整型转换成字符(integer to ascii) */
static void itoa(uint32_t value, char** buf_ptr_addr, uint8_t base) {
   uint32_t m = value % base;            // 求模,最先掉下来的是最低位   
   uint32_t i = value / base;            // 取整
   if (i) {                            // 如果倍数不为0则递归调用。
      itoa(i, buf_ptr_addr, base);
   }
   if (m < 10) {      // 如果余数是0~9
      *((*buf_ptr_addr)++) = m + '0';          // 将数字0~9转换为字符'0'~'9'
   } else {              // 否则余数是A~F
      *((*buf_ptr_addr)++) = m - 10 + 'A'; // 将数字A~F转换为字符'A'~'F'
   }
}

/* 将参数ap按照格式format输出到字符串str,并返回替换后str长度 */
uint32_t vsprintf(char* str, const char* format, va_list ap) {
   char* buf_ptr = str;
   const char* index_ptr = format;
   char index_char = *index_ptr;
   int32_t arg_int;
   char* arg_str;
   while(index_char) {
      if (index_char != '%') {
         *(buf_ptr++) = index_char;
         index_char = *(++index_ptr);
         continue;
      }
      index_char = *(++index_ptr);         // 得到%后面的字符
      switch(index_char) {
         case 's':
            arg_str = va_arg(ap, char*);
            strcpy(buf_ptr, arg_str);
            buf_ptr += strlen(arg_str);
            index_char = *(++index_ptr);
            break;

         case 'c':
            *(buf_ptr++) = va_arg(ap, char);
            index_char = *(++index_ptr);
            break;

         case 'd':
            arg_int = va_arg(ap, int);
      /* 若是负数, 将其转为正数后,再正数前面输出个负号'-'. */
            if (arg_int < 0) {
               arg_int = 0 - arg_int;
               *buf_ptr++ = '-';
            }
            itoa(arg_int, &buf_ptr, 10);
            index_char = *(++index_ptr);
            break;

         case 'x':
            arg_int = va_arg(ap, int);
            itoa(arg_int, &buf_ptr, 16);
            index_char = *(++index_ptr); // 跳过格式字符并更新index_char
            break;
      }
   }
   return strlen(str);
}

/* 格式化输出字符串format */
uint32_t printf(const char* format, ...) {
   va_list args;
   va_start(args, format);               // 使args指向format
   char buf[1024] = {0};               // 用于存储拼接后的字符串
   vsprintf(buf, format, args);
   va_end(args);
   return write(buf);
}


使用特权

评论回复
沙发
daichaodai| | 2023-5-21 19:24 | 只看该作者
使用格式化字符串可以实现printf函数功能。

使用特权

评论回复
板凳
ulystronglll| | 2023-6-6 13:36 | 只看该作者
如何使用vsprintf,vsnprintf等函数

使用特权

评论回复
地板
janewood| | 2023-6-6 14:22 | 只看该作者
在传递可变参数列表时,需要按照格式化字符串中占位符的顺序传递相应的参数,否则输出结果可能会出现错误。

使用特权

评论回复
5
bestwell| | 2023-6-6 14:30 | 只看该作者
vsprintf()函数是单片机程序中常用的字符串处理函数之一,在调试和输出结果时具有很重要的作用。

使用特权

评论回复
6
hilahope| | 2023-6-6 14:45 | 只看该作者
在传递格式化字符串时,需要确保其符合标准的格式化占位符规范,如"%d"、"%f"等。

使用特权

评论回复
7
loutin| | 2023-6-6 14:57 | 只看该作者
单片机串口可以用printf发送数据吗?

使用特权

评论回复
8
olivem55arlowe| | 2023-6-6 15:03 | 只看该作者
编译vsprintf错误               

使用特权

评论回复
9
robincotton| | 2023-6-6 15:09 | 只看该作者
printf,sprintf,vsprintf之间的区别是什么呢

使用特权

评论回复
10
10299823| | 2023-6-6 15:21 | 只看该作者
如何用单片机写出类似printf的函数

使用特权

评论回复
11
plsbackup| | 2023-6-6 17:43 | 只看该作者
在调用vsprintf()函数之前,需要确保目标字符数组有足够的内存空间来存储写入的内容。否则,可能会导致数据溢出或者程序崩溃。

使用特权

评论回复
12
beacherblack| | 2023-6-6 17:53 | 只看该作者
该函数与sprintf()函数类似,但不同之处在于可以接受可变参数列表,即可以同时处理多个参数。

使用特权

评论回复
13
Bowclad| | 2023-6-8 17:57 | 只看该作者
和printf有什么区别吗?

使用特权

评论回复
14
saservice| | 2023-6-10 09:49 | 只看该作者
vsprintf()函数是C标准库中的一个字符串处理函数,用于将格式化的数据写入到字符数组中。

使用特权

评论回复
15
chenqianqian| | 2023-6-11 19:49 | 只看该作者
VSprintf即格式化字符串函数,printf也是调用该函数。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

55

主题

5241

帖子

4

粉丝