Forum: D Programlama Dili RSS
Karakter giriş çıkışı
Sayfa:  1  2  sonraki 
acehreli (Moderatör) #1
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ı
Konu adı: Karakter giriş çıkışı
Bu programda Türkçe harf kullandım ama ASCII olmayan bütün karakterler için geçerli:

import std.stdio;
 
void main()
{
    // Derlenmiyor; çünkü 'ğ'nin değeri char'a sığmıyor:
    // char ğ = 'ğ';
 
    // Bence dmd'nin bir hatası yüzünden derlenemiyor:
    // wchar ğ = 'ğ';
 
    // Çalışıyor:
    dchar ğ = 'ğ';
    writeln(ğ);
}

wchar'ın derlenememesi bence hata; onun dışında tamam...

Peki girişten ASCII olmayan karakterleri nasıl okuyacağız ve yazdıracağız? Türkçe karakterlerin char'a sığmadığını anlıyorum. Örneğin aşağıdaki program ğ girildiğinde hatasız çalışıyor ama çıkışa doğal olarak ğ'nin iki baytından birisini yazdırıyor ve çıktıda ğ görünmüyor. Bu doğal, çünkü 2 bayttan oluşan Unicode ğ değeri tek bayta sığmıyor...

Ama wchar ve dchar için de okuma sırasında Segmentation fault alıyorum:

import std.stdio;
import std.cstream;
 
void main()
{
    char karakter;
    din.readf(&karakter);
    writeln(karakter);
}

char yerine wchar veya dchar kullanınca hata oluşuyor. dmd hatası mı; yoksa bir şeyleri yanlış mı anlıyorum?

Ali
Avatar
esatarslan52 (Moderatör) #2
Üye Haz 2009 tarihinden beri · 142 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Ben örnek olark verdiğiniz programları wchar kullanarak çalıştırdığımda code::blocks stdio.d modülünü açarak aşağıdaki satırı hata olarak gösteriyor.dchar olarak denediğimde de çalışma anında "access violation" hatası alıyorum.
FPUTC(c, backend);
wchar için Verdiği hata mesajları;
924|Error: undefined identifier backend|
924|Error: function std.stdio._fputc_nlock (int, _iobuf*) does not match parameter types (wchar,int)|
924|Error: cannot implicitly convert expression (backend) of type int to _iobuf*|

Yukarıdaki satırın bulunduğu kodun satırları aşağıdaki gibi.
else static if (c.sizeof == 2)
            {
                if (orientation <= 0)
                {
                    if (c <= 0x7F)
                    {
                        FPUTC(c, backend);
                    }
                    else
                    {
                        char[4] buf;
                        auto b = std.utf.toUTF8(buf, c);
                        foreach (i ; 0 .. b.length)
                            FPUTC(b[i], backend);
                    }
                }
                else
                {
                    FPUTWC(c, backend);
                }
            }

acehreli:
import std.stdio;
import std.cstream;
 
void main()
{
    char karakter;
    din.readf(&karakter);
    writeln(karakter);
}
Yukarıdaki kod bende hatasız olarak çalışıyor 'ğ' girince ekrana aynı şekilde 'ğ' yazdırıyor.Tiplerin bayt değerler aşağıdaki gibi.
char.sizeof ==> 1
wchar.sizeof ==> 2
dchar.sizeof ==> 4
Bu şartlar altında wchar ve dchar kullanınca doğru çalışmalı char kullanınca da problem çıkmalı. Ama tam tersi bir durum söz konusu  :-/ . Acaba dediğiniz gibi biz mi bir şeyleri yanlış anlıyoruz ki  :blush:
acehreli (Moderatör) #3
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ı
Aynı hata bende de çıkıyor işte... backend en azından o dosyada tanımlı değil. Herhalde bir dmd (veya kütüphane) hatası olarak kabul edeceğiz. Belki birisi bir bug açmıştır bile. Bugün vakit bulursam bakacağım.

esatarslan52:
acehreli:
import std.stdio;
import std.cstream;
 
void main()
{
    char karakter;
    din.readf(&karakter);
    writeln(karakter);
}
Yukarıdaki kod bende hatasız olarak çalışıyor 'ğ' girince ekrana aynı şekilde 'ğ' yazdırıyor.

Sanırım bu, kullandığımız ortamın kodlamasıyla ilgili. Ben varsayılan kodlaması UTF-8 olan bir Linux ortamındayım. Eğer girişten char alan basit bir program yazarsam, ve Türkçe karakteri başka bir pencereden kopyalayarak verirsem, iki char olarak okuyor. (Programı çalıştırdığım pencerede Türkçe klavyem yok. Sonra kullanınca ona da bakacağım.)

Senin ortamında ise tek karakterli kod tablolarından birisi kullanıyor herhalde?

Öğreneceğiz! :)

Ali
acehreli (Moderatör) #4
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ı
wchar için bir bug açtım:

  http://d.puremagic.com/issues/show_bug.cgi?id=3260

Ali
quasimodo (Moderatör) #5
Üye Haz 2009 tarihinden beri · 12 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Comment #1 From  Andrei Alexandrescu   2009-08-19 23:59:42 PDT  -------

Thanks for the report.

Super :)
Karaali
acehreli (Moderatör) #6
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ı
Bu hata giderilmiş... Bir sonraki sürümde doğru çalışması bekleniyor.

Ali
canalpay (Moderatör) #7
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Acaba bir sonraki sürüm ne zaman çıkar ? Tahmininiz var mı ?
acehreli (Moderatör) #8
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ı
Sürümlerin geçmişi şurada:

  http://www.digitalmars.com/d/2.0/changelog.html

Bazen bir kaç haftada bir, bazen iki ayda bir... En son 6 Temmuz'da çıktığına göre 2.032 çok yakında çıkacaktır.

Bundan sonra gelişmeleri daha yakından izleyelim ve yeni olanakları hemen deneyelim ve öğrenelim... :)

Ali
white_rabbit #9
Üye Nis 2010 tarihinden beri · 11 mesaj · Konum: denizli
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
bu sorun giderilmemiş mi bende mi bir hata var.

dmd 2.048 ile ubuntu üzerinde girişten wchar ve dchar okurken Segmentation fault hatası veriyo.

import std.stdio;
import std.cstream;
 
void main() {
    char ch;
    //wchar ch; // hata
    //dchar ch; // hata
    din.readf(&ch);
    writeln(ch); 
}
acehreli (Moderatör) #10
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ı
Evet, çalışmıyor. :(

Zaten din.readf yerine readf (stdin.readf'in kısaltması) kullanılması öneriliyor, ama o da çalışmıyor. Zaten yeni başlayanlar için fazla karışık... :/

Ben de D.ershane'deki bütün din.readf'leri readf ile değiştirmeye başlamış ama fazla ileriye gidememiştim. Ben bir sonraki sürümü bekliyorum. :/

Ali
canalpay (Moderatör) #11
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Zaten yeni başlayanlar için fazla karışık... :/

Bende şimdi denedim ve çalışmıyor. Ancak şimdi çok beğendim. Örneğin teoride şu çalışması gerekiyor (sonsuz parametre alabiliyor. Ne güzel :-) ) :
import std.stdio;
 
void main() {
 
    char a;
    wchar b;
    dchar c;
    
    readf("%s", &a,&b,&c);
 
}

Ayrıca tür dönüşümü yapmadan int türüne bile okuduğumuzu koyabiliyor olmamız lazım.

 
import std.stdio;
 
void main() {
 
    int a;
    int b;
    int c;
    
    readf("%d", &a,&b,&c);
 
}


Şuan readf yerine yine std.stdio'da bulunan readln kullanılabilir.  Ancak string olarak değer dönüştürdüğünde tür dönüşümü yapmak gerekiyor. Ancak cast ile dönüşüm yapılamıyor.  conv'deki to şablonuda hatalı sanırım.  stringin char'a dönüştürülememesi hata mıdır, yoksa normal midir ?
acehreli (Moderatör) #12
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ı
canalpay:
Örneğin teoride şu çalışması gerekiyor (sonsuz parametre alabiliyor. Ne güzel :-) ) :
import std.stdio;
 
void main() {
 
    char a;
    wchar b;
    dchar c;
    
    readf("%s", &a,&b,&c);

Ama orada her okunan için bir düzen karakteri olması gerekiyor: "%s %s %s". Hata da o durumda çalışmaması zaten.

Ayrıca tür dönüşümü yapmadan int türüne bile okuduğumuzu koyabiliyor olmamız lazım.

 
import std.stdio;
 
void main() {
 
    int a;
    int b;
    int c;
    
    readf("%d", &a,&b,&c);

Evet, onun da "%d %d %d" ile çalışması gerek. Ve... O çalışıyor! ;)

Hatta, "%s %s %s" kullanınca da çalışıyor. Çünkü "%s"nin anlamı "değişkenin türüne göre oku" demek oluyor.

Ve senin de dediğin gibi, aslında düzen bilgisi kullanmadan da okuyabilmeliyiz. Yani aslında şöyle kullanılabilmeli:

    readf(&a, &b, &c);

Çünkü zaten din.readf düzen dizgisi almadan okuyabiliyor.

Şuan readf yerine yine std.stdio'da bulunan readln kullanılabilir.

Evet, ama o '\n' karakterini de okuyor. Şöyle bir şey denemiştik galiba:

import std.stdio;
import std.string;
import std.conv;
 
void main()
{
    string line = strip(stdin.readln());
 
    auto i = parse!int(line);
    auto d = parse!double(line);
//     auto s = parse!string(line); ÇALIŞMIYOR
 
    writeln(i, ' ', d);
}

parse!string çalışmadığı gibi, o programın çalışması için girişin de tek satır olarak gelmesi gerekiyor. Örneğin int'i yazıp Enter basılamıyor. Ama şöyle bir giriş tamam: 42 1.25

Bunların hiçbirisi çözülemeyecek sorunlar değil ama yeni başlayanlara uygun olmadığı açık.

conv'deki to şablonuda hatalı sanırım.  stringin char'a dönüştürülememesi hata mıdır, yoksa normal midir ?

İlginç bir soru. :) Aklıma gelen sorunlar:

- string'de birden fazla karakter varsa ilkini mi istiyoruz?
- string'de birden fazla karakter varsa, ama örneğin dchar'a dönüştürüyorsak acaba UTF-8'den UTF-32'ye dönüşüm mü istiyoruz?

Programcılıkta bazen en iyi çözüm, kararın zor olduğu durumlarda çözümü programcıya bırakmaktır. :) Bu durumda string'den karaktere dönüşümü yasaklamak, o tür soruları yanıtlamaktan kurtarıyor. Çünkü programcı kendisi seçebilir.

Ali
canalpay (Moderatör) #13
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Ama orada her okunan için bir düzen karakteri olması gerekiyor: "%s %s %s". Hata da o durumda çalışmaması zaten.


- string'de birden fazla karakter varsa ilkini mi istiyoruz?
olabilir
- string'de birden fazla karakter varsa, ama örneğin dchar'a dönüştürüyorsak acaba UTF-8'den UTF-32'ye dönüşüm mü istiyoruz?
olabilir.

Ancak şu bile çalışmıyor :
import std.conv;
void main(){ 
    char b;
    string a="a";
    b=to!(char)(a);    
}

To şablonunda hata var diyeceğim ancak cast içinde :
import std.conv;
void main(){ 
    char b;
    string a="a";
    b=cast(char)a;
}

hatalı.

a.dup şeklide hatalı tabi :

import std.conv;
void main(){ 
    char b;
    string a="a";
    b=a.dup;
}

İlk elemenına erişmek istersem yine hatalı :
import std.conv;
void main(){ 
    char b;
    string a="a";
    b=a[0].dup;
}

Aklıma gelen tek çözüm stringi char dizisine cevirip sonra chara çevireceğiz. Sanırımbunun nedeni çift tırnak kullanıldığında dizi olarak kabul edilmesi. Ancak dizi olsada kaç elemanı var ki ? 1
import std.stdio;
import std.conv;
void main(){ 
    char b;
    string a="a";
    writeln(a.length);
}

Bana ilk başlarda tek tırnak karakter olarak algılanması ve çift tırnağın karakter dizisi olarak algılanması garip gelmişti. Belki bunun sonucudur ?

Eğer D kendi çözüm getirmeyecekse çözümü getirecek ve en başta sorduğunuz o iki işide gerçekleştircek küçük bir kütüphane çok güzel olabilir.
acehreli (Moderatör) #14
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ı
canalpay:
- string'de birden fazla karakter varsa ilkini mi istiyoruz?
olabilir

Ama kütüphanenin o kararı veremeyeceğini anlayabiliyorum. Hatta bazı durumlarda istenmeyen bir hata bile olabilir. İlk karakter istendiğinde açıkça dizgi[0] yazabiliyoruz nasıl olsa.

- string'de birden fazla karakter varsa, ama örneğin dchar'a dönüştürüyorsak acaba UTF-8'den UTF-32'ye dönüşüm mü istiyoruz?
olabilir.

O kabul edilebilir sanırım. Ama o da yine aynı soruna sahip: string'in uzunluğu 5 ise UTF-8'den dönüşebilen ilk Unicode karakterini mi dönüştürsün? İlk karakterin kodlaması 3 char geretiriyorsa onları mı kullansın?

Bence de olabilir ama karışıklık doğurabilecek garip kararlar bunlar. :) Yine programcıya bırakmak daha iyi.

Ancak şu bile çalışmıyor :
import std.conv;
void main(){ 
    char b;
    string a="a";
    b=to!(char)(a);

Orada string'in uzunluğu 1 olduğu için izin verilmesini bekleyebiliyoruz herhalde. Ama string bir parametre olsa? Yani uzunluğu derleme zamanında bilinmese? Sanırım izin verilmemesinin nedeni o.

a.dup şeklide hatalı tabi :

import std.conv;
void main(){ 
    char b;
    string a="a";
    b=a.dup;
}

Tabii. Çünkü aynı şey: kopyası da string...

İlk elemenına erişmek istersem yine hatalı :
import std.conv;
void main(){ 
    char b;
    string a="a";
    b=a[0].dup;
}

Orada .dup yazılmasa çalışıyor. Çünkü ilk elemanının türü char zaten.

Aklıma gelen tek çözüm stringi char dizisine cevirip sonra chara çevireceğiz. Sanırımbunun nedeni çift tırnak kullanıldığında dizi olarak kabul edilmesi.

Evet, string zaten char dizisi.

Ancak dizi olsada kaç elemanı var ki ? 1
import std.stdio;
import std.conv;
void main(){ 
    char b;
    string a="a";
    writeln(a.length);
}

Uzunluğunun 1 olduğunu bu örnekte biliyoruz. Ama derleyici kod üretirken belirli kuralların dışında akıllılık göstermemelidir. Onun elindeki sorun, string'in char'a dönüştürülmesi. O işi yapan bir kütüphane işlevi bulamıyor. Onun işi orada bitiyor.

Daha ileriye giderek, o dizginin uzunluğunun derleme zamanında biliniyor olmasına bakarak karar vermez. Öyle olsa, bugün derlenen program ilerideki bir zamanda derlenemeyebilir. Kodu değiştirip string bir parametreyi kullanmaya başlasak, artık derleyici o akıllılığı gösteremez ve program derlenemez.

Bana ilk başlarda tek tırnak karakter olarak algılanması ve çift tırnağın karakter dizisi olarak algılanması garip gelmişti. Belki bunun sonucudur ?

Tek tırnak, tek karakter oluyor; çift tırnak ise karakter dizisi.

Eğer D kendi çözüm getirmeyecekse çözümü getirecek ve en başta sorduğunuz o iki işide gerçekleştircek küçük bir kütüphane çok güzel olabilir.

Ama o soruların yanıtlarını verebilmeliyiz. Dizginin ilk karakterini mi kullanacağız? Bence programcının dizgi[42] diye seçmesi çok daha açık olur ve istenmeden yanlış derlenme durumunu ortadan kaldırır.

Ali
canalpay (Moderatör) #15
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Tabii. Çünkü aynı şey: kopyası da string...

Ben dup ile mutable olarak kopyalandığını idup immutable ile kopyalandığını düşünüyordum.

Her dediğiniz kabul. Ben sanırım bazı konuları karıştırmışım. Dün dizileri okuyordum. Orada ne zaman dilim oluyor ne zaman dilimlikten çıkıyor, ayrıca bir dizi adını yazarken ne zaman [] karakteri kullanılıyor derken karıştırmışım.

Örneğin şurada çok güzel bir olanak var. Ancak anlamadığım yerler var. :

import std.stdio;

void main(){ 
    double[] sayı = [1,5,9,5,5,2,3];
    
    sayı[]= (sayı[]+3)/2;// Burada [] kullanmak şart. Peki neden şart ?
    writeln(sayı); // Burada tüm elemanı yazarken şart mı değil mi ? Dmd'nin bir hatası mı var ?
}


D'de dizilerin çok fazla ayrıntısı var.
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:  1  2  sonraki 
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-22, 03:09:12 (UTC -08:00)