[C语言]自己实现sprintf,printf函数

一、要点:

实现sprintf,printf的要点在于不定参数的接收与处理,即va_list的使用,另外使用va_list需要包含stdarg.h头函数,想了解详细用法可以自行查找。

另外就是涉及数据的处理与转换,常用的是整型转字符串,以及各种类型转各种格式的字符串。

二、自己实现的类型转换函数

//整形长度
int cc_intlen(int value)
{
	int number	=	value>0?value:-value;
	int len = 1;
	while(number>=10){
		len++;
		number /= 10;
	}
	return len;
}

//字符串长度
int cc_strlen(char * src)
{
	int len = 0;
	if(src){
		while(*src++){
			len++;
		}
		return len;
	}else{
		return -1;
	}
}

//整形转字符串
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;
	}
	if(value==0){
		tmp_str[lidx++] = 0x30+tmp_val%10;
	}else{
		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;
	}
	if(value==0){
		tmp_str[lidx++] = 0x30+tmp_val%10;
	}else{
		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 debug_sprintf(char * des,const char *format, ...) {
		char tmp_str[20] = {0};
		int len = 0,li = 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;
                    }
										case '0': {
												++format;
												switch(*format){
													case '1':
													case '2':
													case '3':
													case '4':
													case '5':
													case '6':
													case '7':
													case '8':
													case '9': {
															len = *format-'0';
															++format;
															switch (*format) {
																	case 'd': {
																			int val = va_arg(args, int);
																			for(li=0;li<len - cc_intlen(val);li++){
																				tmp_str[li]='0';
																			}
																			tmp_str[li] = 0;
																			cc_int2str(tmp_str,val);
																			cc_strcat(des,tmp_str);
																			break;
																	}
																	case 'x': {
																			int val = va_arg(args, int);
																			for(li=0;li<len - cc_intlen(val);li++){
																				tmp_str[li]='0';
																			}
																			tmp_str[li] = 0;
																			cc_strcat(des,tmp_str);
																			cc_int2hexstr(tmp_str,val);
																			cc_strcat(des,tmp_str);
																			break;
																	}
																	case 's': {
																			char *str = va_arg(args, char *);
																			for(li=0;li<len - cc_strlen(str);li++){
																				tmp_str[li]=' ';
																			}
																			tmp_str[li] = 0;
																			cc_strcat(des,tmp_str);
																			cc_strcat(des,str);
																			break;
																	}
																	default:{
																			cc_strcat(des,"%");
																			if (*format) {
																					tmp_str[0] = '0';
																					tmp_str[1] = len+'0';
																					tmp_str[2] = *format;
																					tmp_str[3] = 0;
																					cc_strcat(des,tmp_str);
																			}
																			break;
																	}
															}
															break;
													}
													default:
														cc_strcat(des,"%");
														if (*format) {
																tmp_str[0] = '0';
																tmp_str[1] = *format;
																tmp_str[2] = 0;
																cc_strcat(des,tmp_str);
														}
														break;
												}
												break;
										}
										case '1':
										case '2':
										case '3':
										case '4':
										case '5':
										case '6':
										case '7':
										case '8':
										case '9': {
												len = *format-'0';
												++format;
												switch (*format) {
														case 'd': {
																int val = va_arg(args, int);
																for(li=0;li<len - cc_intlen(val);li++){
																	tmp_str[li]=' ';
																}
																tmp_str[li] = 0;
																cc_int2str(tmp_str,val);
																cc_strcat(des,tmp_str);
																break;
														}
														case 'x': {
																int val = va_arg(args, int);
																for(li=0;li<len - cc_intlen(val);li++){
																	tmp_str[li]=' ';
																}
																tmp_str[li] = 0;
																cc_strcat(des,tmp_str);
																cc_int2hexstr(tmp_str,val);
																cc_strcat(des,tmp_str);
																break;
														}
														case 's': {
																char *str = va_arg(args, char *);
																for(li=0;li<len - cc_strlen(str);li++){
																	tmp_str[li]=' ';
																}
																tmp_str[li] = 0;
																cc_strcat(des,tmp_str);
																cc_strcat(des,str);
																break;
														}
														default:{
																cc_strcat(des,"%");
																if (*format) {
																		tmp_str[0] = len+'0';
																		tmp_str[1] = *format;
																		tmp_str[2] = 0;
																		cc_strcat(des,tmp_str);
																}
																break;
														}
												}
												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);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值