Forum: Ders Arası RSS
Eşleme Tablosunda Eleman Sorgulama
canalpay (Moderatör) #1
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ı
Konu adı: Eşleme Tablosunda Eleman Sorgulama
Eşleme tablosunda eleman sorgulanırken şöyle bir kod yeterli oluyor:
bool değiştirildi_mi[string][string][string];
değiştirildi_mi["ilk"]["ikinci"]["üçüncü"]=true;
if("ilk" in değiştirildi_mi)
writeln("bulundu");

Ama değiştirildi_mi eşleme tablosundaki "ilk" sözcüğünü yapmak yerine "üçüncü" sözcüğünün var olup olmadığına bakmak için ne yapabilirim ?

if(("ilk" in değiştirildi_mi)&&("ikinci" in değiştirildi_mi["ilk"])
&&("üçüncü" in değiştirildi_mi["ilk"]["ikinci"]))

Böyle bir çözümü yanıt olarak kabuletmiyorum :-p Yani bu çözümden başka çözüm yolu var mı ?
Mengu (Moderatör) #2
Kullanıcı başlığı: NONSERVIAM
Üye Tem 2009 tarihinden beri · 347 mesaj · Konum: Dersaadet
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
bool değiştirildi_mi[string][string][string];
değiştirildi_mi["ilk"]["ikinci"]["üçüncü"]=true;

yukaridaki su satiri yazdirdigimizda karsimiza soyle bir sonuc cikacak:

[ilk:[ikinci:[ucuncu:true]]]

bu da demek oluyor ki, ikinci ilk'e, ucuncu de ikinci'ye ait. o halde su sekilde bir kod yazdigimiz zaman sonuca ulasabiliriz:

if ("üçüncü" in değiştirildi_mi["ilk"]["ikinci"])
{
    writeln("evet, üçüncü mevcut.");
}

tam kod:

import std.stdio;
 
void main(string[] args)
{
    bool değiştirildi_mi[string][string][string];
    değiştirildi_mi["ilk"]["ikinci"]["üçüncü"]=true;
    writeln(değiştirildi_mi);
    if ("üçüncü" in değiştirildi_mi["ilk"]["ikinci"])
    {
        writeln("evet, üçüncü mevcut.");
    }
}
http://www.mengu.net - some kind of monster
canalpay (Moderatör) #3
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ı
İn D için gerçekte öyle bir eşleme tablosunun anahtarı var mı diye bakar.

Eğer yoksa in false değeri döndürür. Ama sizinki (ve bende bu konuyu açmadan önce denediğim şekli) eğer o anahtar yoksa hata veriyor.

Mesela ilk mesajımda yazdığım şu kodu derleyin :
if(("ilk" in değiştirildi_mi)&&("ikinci" in değiştirildi_mi["ilk"])
&&("üçüncü" in değiştirildi_mi["ilk"]["ikinci"]))
ilk anahtarı olmasın yine hata vermez. Ama sizin verdiğiniz(ve bende bu konuyu açmadan önce denediğim) kod hata veriyor.

Yani kodlarla anlatırsam şu hata verir :

tam kod:

import std.stdio;
 
void main(string[] args)
{
    bool değiştirildi_mi[string][string][string];
    değiştirildi_mi["ilk"]["ikinci"]["üçüncü"]=true;
    writeln(değiştirildi_mi);
    if ("üçüncü" in değiştirildi_mi["ilk"]["dördüncü"])
    {
        writeln("evet, üçüncü mevcut.");
    }
}

Şöyle bir hata verir :
core.exception.RangeError@dkvB(136): Range violation


Çünkü olmayan bir eşleme tablosuna erişiyor. Ben ise olmayan eşleme tablosuna erişiyorsa false değeri döndürsün istiyorum.
Mengu (Moderatör) #4
Kullanıcı başlığı: NONSERVIAM
Üye Tem 2009 tarihinden beri · 347 mesaj · Konum: Dersaadet
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
anladim hocam. o halde bir de ali ustadin cevabi bekleyelim cunku benim aklima baska bir sey gelmiyor suan. :)
http://www.mengu.net - some kind of monster
acehreli (Moderatör) #5
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ı
Can'ın sevmediğinden başka yolu yok. :)

İşlev olarak yazılırsa biraz daha kolay oluyor:

import std.stdio;
 
V * mevcut(V, A)(V[A] tablo, A anahtar)
{
    return anahtar in tablo;
}
 
V * mevcut(V, A0, A1)(V[A0][A1] tablo, A0 anahtar0, A1 anahtar1)
{
    auto içTablo = anahtar0 in tablo;
    return içTablo ? mevcut(*içTablo, anahtar1) : null;
}
 
V * mevcut(V, A0, A1, A2)(V[A0][A1][A2] tablo,
                          A0 anahtar0, A1 anahtar1, A2 anahtar2)
{
    auto içTablo = anahtar0 in tablo;
    return içTablo ? mevcut(*içTablo, anahtar1, anahtar2) : null;
}
 
void main()
{
    bool değiştirildi_mi[string][string][string];
    değiştirildi_mi["ilk"]["ikinci"]["üçüncü"]=true;
//     if("ilk" in değiştirildi_mi)
//         writeln("bulundu");
 
    if (mevcut(değiştirildi_mi, "ilk", "ikinci", "üçüncü")) {
        writeln("bulundu");
    }
}

V, "veri"; A, "anahtar" anlamında. in işlecinin dönüş türü, tablodaki veri türünün göstergesidir. Onun için V * döndürüyorum.

null olmayan göstergeler de mantıksal ifadelerde true değerini aldıkları için çalışıyor.

Ali
canalpay (Moderatör) #6
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ı
Can'ın sevmediğinden başka yolu yok.


İyi yanından bakarsam tek olasılık varmış ve onuda bulmuşum ve hatta bir dilde şöyle bir özellik olsa nasıl olur diye düşünüyordum

source örnek = {("ilk" in değiştirildi_mi)&&("ikinci" in değiştirildi_mi["ilk"])
&&("üçüncü" in değiştirildi_mi["ilk"]["ikinci"])};
 
if(source örnek && 1==1){
 
}
gibi bir söz dizimine izin verse ne iyi olur diye düşünüyordum. Sanırım php'de böyle bir şey vardı.

Şuan verdiğiniz örneği anlamaya çalışıyorum. Ayrıca burada şablonlardan mı yararlanıyorsunuz ?
acehreli (Moderatör) #7
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:
tek olasılık varmış ve onuda bulmuşum

Öyle... :) Aslında tabii D'de iki boyutlu dizi veya iki boyutlu eşleme tablosu diye kavramlar yok. Dizi dizisi veya eşleme tablosu eşleme tablosu kullanarak onları bir oluşturuyoruz. O yüzden dil tek düzeyden fazlasını vermez.

ve hatta bir dilde şöyle bir özellik olsa nasıl olur diye düşünüyordum

source örnek = {("ilk" in değiştirildi_mi)&&("ikinci" in değiştirildi_mi["ilk"])
&&("üçüncü" in değiştirildi_mi["ilk"]["ikinci"])};
 
if(source örnek && 1==1){
 
}

D'de string mixin var, şablonların başka olanakları var. Başka çözümler de düşünülebilir.

burada şablonlardan mı yararlanıyorsunuz ?

Evet. Bütün V'leri ve A'ları string yaparsan, senin yazdığın kodun eşdeğeri oluyor. Ben her türle çalışsın diye şablon yaptım.

Ali
canalpay (Moderatör) #8
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ı
Teşekkürler şimdi çok daha iyi anladım.

Ama dkvG için bu kodu kullancağım ; dkvG'yi ilgilendirmeyen bir kodu boşuna koymaya gerek yok.
dkvG için şöyle bir kod yazdım:
    bool mevcut_mu(string ilk,string ikinci,string üçüncü)
    {
        if((ilk in değiştirildi_mi)&&(ikinci in değiştirildi_mi[ilk])
        &&(üçüncü in değiştirildi_mi[ilk][ikinci])){
            return true;
        }else {
            return false;
        }
    }

Ama yazdığınız kod benim için çok önemli. Hem overload var. Hem şablon var. Hemde gösterge.

null olmayan göstergeler de mantıksal ifadelerde true değerini aldıkları için çalışıyor.

diğer türler içinde geçerli değil mi bu ?
örneğin int 0, double 0.0 , string "0".. gibi

Eğer geçerli ise ne için gösterge kullandınız ?

Ayrıca şu satır çok dikkatimi çekti :
    return içTablo ? mevcut(*içTablo, anahtar1) : null;

içTablo auto olarak belirtmişsiniz ama içTablonun türü bool. Ama gösterge sayesinde sanırım anahtar0 değerine erişiyor. Ve sanırsam auto yerine bool yazmış olsaydınız erişemezdi. Yanılıyor muyum ?
acehreli (Moderatör) #9
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ı
Değişik sırada yanıtlıyorum.

canalpay:
Ayrıca şu satır çok dikkatimi çekti :
    return içTablo ? mevcut(*içTablo, anahtar1) : null;

içTablo auto olarak belirtmişsiniz ama içTablonun türü bool.

Aslında bool değil. :D Orada içTablo'nun türü, veri göstergesidir.

Eşleme tablolarını tanıttığım derste tabii ki göstergelere bulaşmayacaktım. O yüzden in'in dönüş türünün gerçeğini sonraya bırakmıştım.

in'in veri göstergesi döndürmesinin hızla ilgisi var. Eğer bool döndürseydi, bazı durumlarda gereksizce iki kere aranmış olurdu:

if (anahtar in tablo) {       // <-- birinci arama
    writeln(tablo[anahtar])// <-- ikinci arama
}

Anahtar'ın tabloda bulunup bulunmadığının anlaşılması da, o anahtara ait verinin bulunması da bir arama gerektirir.

Ama in'in dönüş türü veri göstergesi olunca:

string * veri = anahtar in tablo;  // <-- tek arama
 
if (veri) {
    writeln(*veri);    // gösterdiğine erişerek
}

Eşleme tablolarında arama çok hızlı olduğu için fazla önemli olmadığı düşünülebilir ama bir sistem dili olabilen bütün performansı vermek zorundadır.

Ama gösterge sayesinde sanırım anahtar0 değerine erişiyor.

Doğru.

Ve sanırsam auto yerine bool yazmış olsaydınız erişemezdi.

Evet, bool yazsaydım erişemezdi. auto yazmak, string* ile aynı anlama geliyor. içTablo'nun türünü typeof(içTablo).stringof diye yazdırmayı dene...

Ama dkvG için bu kodu kullancağım ; dkvG'yi ilgilendirmeyen bir kodu boşuna koymaya gerek yok.

Doğru karar! :) Olabildiğine az kod, ve ancak gerçekten gerekiyorsa...

dkvG için şöyle bir kod yazdım:
    bool mevcut_mu(string ilk,string ikinci,string üçüncü)
    {
        if((ilk in değiştirildi_mi)&&(ikinci in değiştirildi_mi[ilk])
        &&(üçüncü in değiştirildi_mi[ilk][ikinci])){
            return true;
        }else {
            return false;
        }
    }

Yukarıda performans ile ilgili olarak söylediklerimi kullanarak daha hızlısını yazabilirsin. ;)

null olmayan göstergeler de mantıksal ifadelerde true değerini aldıkları için çalışıyor.

diğer türler içinde geçerli değil mi bu ?
örneğin int 0, double 0.0 , string "0".. gibi

Sıfırın false olması çok genel bir kural. Gösterge veya referans türlerinde null olmak da false'a dönüştürür. Yukarıda verdiğin string örneği doğru değil. Derleyici string'in içindeki karakterlerin bir tamsayı anlama gelip gelmediğine bakmaz. O string, null olmadığı için, mantıksal ifadelerde true değerini alacaktır. (Denemedim ama. :D)

Eğer geçerli ise ne için gösterge kullandınız ?

Hem in'in dönüş değeri ile uygun olmak, hem de ufak bir hız kazancı sağlamak için.

Ali
canalpay (Moderatör) #10
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ı
Artık en çok istediğim ders göstergeler oldu. Hem böylece D ile olan bilgimde çağ atlayacağım. Her ne kadar D'de göstergelerin eski önemi kalmasada, göstergeye destek tamamen kalkmadan göstergenin önemi kalkmayacak.

Ayrıca göstergeyi öğrenirsem artık c(++) kodlarını çok daha kolay anlayıp D'ye çevirebilirim.

Yazdıklarınızı tamamen anladım sayılır. Ama tekrar tekrar okuyacağım sindirebilmek için.

Birde şu soruları soracağım:

void[] ve *void (belki de void*) ne işe yarar ?

zaten void değer dönmeyecek anlamı taşımıyor mu ? Onun nasıl bir dizisi olur ?
acehreli (Moderatör) #11
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:
Artık en çok istediğim ders göstergeler oldu.

Bundan sonraki ders o olacak.

Her ne kadar D'de göstergelerin eski önemi kalmasada, göstergeye destek tamamen kalkmadan göstergenin önemi kalkmayacak.

D'nin (ve başka dillerin de) avantajı, yeni başlayanların hiç gösterge kavramına bulaşmadan programlar yazabilmesi... Bir kere referans kavramını gösterge olmadan öğrenince, umarım göstergeler zaten anlaşılmış olacak.

C'de ise göstergeyi anlamadan ciddi program yazılamaz.

Ama tekrar tekrar okuyacağım sindirebilmek için.

Bu tür konulara daha fazla ihtiyacımız var. Kimse ders metni okuyarak öğrenemez. :) Böyle forumlar çok daha önemli. Onun için bol bol sor. :)

void[] ve *void (belki de void*) ne işe yarar ?

zaten void değer dönmeyecek anlamı taşımıyor mu ? Onun nasıl bir dizisi olur ?

void, tek başına olduğunca yalnızca dönüş türü olarak kullanılabilir. (Umarım başka bir istisnayı unutmuyorumdur.) Öyle olduğunda, senin de dediğin gibi, "hiçbir tür döndürmez" anlamına gelir.

void* ise, bambaşka bir anlama gelir: "herhangi bir türü gösterebilir" demektir. Bu türden olan bir değişken, herhangi türden bir değişkeni gösterebilir.

void*, C'de şarttır. Türden bağımsız algoritmalar yazarken gerekir. Örnek olarak: qsort. void*, nesneye yönelik dillerde o kadar önemli değildir; çünkü onlarda arayüzler (interface) kullanılabilir. Yani "herhangi bir tür" kadar genel bir ifade yerine, "herhangi bir hayvan" demek daha güvenli ve daha kullanışlıdır.

void*, herhangi bir türü gösterse de, daha sonradan asıl tür olarak kullanılırken, yine de mutlaka, asıl türe dönüştürülmek zorundadır. O yüzden, asıl türün ne olduğunu bir şekilde bilebilmemiz gerekir. Bazen bir enum değeri işe yarayabilir.

Aşağıdaki çok saçma bir örnek ama bir fikir verebilir. Derleyici void* türü konusunda fazla yardım getiremez. Herhangi bir türü göstermek istediğimizi bildiği için tür denetimi sağlayamaz. main'in içinde string türüyle ilgili bir hata var ama derleyici bunu göremez.

import std.stdio;
 
enum Tür
{
    tamsayı, kesirli
}
 
void main()
{
    void * gösterge;
 
    int i;
    gösterge = &i;
    kullan(gösterge, Tür.tamsayı);
    writeln(i);
 
    double d;
    gösterge = &d;
    kullan(gösterge, Tür.kesirli);
    writeln(d);
 
    // HATALI kullanım: string türüne karşılık Tür.tamsayı denmiş...
    string s;
    gösterge = &s;
    kullan(gösterge, Tür.tamsayı);
    writeln(s);
}
 
void kullan(void * veri, Tür tür)
{
    final switch(tür){
    case Tür.tamsayı:
        tamsayı_gibi_kullan(veri);
        break;
 
    case Tür.kesirli:
        kesirli_gibi_kullan(veri);
        break;
    }
}
 
void tamsayı_gibi_kullan(void * veri)
{
    int * asıl_tür_göstergesi = cast(int*)veri;
    *asıl_tür_göstergesi = 42;
}
 
void kesirli_gibi_kullan(void * veri)
{
    double * asıl_tür_göstergesi = cast(double*)veri;
    *asıl_tür_göstergesi = 1.25;
}

Ali
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:
Forum: Ders Arası RSS
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, 19:44:45 (UTC -08:00)