Plan de Estudio — 7 días
La Norma — Reglas Críticas
Funciones
- Máximo 25 líneas por función
- Máximo 4 parámetros
- Máximo 5 variables por función
- Sin argumentos → prototipo con void
- El return va entre paréntesis:
return (val); - Máximo 5 funciones por archivo .c
Cosas Prohibidas
- for → usar while
- do...while
- switch / case
- goto
- Operador ternario ?
- VLAs (arrays de longitud variable)
- Asignaciones múltiples:
a = b = 0
Formato
- Indentación con tabulaciones (no espacios)
- Líneas máximo 80 columnas
- Una instrucción por línea
- Asterisco pegado al nombre:
char *str - Una declaración de variable por línea
- Declaraciones al inicio de la función
- Línea vacía entre declaraciones y código
Header 42 obligatorio
- Todos los .c y .h deben empezar con el header estándar de 42
- En vim: :Stdheader o F1
- En emacs: C-c C-h
- Ejecutar norminette con:
-R CheckForbiddenSourceHeader
Denominación
- Structs empiezan con s_
- Typedefs empiezan con t_
- Unions empiezan con u_
- Enums empiezan con e_
- Macros y defines en MAYÚSCULAS
Compilación
- Siempre:
cc -Wall -Wextra -Werror - 0 warnings permitidos
- Sin segfault, bus error, double free
- Comportamiento sin definir = puede ser evaluado como 0
/* Header 42 aquí arriba (obligatorio) */
int ft_strlen(char *str)
{
int i;
i = 0;
while (str[i])
i++;
return (i);
}
int⇥ft_strlen), el asterisco pegado al nombre (char *str), y el return con paréntesis.
C 00 — write, loops, ASCII
printf — usas write(1, &c, 1) para imprimir un carácter. Todo lo demás se construye a partir de ahí. Los caracteres son números: 'a' = 97, '0' = 48, 'z' = 122.
EX 00 ft_putchar ★☆☆☆ Básico ▼
Muestra el carácter c usando write. Es la función base de toda la Piscine.
- La función recibe un char c como parámetro.
- Llama a write(1, &c, 1) — primer parámetro = stdout (1), segundo = dirección del char, tercero = 1 byte.
- No devuelve nada (void).
#include <unistd.h>
void ft_putchar(char c)
{
write(1, &c, 1);
}
&c es la dirección de memoria de c. write necesita un puntero, no el valor directamente.
EX 01 ft_print_alphabet ★☆☆☆ Básico ▼
Imprime el alfabeto en minúsculas de 'a' a 'z' en una sola línea.
- Declara una variable char c e inicialízala a 'a' (= 97 en ASCII).
- Con un while, iterar mientras
c <= 'z'. - Dentro del loop: llama a ft_putchar(c) y luego c++.
void ft_print_alphabet(void)
{
char c;
c = 'a';
while (c <= 'z')
{
ft_putchar(c);
c++;
}
}
EX 02 ft_print_reverse_alphabet ★☆☆☆ Básico ▼
Imprime el alfabeto en minúsculas de 'z' a 'a'.
- Declara char c = 'z'.
- While loop mientras
c >= 'a'. - Imprime c, luego c--.
void ft_print_reverse_alphabet(void)
{
char c;
c = 'z';
while (c >= 'a')
{
ft_putchar(c);
c--;
}
}
EX 03 ft_print_numbers ★☆☆☆ Básico ▼
Imprime todos los dígitos del 0 al 9 en una sola línea.
void ft_print_numbers(void)
{
char c;
c = '0';
while (c <= '9')
{
ft_putchar(c);
c++;
}
}
EX 04 ft_is_negative ★★☆☆ Medio ▼
Muestra 'N' si n es negativo, 'P' si es positivo o cero.
?) — está prohibido por la Norma. Usa if / else.
void ft_is_negative(int n)
{
if (n < 0)
ft_putchar('N');
else
ft_putchar('P');
}
EX 05 ft_print_comb ★★★☆ Difícil — suele caer en examen ▼
Imprime todas las combinaciones de 3 dígitos distintos en orden creciente, separadas por , . Resultado esperado: 012, 013, ..., 789
- Necesitas 3 contadores: a, b, c (chars de '0' a '9').
- a va de '0' a '7' (si a='8', no hay espacio para b y c distintos y mayores).
- b va de a+1 a '8'.
- c va de b+1 a '9'.
- Imprime a, b, c. Si no es la última combinación (789), imprime
,después.
void ft_print_comb(void)
{
char a;
char b;
char c;
a = '0';
while (a <= '7')
{
b = a + 1;
while (b <= '8')
{
c = b + 1;
while (c <= '9')
{
ft_putchar(a);
ft_putchar(b);
ft_putchar(c);
if (!(a == '7' && b == '8' && c == '9'))
{
ft_putchar(',');
ft_putchar(' ');
}
c++;
}
b++;
}
a++;
}
}
!(a == '7' && b == '8' && c == '9') evita imprimir la coma después del último elemento (789).
EX 07 ft_putnbr ★★★☆ Difícil — clásico de examen ▼
Muestra el entero nb. Debe funcionar para todos los valores de int, incluyendo negativos y INT_MIN (-2147483648).
- Caso especial: si
nb == -2147483648, imprímelo directamente (no cabe en int positivo). - Si nb es negativo, imprime '-' y niega nb.
- Si nb tiene más de un dígito (nb >= 10), llama a ft_putnbr recursivamente con nb/10.
- Imprime el último dígito:
ft_putchar('0' + nb % 10).
void ft_putnbr(int nb)
{
if (nb == -2147483648)
{
ft_putchar('-');
ft_putchar('2');
ft_putnbr(147483648);
return ;
}
if (nb < 0)
{
ft_putchar('-');
nb = -nb;
}
if (nb >= 10)
ft_putnbr(nb / 10);
ft_putchar('0' + nb % 10);
}
INT_MIN = -2147483648. Si haces nb = -nb directamente, hay overflow porque 2147483648 no cabe en un int positivo (máximo 2147483647).
C 01 — Punteros
*ptr accedes al valor que hay en esa dirección. Con &var obtienes la dirección de una variable. Modificar *ptr dentro de una función afecta al valor original.
int x = 10;
int *p = &x; // p guarda la dirección de x
*p = 42; // Modifica el valor en esa dirección
// Ahora x == 42
EX 00 ft_ft ★☆☆☆ Básico ▼
Recibe un puntero a int y le asigna el valor 42.
void ft_ft(int *nbr)
{
*nbr = 42;
}
*nbr = 42 desreferencia el puntero y modifica el valor almacenado en esa dirección. No modifica el puntero en sí.
EX 02 ft_swap ★★☆☆ Medio — clásico de examen ▼
Intercambia el contenido de dos enteros a través de sus punteros.
- Necesitas una variable temporal tmp para guardar uno de los valores.
- Guarda el valor de a en tmp:
tmp = *a. - Asigna el valor de b a a:
*a = *b. - Asigna tmp a b:
*b = tmp.
void ft_swap(int *a, int *b)
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
EX 03 ft_div_mod ★★☆☆ Medio ▼
Divide a entre b. Guarda el cociente en *div y el resto en *mod.
void ft_div_mod(int a, int b, int *div, int *mod)
{
*div = a / b;
*mod = a % b;
}
EX 05 ft_putstr ★★☆☆ Medio — muy frecuente en examen ▼
Muestra los caracteres de un string uno a uno. Un string en C es un array de chars terminado en '\0' (null terminator).
- Un string en C termina en el carácter '\0' (valor 0).
- Itera con while mientras
*str != '\0'(o simplemente*strporque '\0' es falso). - En cada iteración imprime
*stry avanza el puntero constr++.
void ft_putstr(char *str)
{
while (*str)
{
ft_putchar(*str);
str++;
}
}
EX 06 ft_strlen ★★☆☆ Básico-Medio ▼
Cuenta y devuelve el número de caracteres del string (sin contar el '\0').
int ft_strlen(char *str)
{
int i;
i = 0;
while (str[i])
i++;
return (i);
}
C 02 — Strings y manipulación de caracteres
char * — un puntero al primer carácter de una secuencia terminada en '\0'. Puedes acceder a cada char con str[i] o con *(str + i). Los rangos ASCII útiles: 'A'=65…'Z'=90, 'a'=97…'z'=122, '0'=48…'9'=57.
EX 00 ft_strcpy ★★☆☆ Básico-Medio ▼
Copia el string src en dest (incluyendo el '\0'). Devuelve dest.
- Itera con un índice i mientras
src[i] != '\0'. - Copia cada carácter:
dest[i] = src[i]. - Después del loop, añade el terminador:
dest[i] = '\0'. - Devuelve dest.
char *ft_strcpy(char *dest, char *src)
{
int i;
i = 0;
while (src[i])
{
dest[i] = src[i];
i++;
}
dest[i] = '\0';
return (dest);
}
EX 02 ft_str_is_alpha ★★☆☆ Medio ▼
Devuelve 1 si el string contiene solo letras (a-z, A-Z). Devuelve 0 si hay otro tipo. String vacío devuelve 1.
- Si
*str == '\0'(string vacío), devuelve 1 directamente. - Itera por cada carácter.
- Si el carácter no está entre 'a'-'z' NI entre 'A'-'Z', devuelve 0.
- Si termina el loop sin fallar, devuelve 1.
int ft_str_is_alpha(char *str)
{
int i;
i = 0;
while (str[i])
{
if (!((str[i] >= 'a' && str[i] <= 'z')
|| (str[i] >= 'A' && str[i] <= 'Z')))
return (0);
i++;
}
return (1);
}
EX 07 ft_strupcase ★★☆☆ Medio ▼
Pone cada letra en mayúscula. Devuelve str.
- La diferencia entre 'a' y 'A' es exactamente 32 en ASCII.
- Para convertir minúscula → mayúscula:
str[i] -= 32(ostr[i] = str[i] - 32). - Solo aplica si el carácter está entre 'a' y 'z'.
char *ft_strupcase(char *str)
{
int i;
i = 0;
while (str[i])
{
if (str[i] >= 'a' && str[i] <= 'z')
str[i] -= 32;
i++;
}
return (str);
}
EX 09 ft_strcapitalize ★★★☆ Difícil ▼
Capitaliza la primera letra de cada "palabra" (secuencia alfanumérica), el resto en minúscula. Ejemplo: salut, comment tu vas ? 42mots → Salut, Comment Tu Vas ? 42mots
- Necesitas saber si estás al inicio de una palabra. Usa una variable new_word (1 = inicio de palabra, 0 = dentro de palabra).
- Empieza con
new_word = 1(el primer carácter siempre es inicio). - Si el char actual es alfanumérico (letra o dígito): si
new_word == 1, pónlo en mayúscula; si no, en minúscula. Luegonew_word = 0. - Si el char no es alfanumérico (espacio, coma, etc.):
new_word = 1.
char *ft_strcapitalize(char *str)
{
int i;
int new_word;
i = 0;
new_word = 1;
while (str[i])
{
if ((str[i] >= 'a' && str[i] <= 'z')
|| (str[i] >= 'A' && str[i] <= 'Z')
|| (str[i] >= '0' && str[i] <= '9'))
{
if (new_word == 1 && str[i] >= 'a' && str[i] <= 'z')
str[i] -= 32;
else if (new_word == 0 && str[i] >= 'A' && str[i] <= 'Z')
str[i] += 32;
new_word = 0;
}
else
new_word = 1;
i++;
}
return (str);
}
C 03 — Comparación y concatenación de strings
s1 == s2 — eso compara punteros. Hay que comparar carácter a carácter. La diferencia entre dos chars es lo que devuelven strcmp y sus variantes: negativo si s1 < s2, 0 si son iguales, positivo si s1 > s2.
EX 00 ft_strcmp ★★☆☆ Medio ▼
Compara dos strings. Devuelve 0 si son iguales, negativo si s1 < s2, positivo si s1 > s2.
- Itera mientras
s1[i] == s2[i]Y el carácter no sea '\0'. - Cuando el loop termina, devuelve la diferencia:
(unsigned char)s1[i] - (unsigned char)s2[i]. - Si llegamos al final iguales, s1[i] = s2[i] = '\0', así que la diferencia es 0.
int ft_strcmp(char *s1, char *s2)
{
int i;
i = 0;
while (s1[i] == s2[i] && s1[i] != '\0')
i++;
return ((unsigned char)s1[i] - (unsigned char)s2[i]);
}
unsigned char para evitar problemas con caracteres con valores > 127 (extendidos). Es el comportamiento estándar de la libc.
EX 02 ft_strcat ★★☆☆ Medio ▼
Concatena src al final de dest. Devuelve dest.
- Primero, busca el final de
dest: avanza un índice hasta llegar al '\0' de dest. - Desde ese punto, copia todos los caracteres de
src. - Añade '\0' al final.
- Devuelve
dest.
char *ft_strcat(char *dest, char *src)
{
int i;
int j;
i = 0;
j = 0;
while (dest[i])
i++;
while (src[j])
{
dest[i] = src[j];
i++;
j++;
}
dest[i] = '\0';
return (dest);
}
EX 04 ft_strstr ★★★☆ Difícil ▼
Busca la primera aparición de to_find dentro de str. Devuelve el puntero a esa posición, o NULL si no encuentra. Si to_find es vacío, devuelve str.
- Si
to_find[0] == '\0'(string vacío), devuelvestr. - Para cada posición i de str, comprueba si
to_findencaja ahí. - Compara carácter a carácter con un índice j.
- Si llegas al final de to_find sin fallar (
to_find[j] == '\0'), devuelvestr + i. - Si no encontraste nada, devuelve
NULL(0).
char *ft_strstr(char *str, char *to_find)
{
int i;
int j;
if (!to_find[0])
return (str);
i = 0;
while (str[i])
{
j = 0;
while (str[i + j] == to_find[j] && to_find[j])
j++;
if (!to_find[j])
return (str + i);
i++;
}
return (0);
}
2. Compila siempre con cc -Wall -Wextra -Werror — 0 warnings.
3. No uses for, switch, ternario (?), ni goto.
4. Declara variables al inicio de la función, con línea vacía antes del código.
5. return (valor); — siempre con paréntesis.
6. Máximo 25 líneas por función.