>how do i go about writing my own printf function
You first learn how to write a function that takes a variable number of arguments, then you learn how to convert various supported types into strings and write those strings using a lower level function, putchar as one possible option. Then you learn how to process the formatting flags so that your printf will handle more complex formatting than just type conversion. Here's a quick and dirty example, it can be made to be more compact and elegant with a little effort:
Code:
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
void fprint(const char *format, ...);
int
main(void)
{
fprint("|%12d|\n", 45);
fprint("|%012d|\n", 45);
fprint("|% 012d|\n", 45);
fprint("|%+12d|\n", 45);
fprint("|%+012d|\n", 45);
fprint("|%-12d|\n", 45);
fprint("|%- 12d|\n", 45);
fprint("|%-+12d|\n", 45);
fprint("|%12.4d|\n", 45);
fprint("|%-12.4d|\n\n", 45);
fprint("|%12d|\n", -45);
fprint("|%012d|\n", -45);
fprint("|% 012d|\n", -45);
fprint("|%+12d|\n", -45);
fprint("|%+012d|\n", -45);
fprint("|%-12d|\n", -45);
fprint("|%- 12d|\n", -45);
fprint("|%-+12d|\n", -45);
fprint("|%12.4d|\n", -45);
fprint("|%-12.4d|\n", -45);
return 0;
}
static int
length(
int value
)
{
int n = 0;
if (value == 0) {
return 1;
}
while (value) {
++n;
value /= 10;
}
return n;
}
static void
r_write_value(
int value,
int n
)
{
/* Assume positive value */
if (n) {
r_write_value(value / 10, n - 1);
if (value) {
putchar(value % 10 + '0');
}
else {
putchar('0');
}
}
}
static void
write_value(
int value,
int n
)
{
if (value == 0) {
putchar('0');
}
else {
r_write_value(value, n);
}
}
void
fprint(
const char *format,
...
)
{
va_list args;
const char *it;
int value;
int i;
va_start(args, format);
for (it = format; *it; it++) {
if (*it == '%') {
int left = 0; /* Left justify */
int plus = 0; /* Print sign */
int zero = 0; /* Zero padding */
int space = 0; /* Whitespace sign replacement */
int field_width = 0; /* Precision before decimal */
int precision = 0; /* Precision after decimal */
while (*(++it) != 'd') {
/* Specific flags */
switch (*it) {
case ' ': space = 1; break;
case '+': plus = 1; break;
case '0': zero = 1; break;
case '-': left = 1; break;
}
/* Precision */
if (isdigit(*it)) {
char *save;
field_width = (int)strtol(it, &save, 10);
it = save;
if (*it == '.') {
precision = (int)strtol(it + 1, &save, 10);
}
it = save;
break;
}
}
value = va_arg(args, int);
/* Print formatting */
if (!precision) {
precision = length(value);
}
field_width -= precision;
if (space || plus || value < 0) {
--field_width;
}
if (!left) {
if (value < 0) {
if (!zero) {
for (i = 0; i < field_width; i++) {
putchar(' ');
}
putchar('-');
}
else {
putchar('-');
for (i = 0; i < field_width; i++) {
putchar('0');
}
}
}
else {
if (space) {
putchar(' ');
}
if (!zero) {
for (i = 0; i < field_width; i++) {
putchar(' ');
}
if (plus) {
putchar('+');
}
}
else {
if (plus) {
putchar('+');
}
for (i = 0; i < field_width; i++) {
putchar('0');
}
}
}
write_value(abs(value), precision);
}
else {
if (value < 0) {
putchar('-');
}
else {
if (plus) {
putchar('+');
}
else if (space) {
putchar(' ');
}
}
write_value(abs(value), precision);
for (i = 0; i < field_width; i++) {
putchar(' ');
}
}
}
else {
putchar(*it);
}
}
va_end(args);
}
Also note that this only implements the %d flag, and even then it's not fully functional.
>so that i do not have to include stdio.h
That's not really a good reason to write your own printf. If you really don't want to include stdio.h you can declare a prototype for printf:
Code:
int printf(const char *format, ...);
int
main(void)
{
printf("Hello, world!\n");
return 0;
}
In the end, providing declarations is all stdio.h does for you. If you provide your own (correct!) prototype then the effect is the same.