一、要点:
实现sprintf,printf的要点在于不定参数的接收与处理,即va_list的使用,另外使用va_list需要包含stdarg.h头函数,想了解详细用法可以自行查找。
另外就是涉及数据的处理与转换,常用的是整型转字符串,以及各种类型转各种格式的字符串。
二、自己实现的类型转换函数
//整形转字符串
void cc_int2str(char *str,int value)
{char tmp_str[20] = {0};int lidx = 0;char flag = 0;int tmp_val;if(value<0){flag = 1;tmp_val = -value;}else{tmp_val = value;}while(1){if(tmp_val==0){break;}else{tmp_str[lidx++] = 0x30+tmp_val%10;tmp_val = tmp_val/10;}}if(flag){tmp_str[lidx++] = '-';}while(lidx--){*str++ = tmp_str[lidx];}*str = 0;
}
//整形转16进制字符串
void cc_int2hexstr(char *str,int value)
{char tmp_str[20] = {0};int lidx = 0;char flag = 0;int tmp_val;if(value<0){flag = 1;tmp_val = -value;}else{tmp_val = value;}while(1){if(tmp_val==0){break;}else{if(tmp_val%16<10){tmp_str[lidx++] = 0x30+tmp_val%16;}else{tmp_str[lidx++] = 0x40+(tmp_val%16-9);}tmp_val = tmp_val/16;}}if(flag){tmp_str[lidx++] = '-';}while(lidx--){*str++ = tmp_str[lidx];}*str = 0;
}
//字符串拷贝函数
int cc_strncpy(char * des,char * src,uint16_t n)
{if(src && des && n){while(n-->0){if(*src){*des++ = *src++;}else{*des++ = *src++;break;}}return 0;}else{return -1;}
}
//字符串拼接函数
int cc_strcat(char * des,char * src)
{if(src && des){while(*des){des++;}while(*src){*des++ = *src++;}*des++ = *src++;return 0;}else{return -1;}
}
//字符串拼接指定长度函数
int cc_strncat(char * des,char * src,uint16_t n)
{if(src && des && n){while(*src){src++;}while(n-->0){if(*src){*des++ = *src++;}else{*des++ = *src++;break;}}return 0;}else{return -1;}
}
三、实现sprintf函数
//记得包含 #include "stdarg.h"void cc_sprintf(char * des,const char *format, ...) {char tmp_str[20] = {0};va_list args;va_start(args, format);*des = 0;while (*format) {switch (*format) {case '%':++format;switch (*format) {case 'd': {int val = va_arg(args, int);cc_int2str(tmp_str,val);cc_strcat(des,tmp_str);break;}case 'x': {int val = va_arg(args, int);cc_int2hexstr(tmp_str,val);cc_strcat(des,tmp_str);break;}case 's': {char *str = va_arg(args, char *);cc_strcat(des,str);break;}default:cc_strcat(des,"%");if (*format) {tmp_str[0] = *format;tmp_str[1] = 0;cc_strcat(des,tmp_str);}break;}break;default:tmp_str[0] = *format;tmp_str[1] = 0;cc_strcat(des,tmp_str);break;}++format;}va_end(args);
}
四、实现printf函数
//记得包含 #include "stdarg.h"
//代码主要针对单片机平台,其他平台请自行修改pchar函数//串口初始化
void Debug_UartCfg(void)
{rcu_periph_clock_enable(RCU_GPIOA);gpio_init(GPIOA,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_9);gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_50MHZ,GPIO_PIN_10);rcu_periph_clock_enable(RCU_USART0);usart_deinit(USART0);usart_baudrate_set(USART0,115200);usart_stop_bit_set(USART0,USART_STB_1BIT);usart_word_length_set(USART0,USART_WL_8BIT);usart_parity_config(USART0,USART_PM_NONE);usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);usart_enable(USART0);
}int pchar(char c)
{while(!usart_flag_get(USART0,USART_FLAG_TBE));usart_data_transmit(USART0,c);while(!usart_flag_get(USART0,USART_FLAG_TC));return 0;
}int putstr(char * c)
{while(*c){pchar(*c++);}return 0;
}void cc_printf(const char *format, ...) {char tmp_str[20] = {0};va_list args;va_start(args, format);while (*format) {switch (*format) {case '%':++format;switch (*format) {case 'd': {int val = va_arg(args, int);int2str(tmp_str,val);putstr(tmp_str);break;}case 'x': {int val = va_arg(args, int);cc_int2hexstr(tmp_str,val);putstr(tmp_str);break;}case 's': {char *str = va_arg(args, char *);putstr(str);break;}default:pchar('%');if (*format) {pchar(*format);}break;}break;default:pchar(*format);break;}++format;}va_end(args);
}