3 Mayıs 2016 Salı

tzset

Sistemin saat dilimini değiştirir. Şöyle yaparız.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main (int argc, char *argv[])
{
    struct tm *mt;
    time_t mtt;
    char ftime[10];

    setenv("TZ", "PST8PDT", 1);
    tzset();
    mtt = time(NULL);
    mt = localtime(&mtt);
    strftime(ftime,sizeof(ftime),"%Z %H%M",mt);

    printf("%s\n", ftime);
}

strptime

Giriş
Şu satır dahil edilir.
#include <ctime>
formatlı string'i struct tm yapısına çevirir. Yani C#'taki DateTime.ParseExact () metoduna benziyor. Tekrar formatlı string'e çevirmek için strftime kullanılır.

Bu metodun tersini yani struct tm yapısını formatlı string'e çevirme işini strftime yapar.

1. C dili ile strftime ile formatlanan bir string'i tekrar struct tm yapısına çevirmenin bir yolu yok. Ancak POSIX standardı ile gelen strptime bunu başarabiliyor. 
2. C++ ile std::get_time kullanılabilir.

Temel Kullanım
Şöyle kullanırız.
char myDate[] = "2012-01-01";

struct tm result;
char *end = strptime(myDate, "%Y-%m-%d", &result);
Tüm string'in düzgünce parse edildiğini şöyle kontrol ederiz.
if (end != NULL && *end == '\0') {...}

Hata varsa end null değerine eşittir. 
if (end == NULL)
{
  printf("Invalid date\n");
}
%Y : Yıl - 2016 gibi
%a : Kısa gün ismi - Mon gibi.
%b : Kısa ay ismi - Mar gibi
%d : gün - 15 gibi
%H : Saat - 09 gibi
%M : Dakika - 23 gibi
%S : Milisaniye - 6000000 gibi
%Z : Saat dilimi

Ay/Gün/Yıl için şöyle yapılır
struct tm tm;
strptime("01/26/12", "%m/%d/%y", &tm);
Saat dakika için şöyle yapılır.
std::tm tm = {};
char* snext = ::strptime("2016-Mar-15 09:23:58.665068", "%Y-%b-%d %H:%M:%S", &tm);

Saat Dilimi
Normalde tm yapısı içinde saat dilimi alanı yok. Bu alan bir GNU extension. Dolayısıyla derlerken time.h'tan önce şu #define'ları yapmak gerekiyor. Aslında benim anladığım sadece _GNU_SOURCE tanımlamasını yapmak yeterli.
#define __USE_XOPEN
#define _GNU_SOURCE

#include <time.h>
Ya da derleyiciye bu seçenekleri vermek gerekiyor.
gcc -Wall test.c -o test -D__USE_XOPEN -D_GNU_SOURCE

Anladığım kadarıyla bu metod saat dilimini çevirirken başarılı değil. Saati dilimi için %Z kullanılır.
Açıklaması şöyle
The %Z format specifier only accepts time zone abbreviations of the local time zone, or the value "GMT". This limitation is because of ambiguity due to of the over loading of time zone abbreviations. One such example is EST which is both Eastern Standard Time and Eastern Australia Summer Time.
Dolayısıyla yerel saat dilimi ve GMT dışında başka bir saat dilimi veremiyoruz. Eğer yerel saat dilimimiz EST ise şöyle yaparız.
const char* format =  "%b %d, %Y %H:%M:%S %Z";
const char* myDate = "Feb 19, 2016 01:00:00 EST";

struct tm result = {0};
char* end = strptime(myDate, format, &result);



29 Nisan 2016 Cuma

std::default_random_engine - Bir Pseudo-random number generator (PRNG)

Giriş
Şu satırı dahil ederiz.
#include<random>
C++ kütüphanesinin gerçekleştirimine bırakılmış. Açıklaması şöyle
Remark: The choice of engine type named by this typedef is implementation-defined. [ Note: The implementation may select this type on the basis of performance, size, quality, or any combination of such factors, so as to provide at least acceptable engine behavior for relatively casual, inexpert, and/or lightweight use. Because different implementations may select different underlying engine types, code that uses this typedef need not generate identical sequences across implementations. — end note ]
Bence bu sınıfı kullanmamak gerekir. Bu sınıf GCC'de minstd_rand0 olarak gerçekleştirilmiş.
VS2012'de ise mt19937 olarak gerçekleştirilmiş .

constructor - default
Sınıfı şöyle yaratabiliriz. Ancak bu durumda seed vermediğimiz için hep aynı sonuçları elde ederiz.
std::default_random_engine generator;
constructor - time
Sistem saatini kullanarak şöyle yaparız.
std::default_random_engine generator( (unsigned int)time(0) );
constructor - chrono time
Chrono kullanarak şöyle yaparız.
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine generator (seed));
constructor - random_device
Donanım tabanlı bir üreteci kullanarak şöyle yaparız.
std::default_random_engine generator( std::random_device{}() ); 




20 Nisan 2016 Çarşamba

std::atexit

Giriş
atexit main metod içinden return ile çıkılınca veya exit() metodu çağırılınca işletilen bir metodları eklemek için kullanılır

POSIX standardında pthread_cleanup_push() herhangi bir thread'den çıkınca işlem yapmak için kullanılır.

Şöyle yaparız.
#include <iostream>
#include <cstdlib>

void atexit_handler_1() 
{
    std::cout << "at exit #1\n";
}

void atexit_handler_2() 
{
    std::cout << "at exit #2\n";
}

int main() 
{
    const int result_1 = std::atexit(atexit_handler_1);
    const int result_2 = std::atexit(atexit_handler_2);

    if ((result_1 != 0) or (result_2 != 0)) {
        std::cerr << "Registration failed\n";
        return EXIT_FAILURE;
    }

    std::cout << "returning from main\n";
    return EXIT_SUCCESS;
}


19 Nisan 2016 Salı

std::get_money

Giriş
Şu satırı dahil ederiz.
#include <locale>
std::get_money metodu
Elimizde şöyle bir satır olsun.
$89.99
Bu satırı okumak için şöyle yaparız. Doldurulan parametre long double veya string olmalıdır. Değerin kuruş biriminde olduğu varsayalır.
long double price;   get_money only supports long double
ifstream filein("bookfile.txt");

filein.imbue(std::locale("en_US.UTF-8"));
filein >> std::get_money(price);
price /= 100;  //get_money uses the lowest denomination, in this case cents


15 Nisan 2016 Cuma

std::mutex Sınıfı

Giriş
Yeni mutex tipleri şunlar. Bu tipler POSIX'teki mutex tipleri ile aynı.

std::mutex, std::timed_mutex (C++11)
std::recursive_mutex, std::timed_recursive_mutex (C++11)
std::shared_mutex (C++17) , std::shared_timed_mutex (C++14)

Mutex Lockable kavramını getirir.

Mutex temel olarak şu metodları sunar.
  • lock
  • unlock
  • try_lock
Windows'ta std::mutex
std::mutex Windows'ta altta CriticalSection ile gerçekleştirilmiş. Mutex içinde şöyle bir kod var.
struct _Mtx_internal_imp_t
{   /* Win32 mutex */
    int type; // here MS keeps particular mutex type
    Concurrency::critical_section cs;
    long thread_id;
    int count;
};
Aslında ne ile gerçekleştirilmiş olduğunun pek bir önemi yok. CriticalSection ve std::mutex farklı şeyler. CriticalSection aynı thread tarafından birden fazla kilitlenebilir. Yani recursive bir yapıdır. std::mutex ise sadece bir kere kilitlenebilir.

try_lock metodu
Bu metodu hiç bir zaman kullanmamak en iyisi. unique_lock kullanmak en güzel çözüm.
unique_lock( mutex_type& m, std::try_to_lock_t t );
Şöyle kullanılırsa çok fazla işlemci yer.
std::mutex m;
while (!m.try_lock()) {}
# do work
m.unlock();



1 Nisan 2016 Cuma

locale ve karakterler

Giriş
Şu satırı dahil ederiz.
#include <cctype>
Bu metodlar seçili locale ile çalışır. Eğer belirtilen bir locale ile çalışmak istersek std::ctype facet kullanılır.

Küme Metodları
isalphanum metodu
Şöyle yaparız.
if (isalphanum(chValue)){...}
isblank metodu
Şöyle yaparız.
if (isblank(chValue)){...}
isupper metodu
isupper metodu verilen karakterin büyük olup olmadığını döndürür. Normalde ASCII kullandığımız için kod çok kolaydır ancak locale işin içine girince farklı kodlar yazmak gerekir. Örneğin EBCDIC için kod şöyle bir hal alır.
inline int is_upper_alpha(char chValue)
{
    if (((chValue >= 'A') && (chValue <= 'I')) ||
        ((chValue >= 'J') && (chValue <= 'R')) ||
        ((chValue >= 'S') && (chValue <= 'Z')))
        return 1;
    return 0;
}
ASCII için şöyle olmalıydı
inline int is_upper_alpha(char chValue)
{
    return ((chValue >= 'A') && (chValue <= 'Z'));
}
Bir de locale işin içine girince ortalık daha da karışır. Bu yüzden isupper() metod altta ctype nesnesini kullanarak bizi bu zahmetten kurtarır.

Dönüşüm Metodları
tolower
Metodun imzası şöyle
int std::tolower(int ch); // #include <cctype>
Metoda geçilen parametre unsigned char olarak geçilmeli.
for (char &ch : mystr)
    ch = std::tolower( (unsigned char)ch );
Neden var bilmiyorum ancak locale dosyası içinde de aynı isme ancak farklı imzaya sahip bir metod daha var.
template<typename charT>
charT std::tolower(charT ch, const std::locale& loc);    // #include <locale>