Skip to content

librity/ft_printf

Repository files navigation

42 São Paulo - ft_printf

42 São Paulo License Code size in bytes Lines of code Top language Last commit

Norminette v3 Build FT_PRINTF_TEST 42TESTERS-PRINTF PFT_2019

A partial implementation of printf in pure C.


📜 Table of Contents

🧐 About

This is the third project I did at 42 São Paulo: an implementation of the famous printf function from scratch.

It was a big project and my first milestone at 42: I felt properly challenged and out of my comfort zone throughout most of it. It taught me how to organize code effectively in C, and to separate responsibilities without resorting to Classes and Objects (which is what I'm used to).

I managed to do it without using a single malloc or free, but with pointers to stack structs that I pass around to each handler. There's an isolated struct, handler, and formatter for each conversion.

The only thing that conversion "modules" share are the flag parser and pure utility functions. I did it this way so I didn't need to worry about breaking the formatting of other conversions as I tinkered with the rules.

This was a really good decision since there are many formatting exceptions and flag combinations that vary from conversion to conversion, and it sure saved me some headaches.

🏁 Getting Started

⚙️ Prerequisites

All you need is a shell and a C compiler like gcc or clang.

🖥️ Installing

To compile the entire thing just clone the repo and run make:

$ git clone https://github.com/librity/ft_printf.git
$ cd ft_printf
$ make

This will generate a ft_printf.a archive, which you can compile with any of the example files:

$ cp examples/example_1.c example.c
$ gcc -g -I ./includes example.c ft_printf.a
$ ./a.out

🎈 Usage

You can call ft_printf as you would call your system's printf function:

ft_printf("'%-10s'\n", "Hello, world!");

It handles most conversions:

  • Percent char: %%
  • Unsigned char: %c
  • Signed decimal int: %i or %d
  • Null-terminated char *: %s
  • Unsigned decimal int: %u
  • Uppercase hexadecimal unsigned int: %X
  • Lowercase hexadecimal unsigned int: %x
  • Pointer/hexadecimal memory address unsigned long: %p
  • float and double: %f
  • long double: %Lf

And also handles almost all the flags:

  • Zero padding 0
  • Let-justified -
  • Minimum field width
  • Precision .
  • Wildcard arguments *

Conversions and flags must respect the format: %[0 and/or -][width][.number]conversion

Unfortunately there's no rigorous documentation or standard for this function, and a lot of its behavior is implementation-specific. There are many corner-cases that need to be ironed out by trial and error. Since this is a 42 project, I replicated the behavior of Apple's printf.

This is best source I could find on the project, and should be enough to get you started.

✅ Testers

Github Actions by @wblech

🐙 Github Actions

Norminette v3 github action based on @AdrianWR's implementation.

🛸 42 São Paulo

Part of the larger 42 Network, 42 São Paulo is a software engineering school that offers a healthy alternative to traditional education:

  • It doesn't have any teachers and classes.
  • Students learn by cooperating and correcting each other's work (peer-to-peer learning).
  • Its focus is as much on social skills as it is on technical skills.
  • It's completely free to anyone that passes its selection process - The Piscine

It's an amazing school, and I'm grateful for the opportunity.

Releases

No releases published

Packages

No packages published