<aside> 🖊️ As coisas que precisei aprender para entender e construir o projeto printf. Fique à vontade para comentar e contribuir!

</aside>

palavras-chave: função variádica, string de formatação, token, parsing

<aside> ⚠️ Sabemos que não é todo mundo que tem o privilégio de poder dedicar 100% do seu tempo integralmente para a 42. Estes guias surgiram com o objetivo de agilizar o processo de descobrir quais os conhecimentos necessários para conseguir resolver o problema proposto pelo projeto, economizando tempo valioso pra codar. Evitei ao máximo dar soluções prontas — porque desenhar, implementar, testar e construir a solução também faz parte do seu aprendizado na 42. Mesmo assim, esta página pode conter alguns spoilers de implementação, por isso, prossiga com precaução!

</aside>

Introdução

Você provavelmente já usou a função printf() (que precisa do #include <stdio.h>) alguma vez, nem que seja para debugar os seus códigos. Essa é aquela função que precisa de pelo menos um parâmetro que seja um string, e que escreve coisas no terminal quando o programa é executado. Essa string inicial pode conter coisas como %i ou %s, que no final das contas serão substituídos pelo valor do que for passado nos parâmetros seguintes da função. Algo mais ou menos assim:

#include <stdio.h>

int main(void)
{
	int idade = 29;
	char *nome = "Rods";

	printf("Me chamo %s e tenho %i anos!\\n", nome, idade);
	return (0)
}

(Ao ser executado, no terminal deve aparecer isso: Me chamo Rods e tenho 29 anos!)

Este projeto é tão simplesmente para você criar a sua própria versão da função printf(), e a partir de então vc poderá adicioná-la na sua libft e a utilizar sempre que precisar!

Entendo que o principal objetivo desse projeto é aprendermos como funcionam funções variádicas (ou seja, funções que recebem uma quantidade variável/indefinida de argumentos de entrada). Para mim, foi também uma oportunidade de aprofundar mais no uso do Makefile, e de revisitar todo o processo de compilação de códigos, que vai desde escrever os códigos fonte em .c, transformá-los em códigos objeto (arquivos .o), gerar a biblioteca estática .a, até gerar o arquivo binário final ****que é o que executamos pelo terminal usando o comando ./. Coisas que estivemos utilizando desde a Libft, mas que só fizeram sentido mesmo pra mim neste projeto.

Vale notar que o que a função printf faz, basicamente, é ler uma string de caracteres, e interpretá-la! Isso significa que a função tem uma inteligência a mais, para além de somente ler caracter por caracter, ela é capaz de entender em que pontos dessa string ela precisará fazer uma pausa, ler um outro argumento, escrever esse argumento no terminal de um jeito específico, e então continuar de onde parou a leitura da string original de formatação. A chave para essa análise “inteligente” da string, no caso da printf, é um símbolo: o %. Não porque um sinal de porcentagem é particularmente mágico ou especial, mas porque no passado, elegeram esse caracter como um caracter especial com uma função especial dentro de uma string de formatação*.* O termo técnico para esse símbolo é token. E o termo técnico para esse processo de interpretar inteligentemente uma sequência de caracteres a partir de tokens, símbolos especiais, é parsing. Neste projeto você escreverá o seu primeiríssimo parser 😊

É um senso comum que a parte mandatória desse projeto é muito simples de ser implementada, já a parte bonus tem um grau bem maior de complexidade. Eu implementei uma partezinha do bonus (a flag #) apenas, porque precisava entegar o projeto rápido, mas no meu Github dá pra ver que a estrutura básica que criei pra implementar essa flag (o sctruct flags e a função capture_flags()) já dá conta de acomodar as outras partes do bonus.

Boa sorte! 🍀

Para entender antes de começar

Lidando com argumentos variáveis

As funções permitidas para fazer esse projeto são as ferramentas que precisamos para trabalhar com funções variádicas. Assim como nas funções (não variádicas) que viemos construindo — em que nós definimos exatamente quantos e quais serão os parâmetros de entrada da função (declaração), e esses parâmetros são inicializados em no momento em que a função é chamada (inicialização), e quando chega ao final da nossa elas são automaticamente liberadas da memória (e se for o caso de usar o malloc, precisamos dar free para liberá-las) —, assim é com os argumentos das funções variádicas. Eles serão todos guardados em uma lista (do tipo va_list), essa lista precisa ser inicializada (va_start) e finalizada (va_end), e para navegar pelos argumentos da função, precisamos sempre informar qual é o tipo do argumento a ser recuperado da lista (int, long int, void *, etc.).

Dá uma lida na documentação dessas funções e também em algum código que implementa essas funções (lá embaixo), e depois, pra aquecer os motores, sugiro seguir esse checklist para se familiarizar com argumentos variáveis: