Forum: Ders Arası RSS
Yapı içinde dinamik dizi tanımlamak
Yapı içinde referans türü
zafer #1
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Yapı içinde dinamik dizi tanımlamak
Merhaba,

Benim küçük, kendi haline ve aşağıdaki adresdeki depoda bulunan deneysel bir rehber projem var. Bir süredir yoğunluktan yeni özellikler ekleyememiştim. Geçende aklıma takılan bir özelliği eklemeye karar verdim. Malum rehberin şu halinde kişi için açılan kayıtta sadece bir telefon numarası kaydı yapılabilmekte, oysaki kişilerin birden fazla telefonu olabilir. Bu vesile ile bende bir kişi kaydı için en fazla üç adet telefon numarası kaydı yapılmasını sağlayacak bir model geliştirmeye çalıştım. Ortaya çıkan örnek çalışma şöyle oldu.

import std.stdio;
import std.string;
 
struct Kayit
{
    string isim;
    string[] telefonNo;
}
 
void main()
{
    Kayit kay;
        
    write("Isim :");
    kay.isim = readln();
    kay.telefonNo = TelefonNumaralariAl(3);    
 
    
    writeln("Isim ->", kay.isim);
        writeln("TelefonNo[0] ->", kay.telefonNo[0]);
        writeln("TelefonNo[1] ->", kay.telefonNo[1]);
        writeln("TelefonNo[2] ->", kay.telefonNo[2]);
}
 
string[] TelefonNumaralariAl(int adet)
{
    string[] telefonlar;
    
    telefonlar.length = adet;
    
    string okunanTelefonNo;
    for (int i = 0; i < adet; ++i)
    {
        write("Bir telefon[", i+1 ,"] :");
        okunanTelefonNo = readln();
        
        if (okunanTelefonNo != "\n")
        {
            telefonlar[i] = chomp(okunanTelefonNo);
        }
        else
        {
            break;
        }
    }
    
    return telefonlar;
}

Burada Kayit isimli yapı içinde string[3] telefonNo isminde üç değer alabiilien tek boyutlu bir dizi tanımladım ve daha sonra string[] TelefonNumaralariAl() metodu içinde kullanıcıdan telefon numaralarını toplayıp bir dizi içine doldurup geri gönderdim ve bu diziyide Kayit yapısı içindeki gerçek yerine aktardım. Buraya kadar bir sıkıntım yok ama oldukça fazla uğraştım :)

Bu uğraşılarım arasında şöyle bir sorunla karşılaştım. kayıt içindeki diziyi dinamik dizi olarak tanımladığım zaman şöyle bir hata verdi.

import std.stdio;
import std.string;
 
struct Kayit
{
    string isim;
    string[] telefonNo;
}
 
void main()
{
    Kayit kay;
        
    write("Isim :");
    kay.isim = readln();
    
    string okunanTelefonNo;
    int say = 0;
    
    do
    {
        write("Bir telefon[", say + 1 ,"] :");
        okunanTelefonNo = readln();
        
        kay.telefonNo[say] = chomp(okunanTelefonNo);
        
        ++say;
    } while (okunanTelefonNo != "\n")
 
    
    writeln("Isim ->", kay.isim);
        writeln("TelefonNo[0] ->", kay.telefonNo[0]);
        writeln("TelefonNo[1] ->", kay.telefonNo[1]);
        writeln("TelefonNo[2] ->", kay.telefonNo[2]);
}

Bu kodu çalıştırdığım zaman aldığım hata ise şöyle oldu;

Isim :zafer
Bir telefon[1] :5449638574
core.exception.RangeError@main(25): Range violation
./main(onRangeError+0x28) [0x8091c48]
./main(_d_array_bounds+0x16) [0x808d816]
./main() [0x808b10a]
./main(_Dmain+0x92) [0x808a786]
./main(_D2rt6dmain24mainUiPPaZi7runMainMFZv+0x14) [0x808dc60]
./main(_D2rt6dmain24mainUiPPaZi7tryExecMFMDFZvZv+0x1d) [0x808d905]
./main(_D2rt6dmain24mainUiPPaZi6runAllMFZv+0x32) [0x808dca2]
./main(_D2rt6dmain24mainUiPPaZi7tryExecMFMDFZvZv+0x1d) [0x808d905]
./main(main+0x94) [0x808d8b4]
/lib/i686/cmov/libc.so.6(__libc_start_main+0xe6) [0xf75fdc76]
./main() [0x808a641]

Dinamik dizinin boyutunu bir yerlerde ayarlamam gerekiyor sanırım "core.exception.RangeError@main(25): Range violation" aldığımız hata onu gösteriyor ama konuyu tam anlayamadığım için buraya taşıdım hep beraber bakabilir miyiz?
https://github.com/zafer06 - depo
acehreli (Moderatör) #2
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ı
zafer:
kişi kaydı için en fazla üç adet telefon numarası kaydı yapılmasını sağlayacak

Üç olabilirse sonsuz da olabilir tabii ama bir yerde sınırlamak da gerekebilir. (Sonradan not: İkinci program zaten belirsiz sayıda numara okuyormuş.)

    string[] telefonNo;

Burada Kayit isimli yapı içinde string[3] telefonNo isminde

Belki daha önce öyle de denenmişti ama bu kodda telefonNo'nun türü string[]. string[3] olsa sabit uzunluklu dizi olurdu, string[] olunca dinamik dizi oluyor. Sabit uzunluklu dizilerin bir farkı, her zaman için belirtilen adet elemana sahip olmalarıdır.

Daha da önemlisi; string[3] değer türüdür, string[] ise referans türüdür. Değer türü ve referans türü farklarını daha ilerideki bir bölümde göstermişim:

  http://ddili.org/ders/d/deger_referans.html

Buraya kadar bir sıkıntım yok ama oldukça fazla uğraştım :)

Bende de doğru çalıştı. Diziler ve dilimler D'nin çok yararlı olanakları ama bazen karışık olabiliyorlar. Biraz teknik ayrıntılara da girer ama şöyle bir makale var:

  http://ddili.org/makale/d_dilimleri.html

Dilimlerin çok şaşırtıcı yanları olabiliyor. Bunlardan en önemlisi oradaki "Belirsizlik" başlığında var ve belki de seni uğraştıran da o "belirsiklik"ti. :)

Bu uğraşılarım arasında şöyle bir sorunla karşılaştım. kayıt içindeki diziyi dinamik dizi olarak tanımladığım zaman şöyle bir hata verdi.

    string[] telefonNo;
// ...
        kay.telefonNo[say] = chomp(okunanTelefonNo);

O satır hatalı çünkü telefonNo'nun başlangıçta hiçbir elemanı yok. Hangi elemanına erişmeye çalışırsak çalışalım hatalı olur. kay.telefonNo[say] = deyince "say numaralı elamanının değerini değiştir" demiş oluyoruz ama öyle bir eleman yok.

Aklıma üç seçenek geliyor. Ben ilkini yeğlerim:

1) telefonNo'nun sonuna eklemek:

        kay.telefonNo ~= chomp(okunanTelefonNo);

Böylece kendiliğinden, etkince, ve akıllıca büyür. (Büyüme algoritması yukarıdaki makalede açıklanıyor.) Büyümenin yeterince hızlı gelmediği nadir programlar için de Appender kullanılabilir. O da aynı makalede "Dilim Üyeleri ve Appender" başlığı altında geçiyor. Oradan da D.ershane'nin Aralıklar bölümüne bir bağlantı var:

  http://ddili.org/ders/d/araliklar.html

2) telefonNo'nun uzunluğunu belirleyerek yer bulunduğunu garantilemek:

        kay.telefonNo.length = say + 1;
        kay.telefonNo[say] = chomp(okunanTelefonNo);

Ama zaten birinci yöntemin yaptığı da bunun eşdeğeridir.

Birazcık daha etkin olmak istersek ve kaç numara geleceğini biliyorsak, yine birinci programdaki gibi .length'i en baştan tek seferde de belirleyebiliriz.

3) Eğer tasarım gerçekten 3 adet telefona izin veriyorsa diziyi baştan string[3] olarak tanımlamak:

    string[3] telefonNo;
// ...
        kay.telefonNo[say] = chomp(okunanTelefonNo);

Bu sefer de numaralar girilirken üçten fazla telefona izin verilmemesi gerekir yoksa yine core.exception.RangeError hatası atılır.

Ali
zafer #3
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
Belki daha önce öyle de denenmişti ama bu kodda telefonNo'nun türü string[]. string[3] olsa sabit uzunluklu dizi olurdu, string[] olunca dinamik dizi oluyor. Sabit uzunluklu dizilerin bir farkı, her zaman için belirtilen adet elemana sahip olmalarıdır.

Pardon Ali, yazım hatası bazen çok tehlikeli oluyor. Mümkün olduğunca yazılarımı kontrol ediyorum ama yoğunluktan buna bakamadım gözümden kaçmış birinci kod blokundaki yapıda telefonNo değişkeni string[] değil string[3] olmalıydı. Neyse sorun yok ben yazdıklarını anladım. Kusura bakma lütfen  :blush:


Bende de doğru çalıştı. Diziler ve dilimler D'nin çok yararlı olanakları ama bazen karışık olabiliyorlar. Biraz teknik ayrıntılara da girer ama şöyle bir makale var:

  http://ddili.org/makale/d_dilimleri.html

Dilimlerin çok şaşırtıcı yanları olabiliyor. Bunlardan en önemlisi oradaki "Belirsizlik" başlığında var ve belki de seni uğraştıran da o "belirsiklik"ti. :)

Bu makale harika ama aynı zamanda bayağı zor geldi. Yazıcıdan çıktısını aldım evde daha sakin bir ortamda tekrar incelemek için, vaktin olursa böyle güzel yazıları tekrar çevirmeni çok isterim. Emeğin için teşekkürler  ;-)
https://github.com/zafer06 - depo
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-18, 04:10:56 (UTC -08:00)