10 Kasım 2017 Cuma

std::ctype facet

ctype
Şu satırı dahil ederiz.
#include <locale>
ctype bir karakterin hangi kümeye ait olduğunu bulmak için kullanılır. Küme metodları
isalnum,isalpha, islower, isupper vs. gibi şeylerdir. Donüşüm metodları tolower, toupper gibi şeylerdir.

ctype atama
Şöyle yaparız.
std::stringstream ss = ...;
std::locale numbers (std::locale(), new my_ctype);
ss.imbue(numbers);
Constructor 
Örnek ver

Constructor - from locale
ctype facet olduğu için locale içindeki haline erişmek için std::use_fact<std::ctype<...>>(locale) çağrısı yapılır.

Örnek
ctype locale nesnesinin içindedir. locale nesnesi global olmalı. Şu kullanım şekli yanlış.
auto& ct = std::use_facet<std::ctype<char>>(std::locale(""));
Örnek
Şöyle yaparız.
std::locale loc(std::locale(""));
auto& ct = std::use_facet<std::ctype<char>>(loc);
Örnek
Şöyle yaparız.
std::locale const loc("");
std::use_facet<std::ctype<char >(loc)....//Artık ctype sınıfı kullanabiliriz.
scan_is metodu
Birinci parametre mask olarak anılır. İkinci ve üçücü parametreler iterator başı ve sonudur. Mask koşulunu sağlayan ilk karakteri döner.
Örnek
Şöyle yaparız. Çıktı olarak "Test" alırız
// skip until the first letter
char s1[] = "      \t\t\n  Test";
const char* p1 = ct.scan_is(std::ctype_base::alpha, std::begin(s1), std::end(s1));
Örnek
Şöyle yaparız. Çıktı olarak "abcd" alırız
// skip until the first letter
char s2[] = "123456789abcd";
const char* p2 = f.scan_is(std::ctype_base::alpha, std::begin(s2), std::end(s2));
std::cout << "'" << p2 << "'\n";
tolower Metodu
Bir karakteri küçük harfe değiştirmek için kullanılabilir. Örnekte elimizde şöyle bir nesne var.
std::u16string data(str ? str : u"");
std::u16string ldata;
Bu nesneyi küçük harfe çevirip ldata içinde saklamak istiyoruz.
auto const& ct = std::use_facet<std::ctype<char16_t>>(std::locale());
for (std::u16string::const_iterator it = data.begin(); it != data.end(); ++it)
{
    ldata.push_back( ct.tolower(*it) );
}
tolower metodunun tek bir karakter yerine iterator alan bir metodu daha var. Aynı şekilde çalışıyor.
std::u16string ToLower(const char16_t* str)
{
  if (!str) {
    return std::u16string();
  }
  std::u16string data(str);
  std::use_facet<std::ctype<char16_t>>(std::locale()).tolower(&data[0],
                                                      &data[0] + data.size());
  return data;
}
narrow Metodu
wide string'i, normal string'e çevirir. Örnekte narrow metodu çeviremediği karakterler için _ yazar.
#include <clocale>
#include <locale>
#include <string>
#include <vector>

inline std::string narrow(std::wstring const& text)
{
    std::locale const loc("");
    wchar_t const* f = text.c_str();
    std::size_t const len = text.size();
    std::vector<char> buffer(len + 1);
    std::use_facet<std::ctype<wchar_t> >(loc).narrow(f, f + len, '_', &buffer[0]);
    return std::string(&buffer[0], &buffer[len]);
}
table metodu
Her ctype sınıfı classification amaçlı bir tablo barındırır.  table en aza 256 karakter uzunluğundadır. table() metodu ile tabloya erişilir.
#include <iostream>
#include <cassert>
#include <locale>
int main()
{

    std::locale loc1("en_US.UTF8");
    const std::ctype_base::mask* tbl1 =
         std::use_facet<std::ctype<char>>(loc1).table();

    std::locale loc2(std::locale("en_US.UTF8"), new std::ctype<char>);
    const std::ctype_base::mask* tbl2 =
         std::use_facet<std::ctype<char>>(loc2).table();

    for(size_t n = 0; n < 256; ++n)
        assert(tbl1[n] == tbl2[n]);
}
ctype'tan kalıtım - Character Classification
Örnek
Rakamlar hariç diğer tüm karakterleri boşluk (space) olarak okuyan bir ctype facet için şöyle yaparız.
Önce rc değişkeni table_size kadar büyük yaratılıyor ve space ile dolduruluyor. Daha sonra '0' ve '9' karakterleri digit olarak işaretleniyor.
struct digits_only: std::ctype<char> {
  digits_only(): std::ctype<char>(get_table()) {}

  static std::ctype_base::mask const* get_table() {
    static std::vector<std::ctype_base::mask> 
      rc(std::ctype<char>::table_size,std::ctype_base::space);

    std::fill(&rc['0'], &rc['9'], std::ctype_base::digit);
    return &rc[0];
  }
};
Örnek
Rakamlar hariç diğer tüm karakterleri boşluk (space) olarak okuyan bir ctype facet için şöyle yaparız.
struct digit_reader : std::ctype<char>
{
  digit_reader() : std::ctype<char>(get_table()) {}
  static std::ctype_base::mask const* get_table()
  {
    static std::vector<std::ctype_base::mask> rc(table_size, std::ctype_base::mask());

    for (size_t i = 0; i < table_size; ++i)
    {
      rc[i] = std::isdigit(i) ? std::ctype_base::digit : std::ctype_base::space;
    }
    return &rc[0];
  }
};
Kullanmak için şöyle yaparız.
std::stringstream ss("=sjkc(11,32as%2dc 32,43)a-b,49,26),b.'47,28n,a=64");
ss.imbue(std::locale(std::locale(), new digit_reader()));

int num;
while (ss >> num)
{
  std::cout << num << ' ';
}
Örnek
Bir başka örnekte sadece tab karakteri whitespace olarak görülsün isteniyor. Böylece EOL gibi karakterler dikkate alınmıyor
// This is my facet:
// It is designed to treat only <tab> as whitespace
class TabSepFacet: public std::ctype<char>
{
public:
  typedef std::ctype<char>   base;
  typedef base::char_type    char_type;

  TabSepFacet(std::locale const& l) : base(table)
  {
    // Get the ctype facet of the current locale
    std::ctype<char> const&  defaultCType = std::use_facet<std::ctype<char> >(l);

    // Copy the default flags for each character from the current facet
    static char data[256];
    for(int loop = 0; loop < 256; ++loop) {data[loop] = loop;}
    defaultCType.is(data, data+256, table);

    // Remove the other spaces
    for(int loop = 0; loop < 256; ++loop)
    {
      // If the space flag is set then XOR it out.
      if (table[loop] & base::space)
      {   table[loop] ^= base::space;
      }
    }
    // Only a tab is a space
    table['\t'] |= base::space;
  }
private:
  base::mask table[256];
};




Hiç yorum yok:

Yorum Gönder