3 Eylül 2016 Cumartesi

perror

Giriş
Şu satırı dahil ederiz.
#include <stdlib.h>
Genellikle uygulama ismi de yazdırılır.
int main(int argc, char *argv[])
{
    char *foo = malloc(9999999999L);
    if (foo == 0)
        perror(argv[0]);
    return 0;
}
Çıktı olarak şunu alırız.
> ./foo
./foo: Cannot allocate memory

26 Ağustos 2016 Cuma

__cdecl Calling Convention

__cdecl - C Dili
Şöyledir. Metod çağrısı yapan stack'i eski haline getirir.
push b;
push a;
call fnAdd;
add esp, 8    # restore stack.
Bu calling convention'da value olarak geçilen bir sınıf, metod'dan çıkarken yok edilir. Şöyle bir kod olsun.
#include <stdio.h>

struct Foo {
    Foo() { puts("created"); }
    Foo(const Foo&) { puts("copied"); }
    ~Foo() { puts("destroyed"); }
};

void __cdecl x(Foo f) { }

int main() {
    Foo f;
    x(f);
    return 0;
}
x'in assemly koduna bakarsak Foo f parametresi için destructor çağrısı yapıldığını görebiliriz.
x:
    mov     qword ptr [rsp+8],rcx
    sub     rsp,28h
    mov     rcx,qword ptr [rsp+30h]
    call    module!Foo::~Foo (00000001`400027e0)
    add     rsp,28h
    ret
__stdcall - Windows 
Şöyledir. Metod kendisi stack'i eski haline getirir.
push b;
push a;
call fnAdd;    # stack is restored by the callee. with ret 8
Bu Windows'ta kullanılan calling convention. Windows'ta DLL metodları şöyle tanımlanır.
#ifdef TEST_EXPORTS
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif

TESTAPI int __stdcall myadd(int a, int b);
Bazı Win32 metodlarının imzası şöyledir.
WINADVAPI LSTATUS APIENTRY RegQueryValueExW(...);
Burada APIENTRY aslında __stdcall için macro'dur. Bazen de WINAPI __stdcall için macro olarak kullanılır.





18 Ağustos 2016 Perşembe

filebuf Sınıfı

Giriş
Şu satırı dahil ederiz.
#include <fstream>
Constructor
Şöyle yaparız.
std::filebuf tempfilebuf;
close metodu
Şöyle yaparız.
tempfilebuf.close();
open metodu
Şöyle yaparız.
tempfilebuf.open("/tmp/extmpfile", std::ios::binary|std::ios::out);
Daha sonra bu sınıf ostream ile kullanılabilir. ostream yok olunca dosya kapatılmaz. Şöyle yaparız.
{
  std::ostream tempfile(&tempfilebuf);
  ...
}


8 Ağustos 2016 Pazartesi

std::bind1st

Giriş
Lambda çıktıktan sonra bu algoritmalara gerek kalmadı. Bu metod binary bir function ile çalışır.
Şöyle yaparız. greater metodunun ilk parametresi 10 olacaktır. 10 > x true ise aslında 10'dan küçük elemanları sayarız
vector<int> v1; 
// Count the number of integers < 10 in the vector 
count_if( v1.begin(), v1.end(), bind1st(greater<int>(), 10 ) ); 


4 Ağustos 2016 Perşembe

std::mem_fn

Giriş
Şu satırı dahil ederiz.
#include <functional>
std::mem_fn işlev olarak std::bind ile hemen hemen aynı şey.

Alana Erişmek
Şöyle yaparız.
#include <algorithm>
#include <functional>
#include <iterator>    
#include <iostream>

struct Obj { int a, b, c; };

int main() {

  Obj o[3] = {{1, 2, 3}, {11, 22, 33},{111, 222, 333}};

  int a[3];

  std::transform(std::begin(o), std::end(o),
                 std::begin(a),
                 std::mem_fn(&Obj::a));

  for (auto e : a)
    std::cout << e << ' ';

  std::cout << std::endl;
};
Çıktı olarak şunu alırız.
1 11 111

18 Temmuz 2016 Pazartesi

Streamler wofstream Sınıfı

imbue metodu
Şöyle yaparız.
#include <fstream>
#include <locale>
#include <codecvt>

const locale utf8_locale = locale(locale(), new codecvt_utf8<wchar_t>());
wofstream file(url);
file.imbue(utf8_locale);
file << L"իմբյու" << endl;


26 Mayıs 2016 Perşembe

C++ ile Locale

Locale atamak

C++ programlarında global bir locale bulunur. Bu locale ilk açılışta std::locale::classic() olarak atanmıştır.

Global locale nesnesini değiştirmek için şu yöntemlerden biri kullanılabilir

1. "If a programmer wants to honor local conventions it should use corresponding locale objects. The static member function global of the class locale can be used to install a global locale object."

std::locale::global(std::locale(""));
Programın C locale'i başladığını ancak daha sonra değişitirildiğini gösteren küçük bir örnek
int main(void)
{
  std::cout << std::locale().name() << std::endl;//C locale ile başlar
  std::locale::global(std::locale(""));//Kullanıcının locale'ini atar
  std::cout << std::locale().name() << std::endl;
  std::locale::global(std::locale("C"));//C locale'ini atar
  std::cout << std::locale().name() << std::endl;
  return 0;
}
Çıktı olarak şunu verir
C
French_Canada.1252
C

2. setlocale metodu kullanılır.  std::setlocale yazısına taşıdım.

Locale İsimleri
Eğer belli bir ülkenin locale'i kullanılmak istenirse "" yerine locale ismini kullanmak gerekir.Ancak kullanılan string ismi platforma göre değişkenlik gösterir. Linux üzerinde seçili locale isimini görmek için "locale" komutu kullanılabilir.

Java gibi dillerde locale isimleri standartlaşmıştır.  Locale.getISOLanguages() ve Locale.getISOCountries() metodları kullanılabilir. Java'da şöyle yaparız:
public final class IsoUtil {
    private static final Set<String> ISO_LANGUAGES = new HashSet<String>
        (Arrays.asList(Locale.getISOLanguages()));
    private static final Set<String> ISO_COUNTRIES = new HashSet<String>
        (Arrays.asList(Locale.getISOCountries()));

    private IsoUtil() {}

    public static boolean isValidISOLanguage(String s) {
        return ISO_LANGUAGES.contains(s);
    }

    public static boolean isValidISOCountry(String s) {
        return ISO_COUNTRIES.contains(s);
    }
}