The versatility of The printf function in C represents a great exercise in programming. This project is of MODERATE difficulty. It will enable you to discover variadic functions in C. The key to a successful ft_printf is a well-structured and good extensible code.
🚫 ft_printf("%s\n", "When you light a candle, you also cast a shadow.");
🚫 ft_printf("%s\n", "What hurts you, blesses you. Darkness is your candle.");
🚫 ft_printf("%s\n", "Into the darkness they go, the wise and the lovely.");
A small description of the required conversions :
% | Type |
---|---|
%c | Print a single character. |
%s | Print a string of characters. |
%p | The void * pointer argument is printed in hexadecimal. |
%d | Print a decimal (base 10) number. |
%i | Print an integer in base 10. |
%u | Print an unsigned decimal (base 10) number. |
%x | Print a number in hexadecimal (base 16, lowercase). |
%X | Hex integer (uppercase). |
%% | Just the %. |
Manage any combination of the following flags :
-0.
and minimum field width with all conversions.- Manage all the following flags:
# +
(yes, one of them is a space).
🚩 Flags 🚩 | ❓ |
---|---|
Num | (Number between % and the identifier) Minimum field width. |
- | Left justify. |
0 | Field padded with 0's instead of blanks. |
. | Precision. |
+ | Add a plus sign ('+') in the front of positive numeric conversions. |
' ' | Add a single space (' ') in the front of positive numeric conversions. |
# | Add the corresponding prefix in front of x, X and o conversions. |
This is how the embedded format tags are aligned :
Holder key | Prefix and justification flags * | Minimum Width * | Precision * | Conversion |
---|---|---|---|---|
% |
- , 0 , + , ... |
10 , 5 , ... |
. , .10 , .5 , ... |
c , d , i , s , ... |
For %d and %i, the precision is the minimum number of digits to print.
For %s, the precision is the maximum field width.
🔻 To be aware of :
- flag '0' is ignored when flag '-' is present.
- flag '0' is ignored when flag '.' is present (%d e %i).
- flag '0' results in undefined behavior with '%c', '%s' and '%p'.
- flag '.' results in undefined behavior with '%c' and '%p'.
🚧 Project Organization :
.
├── includes/
├── libft/
├── srcs/
├── Makefile
Step 1️⃣ :
- I created a format structure inside my headerfile and also made some basic util typdefs :
typedef struct s_fmt
{
const char *format;
va_list ap;
size_t i;
size_t counter;
} t_fmt;
- Also a placeholder structure to stock all the informations about every placeholder that printf manages :
typedef struct s_holder
{
int left_justify;
char *prefix;
char padding;
int width;
int precision;
char conversion;
char *argument;
size_t counter;
} t_holder;
Step 2️⃣ :
I created mandatory functions in my ft_printf.c file :
int ft_printf(const char *format, ...);
int ft_vprintf(const char *format, va_list ap);
DESCRIPTION :
The functions in the printf() family produce output according to a format
as described below. The functions printf() and vprintf() write output to
stdout, the standard output stream.
PARAMETERS :
#1. The string format in which the output will be printed.
#2. ... The variadic arguments passed to the format string's placeholders. In
the vprintf() function, the variadic argument are already passed as a
va_list type.
RETURN VALUES :
Upon successful return, these functions return the number of characters printed.
Step 3️⃣ :
I created functions responsible of initilizing both of my structures inside my ft_initializer.c file:
t_fmt *ft_initialize_fmt(const char *format, va_list ap);
t_holder *ft_initialize_holder(void);
DESCRIPTION :
Initializes the format struct with the string given and the va_list variable,
setting the initial values of both variables i and counter up to 0.
PARAMETERS :
#1. The string format in which the output will be printed.
#2. The variadic arguments list
RETURN VALUES :
The new, initialized variable struct format.
DESCRIPTION :
Initialize the holder struct that will retain the information of the
placeholders flags and conversions.
PARAMETERS :
NONE.
RETURN VALUES :
The new, initialized variable struct holder.
Step 4️⃣ :
I Created a function that will manage the format string, and unitializes the holder as well :
void ft_placeholder_manager(t_fmt *fmt);
DESCRIPTION :
The ft_placeholders_manager() function manages whatever comes after the '%' char in the
ft_printf() function. It calls the ft_initializer() function for the
format struct, as well as the ft_parsing() function that will eventually convert
the argument passed to the va_list into the holder struct. At the end, it
will print to the screen the converted string of the respective argument.
PARAMETERS :
#1. The t_format struct that holds information about the string to be formatted.
RETURN VALUES :
NONE.
Then i had to do some syntax analyzing (parsing) althrough the format string using the function ft_parsing() and its subfunctions "ft_flags_parser() ...".
void *ft_parsing(t_fmt *fmt, t_holder *holder);
DESCRIPTION :
The ft_parsing() function will take the format string from the index in which the
placeholder begins, and will attempt to analyze and organize its flags and
conversors into a struct of type t_holder, using other parsing subfunctions.
PARAMETERS :
#1. The t_format struct that holds information about the string to be formatted.
RETURN VALUES :
It returns the t_holder variable that holds all the information about that particular placeholder.