printf()のような関数

作成日:2014/02/06
最終更新日:2020/07/05

printf()のような関数

作成日:2014/02/06
最終更新日:2020/07/05

printf()のような関数

putc()やputs()だけでは文字列を出力するのが辛いので、printf()っぽい関数を書いてみました。 問題はありますが、判っていて使う分には良さそうです。

ソース1. printf()のような関数
typedef void* va_list;

#define va_size(type) (((sizeof(type) + sizeof(unsigned long) - 1) / sizeof(unsigned long)) * sizeof(unsigned long))
#define va_start(ap, last)        ((ap) = (va_list)&(last) + va_size(last))
#define va_arg(ap, type) (*(type *)((ap) += va_size(type), (ap) - va_size(type)))
#define va_end(ap)
#define parce_num(p, b, num, base) 					\
	do {			     					\
		unsigned long tmpnum;					\
		char *ptmp;						\
		p = b + sizeof(b) - 1;					\
		*(p--) = '\0';						\
		ptmp = p;						\
		tmpnum = num;						\
		while (tmpnum) {					\
			*(p--) = "0123456789abcdef"[tmpnum % base];	\
			tmpnum /= base;					\
		}							\
		if (p == ptmp) {					\
			*p = '0';					\
		} else {						\
			p++;						\
		}							\
	} while (0)

int
vsnprintf(char *buf, int n, const char *format, va_list args)
{
        int num;
        int i, j, k;
        char *pnum, tmp[16];

        for (i = j = 0; j < n && format[i] != '\0';) {
                if (format[i] != '%') {
                        buf[j++] = format[i++];
                        continue;
                }
                i++;
                switch(format[i++]) {
                case 'c':
                        num = va_arg(args, int);
                        buf[j++] = (char)(num & 0x0ff);
                        break;
                case 'u':
                        num = va_arg(args, int);
			parce_num(pnum, tmp, num, 10);
			goto output_buf;
                case 'x':
                        num = va_arg(args, int);
			parce_num(pnum, tmp, num, 16);
			goto output_buf;
                case 's':
                        pnum = va_arg(args, char *);
		output_buf:
                        for (k = 0; pnum[k] != '\0';) {
                                buf[j++] = pnum[k++];
                        }
                        break;
                default:
                        break;
                }
        }
        buf[j] = '\0';
        return j;
}

void
printf(const char *format, ...) {
        va_list args;
	char buf[192];

        va_start(args, format);
        vsnprintf(buf, 192, format, args);
        va_end(args);

	puts(buf);
}