One specifier remains: %%. Then the tester confirms that all nine
specifiers work together.
%%
%% prints a literal % character. No argument is consumed from the
variadic list — va_arg is not called:
if (spec == '%')
return (tci_putchar_fd('%', 1)); /* no va_arg: no argument consumed */This is already in the dispatcher from page 03. If you added it then, nothing needs to change here.
%% exists because % is the delimiter of the specifier syntax — the
only way to print a literal % inside a format string is to escape it.
printf("100%% done\n") prints 100% done. printf("%d%%\n", score)
prints the integer followed by %.
The argument count matters: va_arg is a cursor, and each call
advances it by one argument. A spurious call inside %% would corrupt
the position for every specifier that followed — silently, since format
strings are not validated at compile time.
Complete tci_printf.c
At this point tci_printf.c should contain, in order:
- Includes:
"libtci.h",<stdarg.h>,<unistd.h>,<stdint.h> - Forward declarations for all static helpers
tci_putchar_fdtci_putstr_fdtci_putnbr_basetci_print_signedtci_print_unsignedtci_print_ptrdispatchtci_printf
Run make re. Thirty object files, no warnings.
Run the tester
make re
bash test.shThe tester compiles a small driver that calls both tci_printf and libc
printf with the same format strings and captures the outputs. Any
divergence in output or return value is reported as a failure.
Common failure points at this stage:
- Return value wrong: a helper returns 0 when it should return a byte
count. Check every path through
tci_putstr_fdandtci_putnbr_base. Thewritecall returns the number of bytes written — return that value, not a literal constant. %pwith NULL: returning 0 instead of writing(nil). Check the NULL branch intci_print_ptr.- INT_MIN:
%dwith −2147483648. If this row fails, theint→longpromotion before negation is missing intci_print_signed. - Trailing
%: a%at the very end of the format string with nothing after it. The format loop must handlefmt[i + 1] == '\0'and write the%as a literal character.
Fix any failures before proceeding to the flags page.