实现printf以及Sprintf源码
printf函数的全称为格式化输出函数。之所以叫做格式化出,是因为这个函数提供有多种格式化输出方式,可以向标准输出中输出某种格式的内容。本文目标是详细的讲述printf函数的用法,写法,原理。
int printf(const char *format, ...);
E. printf("%s,666,%s",a ,b);
"%s,666,%s"为format. printf是一个带有不定参量的函数
为了进一步理解不定参量,我们引入stdarg头文件,举个例子如何实现不定参量:
void printargs(int arg1, ...)
{
va_list ap;
int i;
va_start(ap, arg1);
for (i = arg1; i >= 0; i = va_arg(ap, int))
printf("%d ", i);
va_end(ap);
putchar('\n');
}
int main(void)
{
printargs(5, 2, 14, 84, 97, 15, -1, 48, -1);
printargs(84, 51, -1, 3);
printargs(-1);
printargs(1, -1);
return 0;
}
通过上述方式我们能够学会如何通过stdarg实现不定参量作为参数列表的函数。
那么下一步讲解printf的具体实现,首先printf需要完成能够接收%d、%s、%p等输出格式控制符,我们进行了如下的实现:
int vsprintf(char *out, const char *fmt, va_list ap) {
char* buf_p = out;
static char str_temp[64];
while (*fmt != '\0') {
if (*fmt != '%') {
*buf_p++ = *fmt++;
}
else {
switch (*(++fmt)) {
case 'c':
char ch = va_arg(ap, int);
*buf_p++ = ch;
break;
case 's':
char* str = va_arg(ap, char*);
size_t len_s = strlen(str);
strcpy(buf_p, str);
buf_p += len_s;
break;
case 'd':
int num_d = va_arg(ap, int);
char* num_d2str = itoa(num_d, (char*)&str_temp, 10);
strcpy(buf_p, num_d2str);
size_t len_d = strlen(num_d2str);
buf_p += len_d;
break;
case 'p':
int num_p = va_arg(ap, int);
char* num_p2str = itoa(num_p, (char*)&str_temp, 16);
strcpy(buf_p, num_p2str);
size_t len_p = strlen(num_p2str);
buf_p += len_p;
break;
default:
break;
}
fmt++;
}
}
*buf_p++ = '\0';
return buf_p - out;
}
阅读上述代码,它能够实现对一串字符串的转义,能够将所有的格式控制符进行处理,并且将之最后的结果放入到字符串中。
那么很容易实现下列printf的函数:
int printf(const char *fmt, ...) {
va_list args;
int ret;
va_start(args, fmt);
ret = vsprintf(printf_buf, fmt, args);
va_end(args);
puts(printf_buf);
return ret;
}
sprintf函数实现
sprintf只需要进行简单的改动即可
int sprintf(char *out, const char *fmt, ...) {
va_list args;
int i;
va_start(args, fmt);
i = vsprintf(out, fmt, args);
va_end(args);
return i;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)