⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 printf.c

📁 一个mips虚拟机非常好代码,使用C++来编写的,希望大家多学学,
💻 C
字号:
#include "stdarg.h"#include "stdlib.h"void printf(const char* templ, ...);void vprintf(const char* templ, va_list ap);static void put_oct(unsigned long x, int padding, int width, int nice);static void put_dec(unsigned long x, int padding, int width,		    int is_signed, int sign);static void put_hex(unsigned long x, int padding, int width, int nice,		    int hex_case);static void put_chr(int c, int width, int nice);static void put_str(const char* str, int width, int nice);/*	printf(template, ...)	vprintf(template, ap)	--------------------------------------------------------------	printf() is  a simplified printf-like function  that writes up	the output string to the console using putchar().	The following  formatting fields  are recognised and  have the	usual  meaning:  %%, %c,  %d,  %i, %o,  %s,  %u,  %x, and  %X.	Further,  the "l"  option may  be inserted  before  the format	characters "d",  "i", "o", "u",  "x" and "X" to  indicate that	the corresponding  argument is an  long or unsigned  long.  If	"l"  is ommited,  the argument  is  interpreted as  an int  or	unsigned int. Also, the "#"  flag may be inserted after "%" is	the %c, %s, %o, %x and %X fields.  In the %o, %x and %X field,	it  has  the  usual effect  of  printing  the  number as  a  C	constant.   In a  %c  field, it  indicates that  non-printable	characters should be converted to the ^X (if possible) or \xxx	escape sequence (this includes \t  and \v.)  In a %s field, it	escapes all  non-printable characters except  for spaces which	are compressed to  a single space.  The '0', '+',  '-' and ' '	flags  and the  field  width specifier  may  also preceed  the	format  character.  Note  that  the %p  format specifier,  the	precision field, the '*' syntax  and the XPG4 '`' flag and '$'	syntax are not supported.	All that  said, printf() wouldn't  be worth the bother  if the	code  had  to be  written  from  scratch  ;) It's  been  taken	directly from libsulima.*/void printf(const char* templ, ...){    va_list ap;    va_start(ap, templ);    vprintf(templ, ap);    va_end(ap);}void vprintf(const char* templ, va_list ap){    const char* p;    unsigned long x;        /* Process the template. */    for (p = templ; *p != '\0'; ++p) {	if (*p != '%' || *++p == '%')	    putchar(*p);	else {	    int left = 0;	/* the - flag */	    int nice = 0;	/* the # flag */	    int padding = ' ';	/* the 0 flag */	    int sign = 0;	/* the + and ' ' flags */	    int width = 0;	/* the - flag and the field width */	    int lflag;		/* the l modifier */	    int digit;	    /* Process a format specifier flags. */	    for (;;) {		int flag =* p++;		if (flag == '-')		    left = 1;		else if (flag == '+')		    sign = '+';		else if (flag == ' ')		    sign = (sign != '\0') ? sign : ' ';		else if (flag == '#')		    nice = 1;		else if (flag == '0')		    padding = '0';		else {		    --p;		    break;		}	    }	    /* Process the field width. */	    digit = *p++;	    while (digit >= '0' && digit <= '9') {		width = width * 10 + digit - '0';		digit = *p++;	    }	    --p;	    if (left)		width = -width;	    /* Process the "l" format modifier. */	    if (*p != 'l')		lflag = 0;	    else {		lflag = 1;		++p;	    }	    /* Process the format specifier. */	    switch (*p) {	    case 'c':		put_chr(va_arg(ap, int), width, nice);		break;	    case 'd':	    case 'i':		x = (lflag) ? va_arg(ap, long) : (long)va_arg(ap, int);		put_dec(x, padding, width, 1, sign);		break;	    case 'o':		x = (lflag) ? va_arg(ap, long) : (long)va_arg(ap, int);		put_oct(x, padding, width, nice);		break;	    case 's':		put_str(va_arg(ap, const char*), width, nice);		break;	    case 'u':		x = (lflag) ? va_arg(ap, long) : (long)va_arg(ap, int);		put_dec(x, padding, width, 0, sign);		break;	    case 'x':		x = (lflag) ? va_arg(ap, long) : (long)va_arg(ap, int);		put_hex(x, padding, width, nice, 'a');		break;	    case 'X':		x = (lflag) ? va_arg(ap, long) : (long)va_arg(ap, int);		put_hex(x, padding, width, nice, 'A');		break;	    case 'p':		x = va_arg(ap, long);		put_str("0x", 0, 0);		put_hex(x, '0', 16, 0, 'A');		break;	    }	}    }}/*	put_oct(x, padding, width, nice)	put_dec(x, padding, width, is_signed, sign)	put_hex(x, padding, width, nice, hex_case)	--------------------------------------------------------------	Echo an octal, decimal or hexadecimal number.	"hex_case" is either 'a' or 'A'.	"nice" is 1 if the '#' flag is specified.	"padding" is the left-padding character.	"sign" is set to the prevailing '+' or ' ' flag, or is 0.	"is_signed" is 1 for signed conversions	"width" is the field width, negated for the '-' flag.*/void put_oct(    unsigned long x,    int padding,    int width,    int nice){    int flush_left;    char buffer[(sizeof(x) * 8 + 2) / 3 + 2];    char* p = buffer;    /* Don't print the initial '0' in front of a 0. */    if (x == 0)	nice = 0;    /* Align left if width is negative. */    if (width >= 0)	flush_left = 0;    else {	flush_left = 1;	width = -width;    }    /* Generate the digits (least-signficant one first.) */    do {	*p++ = (x & 7) + '0';    } while (x >>= 3);    /* Print the 'nice' zero. */    if (nice)	*p++ = '0';    /* Adjust the width by the number of already-generated characters. */    width -= (p - buffer);    /* Print the left padding. */    if (!flush_left)	for (; width > 0; --width)	    putchar(padding);    /* Print the generated digits in a reversed order. */    do {	putchar(*--p);    } while (p > buffer);    /* Print the right padding. */    for (; width > 0; --width)	putchar(' ');}void put_dec(    unsigned long x,    int padding,    int width,    int is_signed,    int sign){    /* The buffer size uses log10(2) == 0.30103. */    char buffer[sizeof(x) * 8 * 30103L / 100000L + 2];    int flush_left;    char* p = buffer;    /* For signed conversions, grab the absolute value of the number. */    if (!is_signed)	sign = 0;    else {	/* Process the sign and distard it from x. */	if ((long)x < 0) {	    sign = '-';	    x = -x;	}    }    /* Align left if width is negative. */    if (width >= 0)	flush_left = 0;    else {	flush_left = 1;	width = -width;    }    /* Generate the digits (least-signficant one first.) */    do {	*p++ = (x % 10) + '0';	x /= 10;    } while (x);    /* Print the sign character. */    if (sign)	*p++ = sign;    /* Adjust the width by the number of already-generated characters. */    width -= (p - buffer);    /* Print the left padding. */    if (!flush_left)	for (; width > 0; --width)	    putchar(padding);    /* Print the generated digits in a reversed order. */    do {	putchar(*--p);    } while (p > buffer);    /* Print the right padding. */    for (; width > 0; --width)	putchar(' ');}void put_hex(    unsigned long x,    int padding,    int width,    int nice,    int hex_case){    int flush_left;    char buffer[sizeof(x) * 8 / 4 + 2];    char* p = buffer;    /* Align left if width is negative. */    if (width >= 0)	flush_left = 0;    else {	flush_left = 1;	width = -width;    }    /* Generate the digits (least-signficant one first.) */    do {	int digit = x & 15;	*p++ = digit + ((digit < 10) ? '0' : hex_case - 10);    } while (x >>= 4);    /* Print the 'nice' 0x. */    if (nice) {	*p++ = 'x' - 'a' + hex_case;	*p++ = '0';    }    /* Adjust the width by the number of already-generated characters. */    width -= (p - buffer);    /* Print the left padding. */    if (!flush_left) {	for (; width > 0; --width)	    putchar(padding);    }    /* Print the generated digits in a reversed order. */    do {	putchar(*--p);    } while (p > buffer);    /* Print the right padding. */    for (; width > 0; --width)	putchar(' ');}/*	put_chr(c, width, nice)	put_str(s, width, nice)	--------------------------------------------------------------	Print a character or a string.*/void put_chr(    int c,    int width,    int nice){    unsigned char x = c;    if (!nice || (x >= ' ' && x < '\177')) {	while (width > 1) {	    /* Pad on the left. */	    putchar(' ');	    --width;	}	putchar(x);	while (width < -1) {	    /* Pad on the right. */	    putchar(' ');	    ++width;	}    }    else if (x > '\177') {	while (width > 4) {	    /* Pad on the left. */	    putchar(' ');	    --width;	}	putchar('\\');	putchar((x >> 6) & 7);	putchar((x >> 3) & 7);	putchar((x >> 0) & 7);	while (width < -4) {	    /* Pad on the right. */	    putchar(' ');	    ++width;	}    }    else {	while (width > 2) {	    /* Pad on the left. */	    putchar(' ');	    --width;	}	putchar('^');	putchar((x + '@') & 127);	width -= 2;	while (width < -2) {	    /* Pad on the right. */	    putchar(' ');	    ++width;	}    }}void put_str(    const char* str,    int width,    int nice){    const char* p;    int length = 0;    if (width) {	if (!nice)	    length = strlen(str);	else {	    for (p = str; *p; ++p) {		unsigned char x = *p;		if ((x >= ' ' && x < '\177') || isspace(x))		    ++length;		else if (x > '\177')		    length += 4;		else		    length += 2;	    }	}    }    while (width > length) {	/* Pad on the left. */	putchar(' ');	--width;    }    if (!nice) {	while (*str)	    putchar(*str++);    }    else {	while (*str) {	    unsigned char x = *str++;	    if ((x >= ' ' && x < '\177') || isspace(x))		putchar(x);	    else if (x > '\177') {		putchar('\\');		putchar((x >> 6) & 7);		putchar((x >> 3) & 7);		putchar((x >> 0) & 7);	    }	    else {		putchar('^');		putchar((x + '@') & 127);	    }	}    }    while (width < -length) {	/* Pad on the right. */	putchar(' ');	++width;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -