C de Unicode?

Başlatan uçbirim2002, 22 Aralık 2016 - 14:04:49

« önceki - sonraki »

0 Üyeler ve 1 Ziyaretçi konuyu incelemekte.

uçbirim2002

C dilinde çoğu zaman Türkçe karakterler ile sorun yaşıyorum. Windows tarafında <locale.h> ile sorunun bir bölümünü çözüyorum ama yinede sürprizlerle karşılaşıyorum.

C dilinde Unicode kullanmak için bir yöntem veya kütüphane var mıdır?
Hello!

Erdem

C için şöyle bir kütüphane var  ;)

http://julialang.org/utf8proc/

locale.h *.nix tarafında da var diye biliyorum ama ben C++ ile kullanmıştım.

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <locale>


using namespace std;

typedef vector <string> Sozcukler;


Sozcukler giristenOku ()
{
     Sozcukler sozcukler;

     string sozcuk;

     while (cin >> sozcuk)
     {
         sozcukler.push_back (sozcuk);
     }
     return sozcukler;
}

void okuSiralaAra (string const & aranansozcuk)
{
     Sozcukler sozcukler = giristenOku ();
     sort (sozcukler.begin (), sozcukler.end (), locale ("turkish"));
     cout << "Sözcükleri şöyle sıraladım: ";
     copy (sozcukler.begin (), sozcukler.end (),
           ostream_iterator<string> (cout, " "));
     cout << endl;
     Sozcukler::iterator const sonuc = lower_bound (sozcukler.begin (),
                                                    sozcukler.end (),
                                                    aranansozcuk,
                                                    locale("turkish"));
     if (sonuc != sozcukler.end () && *sonuc == aranansozcuk)
     {
         cout << "En az bir tane "
              << aranansozcuk << " buldum! "
              << "Sıralanmış listede "
              << distance (sozcukler.begin (), sonuc) + 1
              << " sırada duruyor\n";
     }
     else
     {
         cout << "Aranan " << aranansozcuk << " sözcüğünü bulamadım\n";
     }
}

int main (int argc, char* argv[] )
{

     if (argc != 2)
     {
         cerr << "Lütfen hangi sözcügün aranacağını bildirin\n"
              << "Doğru kullanım: "
              <<  argv [0] << " <sozcuk>\n";
         return 1;
     }

     okuSiralaAra (argv [1]);

}

bugra9

Eğer işletim sistemiyle alakalı bir şey deniyorsanız linux tarafında bir şey yapmanız gerekmiyor çünkü linux zaten ön tanımlı olarak unicode kullanıyor ve tüm karakter setlerini destekliyor. Ne yaptığınızı ve nasıl bir hata aldığınızı yazarsanız nokta atış cevaplar gelebilir.

uçbirim2002

String lerde sorun olmuyor, ama iş char türüne gelince printf (ve diğer fonksiyonlar) düzgün çalışmıyor.
Hello!

Erdem

#include <stdio.h>
#include <wchar.h>
#include <locale.h>

int main(void)
{
    setlocale(LC_ALL, "");
    printf("%ls\n", L"Çorba yapmaya gidiyordu");
    char dizge[] = "çğIŞÜI";
    printf("%s\n", dizge);
    return 0;
}


uçbirim2002

Dediğim gibi sorun char türünde. Mesela:

#include <stdio.h>
#include <locale.h>

int main(void)
{
    setlocale(LC_ALL, "Turkish");
    char turkce_karakter = 'Ç';

    printf("%c\n", turkce_karakter);

    return 0;
}


Çıktısı:


Oluyor. Veya:

#include <stdio.h>
#include <locale.h>
#include <string.h>

int main(void)
{
    setlocale(LC_ALL, "Turkish");
    char *metin = "ÇÖŞİÜĞışüğçö";

    int i = 0;
    for(i = 0; i < strlen(metin); ++i)
    printf("%c\n", metin[i]);

    return 0;
}


Çıktısı bu oluyor:
























Hello!

Erdem

O olmaz tabi çünkü tek baytlık bir değişkene birden fazla baytlık unicode bir değer atamaya çalışıyorsun.

char demek tek baytlık bir karakterdir. 0xFF

İkili olarak yazarsak

1111 1111

bu şekilde olur.

Örneğin D'de char UTF-8 kod birimi olarak kullanılır. Ama unicode karakterler iki baytla kodlanır.

Unicode'un tanımladığı anlamda harflerle, imlerle, ve diğer simgelerle ilgilendiğimiz durumlarda D'de dchar türünü kullanıyoruz.


import std.stdio;

void main()
{
    // derlenmez
    // char karakter = 'Ç';
    dchar başkaKarakter = 'Ç';
    writefln("%s", başkaKarakter);
}

uçbirim2002

Hello!

Erdem

#include <stdio.h>
#include <locale.h>
#include <wchar.h>

int main(void)
{
    setlocale(LC_ALL, "tr_TR.UTF-8");
    wchar_t karakter = L'Ç';
    wchar_t dizge[20] = L"Merhaba nasılsınız";
    wprintf(L"%lc %ls\n", karakter, dizge);
}


Şu program bende çalıştı. wchar karakterler için %lc dizgeler için %ls kullanılıyormuş. c99 ile derledim.

uçbirim2002

Hello!

neynefes

İstek üzerine başlık açılmıştır.

uçbirim2002



Durum C ile benzer olduğu için soruyorum.

Örneğin kullanıcıdan bir karakter girmesini isteyen, ve bu karaktere yazan D programı:

import std.stdio;

void main()
{
    char karakter = karakter_okuma_fonksiyonu(); // D hakkında fazla bilgim yok :)
    writefln("%c", karakter);
}


Böyle bir durumda kullanıcı 'Ç' 'Ğ' gibi bir karakter girerse, dediğinize hata oluşur. Yada karakteri yanlış yazar. Böyle bir durumda ne yapmam? Tüm değişkenlerimi varsayılan olarak dchar olarakmı belirlemem gerekir?

Konu D'ye kaydı ama bu durumu C ye uyarlarsak, her karakter veya karakter dizisinde wchar_t mi kullanmam gerekir?
Hello!

7hr33l3t73r

#12
Sizin kodunuzdan yuruyerek soyle  bir kod. ( haric Ş, Ğ, ı)

#include <stdio.h>
#include <string.h>
int main(void)
{
        char *metin = "\xc7\xd6\xdc\xcd\xfc\xe7\xf6\x00";
        char *meto = "\xd6\xdc\xcd\xfc\xe7\xf6\x00";
                        /* \xc7 =  Ç */
                        /* \xd6 =  Ö */
                        /* \xdc =  Ü */
                        /* \xcd =  Í */
                        /* \xfc =  ü */
                        /* \xe7 =  ç */
                        /* \xf6 =  ö */
        int i = 0;
        for (i = 0; i < strlen(metin); ++i)
        printf("%05c", metin[i]);
        for (i = 0; i < strlen(meto); ++i)
        printf("\n\n%005c", meto[i]);
        return 0;
}


Cikti.

$ ./ch
    Ç    Ö    Ü    Í    ü    ç    ö

    Ö

    Ü

    Í

    ü

    ç

    ö%


Simdi wchar ile.

#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main(void)
{
        wchar_t wc = L'\x15e';  /* Ş */
        setlocale(LC_ALL, "en_US.UTF-8");
        wprintf(L"%lc\n", wc);
}



Gelelim char'dan :) donusturmeye...


#include <locale.h>
#include <wchar.h>

int main()
{
        char narrow_str[] = "ÇÖŞİÜĞışüğçö";
        wchar_t warr[36];
        setlocale(LC_ALL, "");
        swprintf(warr, sizeof warr/sizeof *warr,
                        L"Convered from UTF-8: '%s'", narrow_str);
        wprintf(L"%ls\n", warr);
}


Simdi kullanicidan, isteyelim ve yazdiralim.

#include <stdio.h>
#include <wchar.h>
#include <locale.h>

int main() {
    wchar_t string[100];
    setlocale(LC_ALL, "");
    printf ("Enter a string: ");
    scanf("%ls",string);
    printf("String Entered: %ls: length: %dn", string, wcslen(string));
    return 0;
}

Cikti.

$ ./string
Enter a string: ĞÜÖÖÇMIIııIIMNNNBBKKLŞŞLPPOoO,iŞLÇÖ
String Entered: ĞÜÖÖÇMIIııIIMNNNBBKKLŞŞLPPOoO,iŞLÇÖ: length: 35n

Sanirim bunlar size fikir verebilir. Ne yapmak istediginize tam hakim olamadigim icin boyle birkac ornek paylasiyorum. Zaten arkadaslarda gerekli aciklamalari size yapmis. Yeterince ornek kodlama da bulabilirsiniz.
dc -e '[q]sa[ln0=aln256%Pln256/snlbx]sb207356256404211981204295703670388snlbxq'
https://www.getgnu.org/gnulinux/gnulinux-ipuclari/nasil-akillica-soru-sorulur.html