本文已参与「新人创作礼」活动.一起开启掘金创作之路。
随着对printf函数的深入理解后,发现,网上许多版本的实现都无法针对大整数和负数做很好的处理,而这个版本针对了负数以及最大的整数和最小的整数都能正常输出。
#include <stdio.h>
#include <stdarg.h>
#include <inttypes.h>
#include <math.h>
int myPrintf(const char* frm, ...) {
int cnt = 0, y, z; va_list arg; va_start(arg, frm);
for (int i = 0; frm[i]; ++i)
switch (frm[i]) {
case '%': switch (frm[++i]) {
case '%': putchar(frm[i]); ++cnt; break;
case 'o': { unsigned int t = va_arg(arg, unsigned int); y = 0;
char s[0xb];
do {
s[y++] = t % 8 + 0x30; t /= 8; ++cnt;
} while (t);
while (y)putchar(s[--y]);
} break;
case 'x': { unsigned int t = va_arg(arg, unsigned int); y = 0;
char s[0xb];
do {
z = t % 0x10; s[y++] = z > 9 ? z + 0x57 : z + 0x30; t /= 0x10; ++cnt;
} while (t);
while (y)putchar(s[--y]);
} break;
case 'p': { unsigned long t = va_arg(arg, unsigned long); y = 0; putchar('0');
char s[0xb];
#ifdef _WIN32
do {
z = t % 0x10; s[y++] = z > 9 ? z + 0x37 : z + 0x30; t /= 0x10; ++cnt;
} while (t);
#else
putchar('x');
do {
z = t % 0x10; s[y++] = z > 9 ? z + 0x57 : z + 0x30; t /= 0x10; ++cnt;
} while (t);
#endif
if (y < 7)s[y++] = 0x30; while (y)putchar(s[--y]);
} break;
case 'c': { int t = va_arg(arg, int); putchar(t > 128 || t < -1 ? 63 : t); } break;
case 'd': {
int t = va_arg(arg, int); y = 0; if (t < 0)putchar('-'), ++cnt;
char s[0xb];
do {
s[y++] = t > 0 ? t % 10 + 0x30 : -(t % 10) + 0x30; t /= 10; ++cnt;
} while (t);
while (y)putchar(s[--y]);
} break;
case 's': {
const char* str = va_arg(arg, const char*);
for (int i = 0; str[i]; i++) {
putchar(str[i]), ++cnt;
}
} break;
case 'l': switch (frm[++i]) {
case 'l':if (frm[++i] == 'd') {
long long t = va_arg(arg, long long); y = 0; if (t < 0)putchar('-'), ++cnt;
char s[0x13];
do {
s[y++] = t > 0 ? t % 10 + 0x30 : -(t % 10) + 0x30; t /= 10; ++cnt;
} while (t);
while (y)putchar(s[--y]);
} else continue; break;
case 'd': {
long t = va_arg(arg, long); y = 0; if (t < 0)putchar('-'), ++cnt;
char s[0xb];
do {
s[y++] = t > 0 ? t % 10 + 0x30 : -(t % 10) + 0x30; t /= 10; ++cnt;
} while (t);
while (y)putchar(s[--y]);
} break;
case 'f': {
double l = va_arg(arg, double); long long t = (long long)l; l -= t;
y = z = 0; if (t < 0)putchar('-'), l = -l, ++cnt;
char s[26];
do {
s[y++] = t > 0 ? t % 10 + 0x30 : -(t % 10) + 0x30; t /= 10; ++cnt;
} while (t);
while (y)putchar(s[--y]); s[y++] = 0x2e; t = 10;
do {
s[y++] = (int)((l + 1e-6) * t) % 10 + 0x30; t *= 10; l -= (int)l; ++cnt;
} while (t < 1000001);
while (y > z)putchar(s[z++]);
} break;
} break;
} break;
default:putchar(frm[i]), ++cnt; break;
}va_end(arg);
return cnt;
}
int main() {
myPrintf("INT32_MAX = %d\n", INT32_MAX);
myPrintf("INT32_MIN = %d\n", INT32_MIN);
myPrintf("INT32_MAX = %x\n", INT32_MAX);
myPrintf("char = %c\n", -1);
myPrintf("char = %lf\n", -801.235324);
myPrintf("INT64_MAX = %lld\n", INT64_MAX);
myPrintf("INT64_MIN = %lld\n", INT64_MIN);
return 0;
}
输出
INT32_MAX = 2147483647
INT32_MIN = -2147483648
INT32_MAX = 7fffffff
char =
char = -801.235324
INT64_MAX = 9223372036854775807
INT64_MIN = -9223372036854775808