The project involves rewriting the original printf function from stdio.h in C.
If you are unfamiliar with printf(), see this simple introduction: https://www.tutorialspoint.com/c_standard_library/c_function_printf.htm
An essential part of my implementation of ft_printf() is the va_start(), va_arg() and va_end() macros
from the stdarg.h library. They are used for handling variable argument lists in functions.
va_start()initializes ava_listvariable to be used withva_argandva_end. It must be called before accessing the variable arguments.va_arg()retrieves the next argument in the list. The type of the expected argument needs to be specified.va_end()cleans up the va_list when you are done with it. It should be called before the function returns.
The ft_printf() function is declared like this:
int ft_printf(const char *, ...);const char *-- A string containing characters and/or type identifiers....-- An undefined amount of arguments, with undefined types.
The return value for ft_printf() is an int, indicating how many characters were printed.
It returns -1 upon error.
%cPrints a single character.%sPrints a string (as defined by the common C convention).%pThe void * pointer argument has to be printed in hexadecimal format.%dPrints a decimal (base 10) number.%iPrints an integer in base 10.%uPrints an unsigned decimal (base 10) number.%xPrints a number in hexadecimal (base 16) lowercase format.%XPrints a number in hexadecimal (base 16) uppercase format.%%Prints a percent sign.
The const char * is a string that can contain both text and type identifiers, like "%s", "%p", etc.
By using the function va_start(), the type identifiers in const char * gets connected to the data ..., which is stored in a va_list.
ft_printf("%i", 42);In this example:
const char *is"%i"...is42.- What will be printed on the standard output:
42.
The function va_arg() is used to iterate through the type identifiers and their respective data.
In ft_printf() -> whenever a type identifier is found in const char *, it gets connected to the next argument in ...
ft_printf("Hello, world! My name is %s, and I am %i years old.\n", "Bob", 40);In this example:
const char *is"Hello, world! My name is %s, and I am %i years old.\n"....is"Bob"and40.%sexpands to"Bob", and%iexpands to40.- What will be printed on the standard output:
"Hello, world! My name is Bob, and I am 40 years old.".
When const char * has reached the '\0', meaning it has reached its end, va_end() is called to clean up the va_list.
- The
ft_printf.cfile containing theft_printf()function, and the remaining*.cfiles containing all the printing functions for the different types. - A
Makefile. - A header file.
To get started, first clone the repository. This command will clone the repo, and move you to the right directory:
git clone https://github.com/busedame/ft_printf/ ft_printf && cd ft_printf- Compile the library:
Run the following command to compile the library:This simply compiles the library, but does not make an executable.make
- Test the function:
- Either use the existing main function in
ft_printf.c(needs to be commented out), or add amain.cfile with a new main function. - Compile using this command:
cc *.c -o ft_printf- Run using this command:
./ft_printf
- Either use the existing main function in
Ensure that you have both your main project and the ft_printf library in the same directory or organized in separate directories. You will need the path to your ft_printf directory to link it in the Makefile.
-
In the header file: Include
ft_printf.h -
In the Makefile:
-
Path to the ft_printf project:
FT_PRINTF_PATH = <path_to_ft_printf_directory> -
Link the libftprintf.a library:
FT_PRINTF = $(FT_PRINTF_PATH)/libftprintf.a LIBS = -L$(FT_PRINTF_PATH) -lft
-
Compile the project and link with ft_printf:
$(NAME): $(OBJ) $(FT_PRINTF) $(CC) $(CFLAGS) $(OBJ) -o $(NAME) $(LIBS)
-
Ensure that ft_printf is compiled during the build process:
$(FT_PRINTF): $(MAKE) -C $(FT_PRINTF_PATH) -
Clean up object files:
clean: rm -f $(OBJ) $(MAKE) -C $(FT_PRINTF_PATH) clean -
Clean up everything (object files, executables, and libftprintf.a):
fclean: clean rm -f $(NAME) $(MAKE) -C $(FT_PRINTF_PATH) fclean
-
Example of Makefile:
CC = cc
CFLAGS = -Wall -Wextra -Werror
OPTIONS = -c
# Path to the ft_printf project
FT_PRINTF_PATH = ./ft_printf
# Source files for your project
SRC = main.c
# Object files for your project
OBJ = $(SRC:.c=.o)
# Final executable name
NAME = my_project
# Link the libftprintf.a library
FT_PRINTF = $(FT_PRINTF_PATH)/libftprintf.a
LIBS = -L$(FT_PRINTF_PATH) -lftprintf
# All: Compile both ft_printf and your project
all: $(NAME)
$(NAME): $(OBJ) $(FT_PRINTF)
$(CC) $(CFLAGS) $(OBJ) -o $(NAME) $(LIBS)
# Compile .c files to .o object files
%.o: %.c
$(CC) $(CFLAGS) $(OPTIONS) $< -o $@
# Ensure that ft_printf is compiled during the build process
$(FT_PRINTF):
$(MAKE) -C $(FT_PRINTF_PATH)
# Clean up object files
clean:
rm -f $(OBJ)
$(MAKE) -C $(FT_PRINTF_PATH) clean
# Clean up everything (object files, executables, and libftprintf.a)
fclean: clean
rm -f $(NAME)
$(MAKE) -C $(FT_PRINTF_PATH) fclean
# Rebuild everything (clean and then compile both ft_printf and your project)
re: fclean all
.PHONY: all clean fclean reThis project was finished Dec 8th 2023.