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.
%c, %d, %i, %u, %x, %X, %p, %s ve %% format belirteçlerini destekler.
ft_printf(const char *str, ...):
Projenin ana fonksiyonudur.
Biçimlendirme kontrolü yapar ve gerekirse uygun fonksiyonları çağırarak ekrana yazdırır.
ft_putchar(char x):
Tek bir karakteri ekrana yazar.ft_check(char str):
Gelen karakterin geçerli bir format belirteci olup
olmadığını kontrol eder.ft_format(va_list *args, char w):
Format belirteci w’ye göre ilgili alt
fonksiyonu çağırır.int ft_printf(const char *str, ...);
str
: Biçimlendirme yapılacak ve yazdırılacak metinleri içeren format dizesi.
-1
.
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.
'c'
, 'd'
,
's'
) göre değişkenlerin doğru şekilde yazdırılmasını sağlayan yardımcı fonksiyondur.
int ft_format(va_list *args, char w);
args
: Değişken sayıdaki parametrelerin işleneceği va_list
türündeki yapı.w
: Geçerli format belirteci (örneğin 'c'
, 'd'
,
's'
, 'x'
, 'X'
, 'p'
vb.).
-1
döner.
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.
int ft_check(char str);
str
: Kontrol edilecek karakter (örneğin 'c'
, 'd'
,
'i'
, 'x'
vb.).
1
, aksi halde
0
.
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.
int ft_int(int w);
w
: İşlenecek tamsayı değeri.-1
döner.
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.
int ft_unsigned(unsigned int w);
w
: İşlenecek işaretsiz tamsayı değeri.-1
döner.
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.
int ft_string(char *str);
str
: Yazdırılacak karakter dizisi.-1
döner.
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.
int ft_hex(unsigned int d, char w);
d
: İşlenecek onaltılık tabanda yazdırılacak sayı.w
: Yazdırma biçimini belirten karakter; 'x'
(küçük harf) veya
'X'
(büyük harf).
-1
döner.
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.
int ft_point(unsigned long w, int i);
w
: İşlenecek adres değeri (pointer).i
: Fonksiyonu ilk çağırma durumunu belirten, 0x
ön ekinin
yazdırılması için kullanılan bayrak benzeri bir değer. İlk çağrıda i == 1
gönderilirse, 0x
yazısı ekrana basılır.-1
döner.
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.
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.
#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;
}
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.
#include <unistd.h>
int main()
{
const char *str = "Merhaba ft_printf!";
write(1, str, 18); // 1 = STDOUT
return 0;
}
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.
#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;
}
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)
#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
, 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.
#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;
}
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.
#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;
}
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