Forum: D Programlama Dili RSS
Konsol Türkçe Karakter Hatası
Sayfa:  önceki  1  2  3 
emre413 (Moderatör) #31
Kullanıcı başlığı: Celal Emre ÇİÇEK
Üye Tem 2009 tarihinden beri · 62 mesaj · Konum: Kırıkkale
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj ID 9967
Evet hocam onu buldum ama buraya henüz yazmamıştım. Sonra şöyle bir şey denedim:

import std.stdio;
import core.sys.windows.windows;
import std.string;
 
extern(C) {
    int wprintf(const wchar *format,...);
}
 
void main() {
    const int _O_U8TEXT = 0x40000;
 
    setmode(fileno(stdout.getFP()), _O_U8TEXT);
    wprintf("Türkçe Karakterler: ı I İ i ö Ö ü Ü ğ Ğ ç Ç ş Ş");
}

wprintf tanımında wchar_t yerine wchar kullandım ondan mı oldu bilmiyorum ancak karakterler doğru basılmadı. Bu arada o getFP olayını düzeltince _setmode ve _fileno fonksiyonlarını tanımadı. Galiba zaten std.stdio'da bu fonksiyonlar tanımlı imiş. Ondan dolayı setmode ve fileno kullanınca tanıdı. Program çalıştı ancak doğru işlev görmedi.
acehreli (Moderatör) #32
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Ortalık çok karıştı. :)

emre413:
extern(C) {
    int wprintf(const wchar *format,...);
}

Tamam, wprintf bir wchar* göstergesi alıyormuş.

emre413:
    wprintf("Türkçe Karakterler: ı I İ i ö Ö ü Ü ğ Ğ ç Ç ş Ş");

O satır derleniyor mu? O dizgi hazır değerinin türü string olmalı (yani, değişmez char dizisi). Otomatik tür dönüşümü olduğunu sanmıyorum. Onun için dizginin sonunda w karakteri olmalı: "merhaba"w gibi... Sonra .ptr niteliği ile veya ilk karakterinin adresi ile wchar* elde edilir. (O da, dizgi hazır değerleri '\0' ile sonlandıkları için çalışır. Yoksa, herhangi bir dizginin sonunda '\0' yoktur.) Yani, "merhaba"w.ptr gibi deneyebilirsin.

emre413:
wprintf tanımında wchar_t yerine wchar kullandım

O bir yere kadar çalışır. Windows'un wchar_t'si UTF-16 değildir ama D'nin wchar'ı UTF-16'dır. Buna rağmen bizi ilgilendirmeyen bazı Unicode karakterleri dışında kodlar birbirlerini tutar. (Windows Unicode'u çok geç anlayabilmiştir.)n

karakterler doğru basılmadı

Elimde Windows sistemi olmadığı için yardım da edemiyorum.

Ama biraz duralım ve yavaş yavaş sırayla gidelim. C++ programını da bir kenara bırakalım lütfen. D programını anlamada kafamızı karıştırmaktan başka hiçbir işe yaramıyor. (Hatta, C++ kaynak kodunun UTF-8 olabilmesi ise sanırım ancak C++11 ile mümkün oldu.)

1) D'de char dizgileri UTF-8'dir. Bundan kaçış yok. Dolayısıyla, "ü" dizgisi iki adet UTF-8 baytından oluşur.

2) O baytlar çıkışa yazdırıldıklarında doğal olarak iki adet UTF-8 kodu olarak yazdırılırlar.

3) Çıkışta konsol var. Konsol eline teker teker iki bayt geçirir. O baytları ne yapsındır? Eğer 1254'e veya başka bir karakter tablosuna ayarlanmışsa her birisini tek karakter olarak algılar ve iki adet karakter yazdırır. ü'nün UTF-8'deki iki baytının değeri 1254'te hangi karakterlere karşılık geldiyse konsol onları gösterir.

Dolayısıyla, konsolu UTF-8'e ayarlamazsak D programının doğru göstermesi mümkün değildir. (Aslında dizgiyi yazdırmadan önce kendimiz bir tercüme de yapabiliriz: Örneğin, ü yerine 1254'teki karşılığını yazdırabiliriz ama her write'tan önce buna dikkat etmek gerekeceğinden onu bir kenara bırakalım.)

4) Konsol UTF-8 olsa bile kullanılan fontun da Unicode karakterlerini içermesi gerekir. Bunun iki yolu olmalı:

Birincisini denedik ve başaramadık: Fontu program içinden seçmek.

İkinci yöntem, konsol için seçilen fontu sistem düzeyinde değiştirmek. Bir anlamda, varsayılan fontu bir kere seçmek. Bu, programın herhangi bir Windows ortamında işlediği durumu kurtarmıyor ama bizim için bir çözüm olabilir.

Benim anladığım bu. Tabii bunun tersi de gerekiyor:

1) Klavyenin fiziksel olarak sağ taraflarındaki o tuşun ü olduğu seçilmiş olan klavye düzeninden bilinmektedir.

2) Konsol ü'ye basıldığını öylece anladığı için onun karşılığı olan iki UTF-8 baytını programın girişine verir.

3) D programı da UTF-8 olduğundan iki baytı olduğu gibi alır ve char dizisinin içine yerleştirir.

Ali
emre413 (Moderatör) #33
Kullanıcı başlığı: Celal Emre ÇİÇEK
Üye Tem 2009 tarihinden beri · 62 mesaj · Konum: Kırıkkale
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Evet fazlaca karıştı :)

Şimdi asıl sorun yani benim düşündüğüm acaba setmode fonksiyonunu düzgün olarak çağıramıyor muyum? Çünkü C++'ta yazınca çalışıyor. Ayrıca MinGW ile de derledim yine çalıştı. Öbürünü VC++ ile denemiştim.

_setmode io.h dosyasında, _fileno stdlib.h dosyasında prototip olarak; _O_U8TEXT fcntl.h dosyasında ve stdout zaten stdio.h dosyasında tanımlı.

Ayrıca _setmode msvcrt.dll'in içinde.

Bir yerde direkt LoadLibraryA ile msvcrt.dll'den çağıran bir kod buldum D için denedim ama yine olmadı. Olmadı derken hata vermedi ama çalışmadı da. Gariplik burada.

import std.stdio;
import core.sys.windows.windows;
import std.string;
 
extern(C) {
    int wprintf(const wchar *format,...);
}
 
extern (Windows)
alias int function(int,int) setmode_f;
 
void main(char[][] args)
{
   const int _O_U8TEXT = 0x40000;
 
   setmode_f f;
 
   HMODULE m = cast(HMODULE) LoadLibraryA(toStringz("msvcrt.dll"));
 
   f = cast(setmode_f) GetProcAddress(m, toStringz("_setmode"));
 
   f(fileno(stdout.getFP()), _O_U8TEXT);
 
   f(cast(int)stdout.getFP(), _O_U8TEXT);
 
   wstring trKarakterler = "Türkçe Karakterler: ı I İ i ö Ö ü Ü ğ Ğ ç Ç ş Ş\n"w;
 
   fwrite(trKarakterler.ptr, 1, trKarakterler.length, stdout.getFP());
 
   writef(trKarakterler);
   wprintf(trKarakterler.ptr);
}

Acaba sorun ekrana basma fonksiyonunda mı diye üç farklı fonksiyon ile denedim.

writeln(f(fileno(stdout.getFP()), _O_U8TEXT));

ile fonksiyonun dönüşüne baktım 65536 döndürdü. MSDN açıklamasında başarılı olursa bir önceki çeviri modunu döndürür diyor yanlış anlamadıysam.

65536 = 0x10000 yani _O_WTEXT

fcntl.h'da baktım.

#define _O_WTEXT        0x10000 /* file mode is UTF16 (translated) */

olarak tanımlanmış. Yani UTF16 olarak gösteriyor.

Şimdilik edindiğim bilgiler bunlar. Yine araştırmaya devam edeceğim ama bu sorun biraz zor çözülür gibi beni aşıyor :)
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Sayfa:  önceki  1  2  3 
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-19, 20:01:39 (UTC -08:00)