42 - Ft_printf

Yayın: 6 Nisan 2025 | Yazar: Derya Acar

Bu proje, standart C dilindeki printf işlevinin yeniden yazılmasıdır. printf işlevi, biçimlendirilmiş bir çıktı oluşturmak için kullanılır ve çeşitli veri türlerini ve biçim belirteçlerini destekler. ft_printf işlevi, aynı davranışı yeniden oluştururken, standart kütüphane fonksiyonlarından bağımsız olarak çalışır ve tamamen özelleştirilebilir bir yapı sunar.


Özellikler



Dosya Açıklamaları



Fonksiyon Açıklamaları


💡 Örnek Kod:


    int	ft_printf(const char *str, ...)
    {
        va_list	args;
        int		leng;
        int		counter;
        int		tmp;
    
        counter = -1;
        leng = 0;
        va_start(args, str);
        while (str[++counter] != '\0')
        {
            if (str[counter] == '%' && ft_check(str[counter + 1]))
            {
                tmp = ft_format(&args, str[++counter]);
                if (tmp == -1)
                    return (-1);
                                    leng += tmp - 1;
            }
            else if (ft_putchar(str[counter]) == -1)
                return (-1);
            leng++;
        }
        va_end(args);
        return (leng);
    }
                  

Açıklama: Fonksiyon, va_list aracılığıyla aldığı değişken sayıda parametreyi belirtilen format belirteçleri doğrultusunda biçimlendirerek çıktıya yazdırır. Örneğin, %d ile tamsayı, %s ile dize, %c ile karakter gibi biçimlendirmeler yapabilirsiniz. Ayrıca %% ile yüzde işaretini yazdırabilirsiniz.


💡 Örnek Kod:


    int	ft_format(va_list *args, char w)
    {
        if (w == 'c')
            return (ft_putchar(va_arg((*args), int)));
        else if (w == '%')
            return (ft_putchar('%'));
        else if (w == 'd' || w == 'i')
            return (ft_int(va_arg((*args), int)));
        else if (w == 'u')
            return (ft_unsigned(va_arg((*args), unsigned int)));
        else if (w == 's')
            return (ft_string(va_arg((*args), char *)));
        else if (w == 'X' || w == 'x')
            return (ft_hex(va_arg((*args), unsigned int), w));
        else if (w == 'p')
            return (ft_point(va_arg((*args), unsigned long), 1));
        else
            return (0);
    }
        

Açıklama: Fonksiyon, w değişkeninin değerine göre uygun alt fonksiyonu çağırır. Örneğin 'c' karakteri için ft_putchar, 'd' veya 'i' için ft_int, 'x' veya 'X' için ft_hex işlevlerini kullanır.


💡 Örnek Kod:


    int	ft_check(char str)
    {
        if (str == 'c' || str == 'd' || str == 'i' || str == 'u' || str == '%'
            || str == 's' || str == 'x' || str == 'X' || str == 'p')
            return (1);
        return (0);
    }
        

Açıklama: Fonksiyon, str karakterinin geçerli bir format belirteci olup olmadığını kontrol eder.


💡 Örnek Kod:


    int	ft_int(int w)
    {
        int	leng;
        int	tmp;

        leng = 0;
        if (w == 0)
            return (write(1, "0", 1));
        if (w == -2147483648)
            return (write(1, "-2147483648", 11));
        if (w < 0)
        {
            if (write(1, "-", 1) == -1)
                return (-1);
            leng++;
            w *= -1;
        }
        if (w >= 10)
        {
            tmp = ft_int(w / 10);
            if (tmp == -1)
                return (-1);
            leng += tmp;
        }
        if (write(1, &"0123456789"[w % 10], 1) == -1)
            return (-1);
        return (leng + 1);
    }
        

Açıklama: Fonksiyon, negatif veya pozitif bir tamsayıyı doğru biçimde ekrana yazdırır. Değer 0 veya -2147483648 gibi özel durumlar için doğrudan yazdırma işlemi yapılır. Diğer durumlarda, rekürsif olarak basamak basamak yazdırma işlemi gerçekleşir.


💡 Örnek Kod:


    int	ft_unsigned(unsigned int w)
    {
        int	leng;
        int	tmp;

        leng = 0;
        if (w >= 10)
        {
            tmp = ft_unsigned(w / 10);
            if (tmp == -1)
                return (-1);
            leng += tmp;
        }
        if (write(1, &"0123456789"[w % 10], 1) == -1)
            return (-1);
        return (leng + 1);
    }
        

Açıklama: Fonksiyon, işaretsiz bir tamsayıyı rekürsif olarak her basamağını yazarak ekrana basar. Böylece sayının büyüklüğüne göre birden çok kez fonksiyonun kendisini çağırır ve son basamağına kadar tüm rakamları write ile çıktı verir.


💡 Örnek Kod:


    int	ft_string(char *str)
    {
        int	i;

        i = -1;
        if (str == NULL)
        {
            if (write(1, "(null)", 6) == -1)
                return (-1);
            return (6);
        }
        while (str[++i])
        {
            if (write(1, &str[i], 1) == -1)
                return (-1);
        }
        return (i);
    }
        

Açıklama: Fonksiyon, geçerli bir karakter dizisi aldıktan sonra dizinin her karakterini tek tek write ile ekrana basar. Eğer gelen str değerinin NULL olduğu fark edilirse, ekrana (null) yazısı basılarak dizinin geçersiz olduğunu ifade eder.


💡 Örnek Kod:


    int	ft_hex(unsigned int d, char w)
    {
        int	leng;
        int	tmp;

        leng = 0;
        if (d >= 16)
        {
            tmp = ft_hex(d / 16, w);
            if (tmp == -1)
                return (-1);
            leng += tmp;
        }
        if (w == 'X')
        {
            if (write(1, &"0123456789ABCDEF"[d % 16], 1) == -1)
                return (-1);
        }
        if (w == 'x')
        {
            if (write(1, &"0123456789abcdef"[d % 16], 1) == -1)
                return (-1);
        }
        return (leng + 1);
    }
        

Açıklama: Fonksiyon, onaltılık tabanda yazdırmak istediğiniz d değerini rekürsif olarak her basamağa ayrıştırır. w değerine göre büyük ( 'X' ) ya da küçük ( 'x' ) harflerle hex çıktısı üretir. Değer 16 veya daha büyükse önce üst basamakları yazdırır, ardından son basamağı ekrana basar.


💡 Örnek Kod:


    int	ft_point(unsigned long w, int i)
    {
        int	leng;
        int	tmp;

        leng = 0;
        if (i == 1)
        {
            if (write(1, "0x", 2) == -1)
                return (-1);
            i = 0;
            leng += 2;
        }
        if (w >= 16)
        {
            tmp = ft_point(w / 16, i);
            if (tmp == -1)
                return (-1);
            leng += tmp;
        }
        if (write(1, &"0123456789abcdef"[w % 16], 1) == -1)
            return (-1);
        return (leng + 1);
    }
        

Açıklama: Fonksiyon, bir adresi onaltılık (hex) formda yazdırır. İlk çağırıldığında i == 1 ise 0x ön ekini yazarak pointer gösterimini standarda uygun hale getirir. Değer 16 veya daha büyük olduğu sürece bölerek tüm basamakları yazdırır.


Variadic Functions (stdarg) Nedir?

ft_printf gibi birden fazla (değişken sayıda) parametre alan fonksiyonlar, variadic function olarak adlandırılır. C dilinde, bu tür fonksiyonlar için #include <stdarg.h> başlık dosyasını kullanırız.

va_list değişken parametreleri tutan özel bir türdür, va_start fonksiyonun prototipinde tanımlanmayan parametrelerin başlangıcını belirler, va_arg sıradaki parametreyi okur ve va_end işlemler bittikten sonra temizlik yapar.

💡 Örnek Kod:


    #include <stdarg.h>
    #include <stdio.h>

    int sum_of_numbers(int count, ...)
    {
        va_list args;
        int sum = 0;

        va_start(args, count);
        for (int i = 0; i < count; i++)
            sum += va_arg(args, int);
        va_end(args);

        return sum;
    }

    int main()
    {
        int result = sum_of_numbers(4, 1, 2, 3, 4);
        printf("Toplam: %d\n", result); // 10

        return 0;
    }
        

write Nedir?

ft_printf projesinde, çıktı almak için genellikle write sistem çağrısı kullanılır. Bu fonksiyon, verilen karakter dizisini belirli bir dosya tanımlayıcısına (genellikle STDOUT) yazar.

C dilinde write fonksiyonunu kullanmak için #include <unistd.h> eklemeniz gerekir. Projede, printf veya puts gibi fonksiyonlar yerine, write ile çıktıyı doğrudan yönetirsiniz.

💡 Örnek Kod:


    #include <unistd.h>

    int main()
    {
        const char *str = "Merhaba ft_printf!";
        write(1, str, 18); // 1 = STDOUT
        return 0;
    }
        

Recursion (Özyineleme) Nedir?

Recursion, bir fonksiyonun kendini çağırması durumudur. ft_printf projesinde sayıları veya adresleri onaltılık tabanda yazdırırken sıkça kullanılır. Böylece her basamak işlendikçe, geri kalan basamaklar için fonksiyon tekrar çağrılır.

💡 Örnek Kod:


    #include <stdio.h>

    int factorial(int n)
    {
        if (n <= 1)
            return 1;
        return n * factorial(n - 1);
    }

    int main()
    {
        printf("%d\n", factorial(5)); // 120
        return 0;
    }
        

Format Belirteçleri Nedir?

ft_printf içinde %d, %s, %x gibi format belirteçleri ile verileri farklı biçimlerde yazdırabiliriz. Her belirteç, hangi türde değişkenin nasıl yazdırılacağını belirler.

Örnekler:
%d / %i (imt / imzalı tamsayı)
%u (işaretsiz tamsayı)
%x / %X (onaltılık, küçük/büyük harf)
%p (pointer / adres)
%c (karakter)
%s (karakter dizisi)
%% (yüzde işareti)

💡 Örnek Kod:


    #include <stdio.h>

    int main()
    {
        int d = 42;
        unsigned int u = 100;
        char c = 'A';
        char *s = "Hello";

        printf("d: %d, u: %u, c: %c, s: %s, hex(d): %x\n", d, u, c, s, d);
        return 0;
    }
        

NULL Nedir?

NULL, bir işaretçinin geçerli bir bellek adresini göstermediği özel bir değerdir. ft_printf projesinde, char * türündeki bir değişken NULL olduğunda, genellikle (null) ifadesi basılır.

💡 Örnek Kod:


    #include <stdio.h>

    void print_str(const char *str)
    {
        if (str == NULL)
            printf("(null)");
        else
            printf("%s", str);
    }

    int main()
    {
        char *s = NULL;
        print_str(s);  // (null)
        return 0;
    }
        

unsigned ve signed Tamsayılar

ft_printf içinde %d veya %i işaretli (signed) tamsayıları, %u ise işaretsiz (unsigned) tamsayıları yazdırır. İşaretsiz tamsayılarda negatif değer bulunmazken, signed tamsayılarda negatif, pozitif ve sıfır değer saklanabilir.

💡 Örnek Kod:


    #include <stdio.h>

    int main()
    {
        signed int si = -5;
        unsigned int ui = 5;

        printf("signed: %d\n", si);   // -5
        printf("unsigned: %u\n", ui); // 5

        return 0;
    }
        

Öneri ve İletişim:

Proje hakkında tüm görüş, öneri ve sorularınız için dilediğiniz zaman iletişime geçebilirsiniz. daha çok yazı, bilgi ve içerik için takipte kalmayı unutmayın. Projenin orijinal kaynak kodlarına aşağıdaki bağlantıdan ulaşabilirsiniz:

🔗 Proje GitHub Linki


42 42 Ecole Libft C