29 Haziran 2020 Pazartesi

printf ailesi

Giriş
C dilinde şu satırı dahil ederiz.
#include <stdio.h>
C++ dilinde şu satırı dahil ederiz.
#include <cstdio>
Bazen C++ programlarında bu satırı dahil etmesek bile printf() kullanılabiliyor.
Örnek
Şöyle yaparız
#include <iostream>

int main(int argc, char const *argv[])
{
  printf("haha");
  return 0;
}
Açıklaması şöyle.
It's implementation defined if that works or not.

The implementation may include additional headers it needs, but you as a developer should not rely on that and include cstdio too which is the guaranteed way to get access to std::printf.

Including stdio.h puts printf in the global namespace and that is usually not what one wants in C++, so stick with cstdio.
Formatlı Veri Yazma
Variadic Function'lar - yani 3 nokta (...) kullanan metodlar - arasında en bilineni printf'tir. printf ailesindeki metodlar formatlı veri yazmak için kullanılır. Bu metoda geçilen değişkenin tipini % işareti ile bildirmemizin sebebi, variadic metodların parametre tiplerini çıkarımda bulunarak anlamak zorunda olmasıdır.

printf ailesi scanf ailesine çok benzer. Her iki ailede kullanılan format belirteçleri çok benzer olsa da birebir aynı değildirler. Aralarında farklar bulunur.Örneğin scanf ailesinde # formatlama işareti kullanılamaz.

printf Neden Float İçin Belirteç Tanımlamaz
printf variadic olduğu için float parametreler dilin kendisi tarafından double'a terfi ettirilir. Haliyle de float için belirteç kullanmaya gerek kalmaz.

precision
Aynen scanf ailesinde olduğu gibi precision verilebilir. Precision % ve sayı ve formatbelirteci veya % ve * ve formatbelirteci olarak verilir. Eğer * kullanılırsa precision parametre olarak belirtilir.
format
(optional) . followed by integer number or *, or neither that specifies precision of the conversion.In the case when * is used, the precision is specified by an additional argument of type int. If the value of this argument is negative, it is ignored. If neither a number nor * is used, the precision is taken as zero. See the table below for exact effects of precision.
Return value
1-2) Number of characters written if successful or negative value if an error occurred.
Örnek
Aşağıdaki kod 9 tane boşluk yazar. 4 tane ' ' ve 5 tane ' ' yani toplam 9 boşluk karakteri
printf("%*c%*c", 4, ' ', 5, ' ');
Örnek
Şöyle yaparız.
char buf[10000];

int precision=10;

const auto num = ...;
std::snprintf(buf, sizeof buf, "%.*e", precision, num);
float scientific
Şöyle yaparız.
#include <cstdio>

std::string FloatToScientificString(float val, int width, int precision)
{
  static const int bufSize = 100;
  static char buffer[bufSize];

  std::snprintf(buffer, bufSize, "%*.*e", width, precision, val);

  return std::string(buffer);
}
double - %lf
Şöyle yaparız. float için özel bir belirteç yoktur. float yazdırılırken de %lf kullanılır ve float tipi double tipine cast edilir.
double a = ...;
printf("%lf ", a);
hexadecimal - %x
int gibi sayıları hexadecimal olarak bastırmak için kullanılır.Şöyle yaparız.
int e = ...;
printf("%0x",&e);
Çıktı olarak şunu alırız.
da54dcac 
int64_t
gcc'de %zx veya %zd kullanılır. Microsoft %Ix veya %Id'yi destekliyordu. VS 2015 ile %z'yi de desteklemeye başladı.

Örnek
Daha eski kodlarda VS ile şöyle yaparız.
int64_t d = ...;
printf("%" PRId64 "\n", d);
long - %l
Şöyle yaparız
long int num = ...;
printf("%ld\n", num);
unsigned için şöyle yaparız
printf("%lu\n", sizeof(long));
long double - %Lf
Şöyle yaparız
long double x = 561.308;
printf("%Lf",x);
long long - %lld
Örnek
Şöyle yaparız.
long long num = ...;
printf("%lld", num);
Örnek
Şöyle yaparız.
long long int d = ...;
printf("%lld", d);
Örnek
qd kullanıldığı da olur ancak %ll tercih edilmeli. Şöyle yaparız.
long long lli=1;
printf("%qd\n", lli);
unsigned long long - %llu
Örnek
Şöyle yaparz
struct statfs buf = ...;
...
printf("Free inodes =%llu\n", buf.f_ffree);
load variable - %n
%n karakterine kadar olan string uzunluğu bir sonraki değişkene atanır. Açıklaması şöyle.
In C printf(), %n is a special format specifier which instead of printing something causes printf() to load the variable pointed by the corresponding argument with a value equal to the number of characters that have been printed by printf() before the occurrence of %n.
Örnek
Şöyle yaparız. "abc " string'inin uzunluğu olan 4, i değişkenine atanır.
int i = 0;
printf("abc %n %d", &i, i);
printf("\n%d\n", i);
Çıktı olarak şunu alırız.
abc  0
4
pointer - %p
Açıklaması şöyle. printf void pointer bekliyor ancak C++ hariç özel olarak cast etmek gerekmiyor.
p - The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.
Örnek - Field
Elimizde şöyle bir kod olsun.
struct Foo
{
  int a;
  int b;
  int c;
};
C ve C++ ile şöyle yaparız.
printf( "%p\n", &some_foo.c );
std::cout << static_cast<void*>{&some_foo.c} << '\n';
Örnek - int
Şöyle yaparız.
int i;    
printf ("%p", &i);
Örnek - char *
Şöyle yaparız.
char * m = "Hello";    
printf ("%p", m);
Şöyle yaparız.
char* str1 = "First";
char* str2 = "Second";
char* str3 = "First";

printf("%p %p %p", str1, str2, str3);
Çıktı olarak şunu alırız.
00403024 0040302A 00403024
Örnek - void *
Şöyle yaparız.
void *p = NULL;
printf("%p", p);
pointer yani uintptr_t - %td
Şöyle yaparız.
int var = ...;
uintptr_t varptr = (uintptr_t)&var;
printf("varptr = %td\n", varptr);
uint64_t - %zu
sizeof() size_t tipinden döner. Bu da çoğu platformda 64 bittir. Şöyle yaparız.
size_t x = ...;
ssize_t y = ...;
printf("%zu\n", x);  // prints as unsigned decimal
printf("%zx\n", x);  // prints as hex
printf("%zd\n", y);  // prints as signed decimal
unsigned int - %u
Şöyle yaparız.
printf("%u\n", 1u);
string - %s
%s seçeneği yazısına taşıdım.

Parametresiz printf
printf'i parametresiz kullanmak hatalıdır.
const char *str;
...
printf(str);
Daha Az Parametre
printf ailesine beliritlenden daha az parametre geçmek Undefined Behavior yaratır. Açıklaması şöyle.
  1. The fprintf function writes output to the stream pointed to by stream, under control of the string pointed to by format that specifies how subsequent arguments are converted for output. If there are insufficient arguments for the format, the behavior is undefined. If the format is exhausted while arguments remain, the excess arguments are evaluated (as always) but are otherwise ignored. The fprintf function returns when the end of the format string is encountered.
Örnek
Şu kod hatalı.
printf("%s is your password");
Fazladan Parametre
printf ailesine fazladan parametre geçmek zararsızdır.
[...] If the format is exhausted while arguments remain, the excess arguments are evaluated(as always) but are otherwise ignored [...]
Örnekte iki format belirteci kullanılmasına rağmen 3 parametre geçiliyor ancak bunun bir zararı yok.
printf("Test %d %s", 123, "abc", "def", "ghi");
Yazılacak Yer Olarak Null
Şöyle yaparız. strlen ile aynı işi görür.
...
const char *src = "hello, alphaGo!";
int32_t len = snprintf(nullptr, 0, "%s", src);