int printf(const char *cntrl_string, ...) {
int pos = 0, cnt_printed_chars = 0, i;
unsigned char *chptr;
va_list ap;
va_start(ap, cntrl_string); // 初始化變長參數列表
// ...
}
while (cntrl_string[pos]) {
if (cntrl_string[pos] == '%') {
++pos;
switch (cntrl_string[pos]) {
case 'c': putchar(va_arg(ap, unsigned char)); ++cnt_printed_chars; break;
case 's': chptr = va_arg(ap, unsigned char*);
while (chptr[i]) { putchar(chptr[i++]); ++cnt_printed_chars; } break;
case 'i': case 'd': cnt_printed_chars += printInt(va_arg(ap, int)); break;
case 'u': cnt_printed_chars += printUnsignedInt(va_arg(ap, unsigned int)); break;
case 'x': cnt_printed_chars += printHexa(va_arg(ap, unsigned int), 'x'); break;
case 'X': cnt_printed_chars += printHexa(va_arg(ap, unsigned int), 'X'); break;
case 'o': cnt_printed_chars += printOctal(va_arg(ap, unsigned int)); break;
case 'p': putchar('0'); putchar('x'); cnt_printed_chars+=2;
cnt_printed_chars += printHexa(va_arg(ap, unsigned int), 'x'); break;
case '#': ++pos; // 處理 #x, #X, #o 等替代格式
switch (cntrl_string[pos]) { /* 類似上述,加前綴 */ } break;
default: putchar(cntrl_string[pos]); ++cnt_printed_chars; // 未知格式直接輸出
}
} else {
putchar(cntrl_string[pos]); ++cnt_printed_chars; // 普通字元直接輸出
}
++pos;
}
va_end(ap);
return cnt_printed_chars;
putchar 與 printCharint putchar(int c) {
switch ((unsigned char)c) {
case '\n': newLine(); break;
case '\r': carriageReturn(); break;
case '\f': clearScreen(); break;
case '\t': for(int i=0;i<8;++i) printChar(32); break; // 8 spaces
case '\b': backspace(); break;
case '\a': beep(); break;
default: printChar(c);
}
return c;
}
void printChar(const byte ch) {
*(word*)(VIDEO + y*160 + x*2) = ch | (fill_color << 8); // 直接寫顯存 0xB8000
++x;
if (x >= WIDTH) newLine();
setVideoCursor(y, x);
}
VIDEO = 0xB8000 為文字模式顯存基址,每字元佔 2 位元組 (ASCII + 屬性/顏色)。
va_start/arg/end 機制,型別安全由程式設計師依格式字串保證。switch 分派,支援基本型別與 # 替代格式。printf 需解析 %[flags][width][.precision][length]specifier。printf (經由系統呼叫輸出)。printf 回傳值語意。%ld, %lld, %f, %p 等長度修飾與指標格式。vsnprintf 以支援緩衝區輸出與長度限制。