Thread overview
std.string indexOf
Mar 16, 2011
erdem
Mar 17, 2011
erdem
Mar 17, 2011
erdem
Mar 17, 2011
erdem
March 17, 2011

Wiki'nin std.string sayfasında (http://ddili.org/wiki/index.php?title=Std.string) bulunan örnek çalışma zamanı hatası veriyor:

import std.stdio;
import std.cstream;
import std.string;


void main()
{
   string dizgi = "Çay bahçesi";

   writeln ('"', dizgi, '"',
            " içinde hangi harfi arayayım? ");

   dchar harf;

   din.readf (&harf);

   int indeks = indexOf (dizgi, harf);

   if (indeks == -1) {
       writeln (harf, " harfi yok");

   } else {
       writeln ("Buldum! İndeksi ", indeks);
   }

}

Alıntı:

>

$ ./deneme
"Çay bahçesi" içinde hangi harfi arayayım?
a
Segmentation fault

**'wstring '**ya da 'dstring' kullansak da sonuç değişmiyor. Gene bu giriş akımının Enter tuşunu karakter olarak algılamasıyla alakalı olabilir mi acaba?

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 17, 2011

Gene bu konuyla alakalı olarak wikideki bir başka örnek:

import std.stdio;
import std.cstream;
import std.string;

void main()
{
   string [] kelimeler;

   kelimeler.length = 3;
   kelimeler [0] = "Boğaz";
   kelimeler [1] = "Köprüsü";
   kelimeler [3] = "Gişeleri";

   string birleşimleri = join (kelimeler, " ");

   writeln (birleşimleri);

}

Sanırım bu da 1 baytlık string üzerinde 2 baytlık karakterler kullanınca hata veriyor.

Alıntı:

>

$ ./deneme
core.exception.RangeError@deneme(14): Range violation

./deneme(onRangeError+0x28) [0x80b3a68]
./deneme(_d_array_bounds+0x16) [0x80a5cb6]
./deneme(_D6deneme7__arrayZ+0x12) [0x80a2f8e]
./deneme(_Dmain+0x83) [0x80a2267]
./deneme(_D2rt6dmain24mainUiPPaZi7runMainMFZv+0x1a) [0x80a5e16]
./deneme(_D2rt6dmain24mainUiPPaZi7tryExecMFMDFZvZv+0x20) [0x80a5da8]
./deneme(_D2rt6dmain24mainUiPPaZi6runAllMFZv+0x32) [0x80a5e5a]
./deneme(_D2rt6dmain24mainUiPPaZi7tryExecMFMDFZvZv+0x20) [0x80a5da8]
./deneme(main+0x94) [0x80a5d54]
/lib/libc.so.6(__libc_start_main+0xe6) [0xc49bc6]
./deneme() [0x80a2131]

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 17, 2011

Konuyu çok güzel bir zamanda açmışsın. :) Lütfen sabırla okuyunuz. Bu çok belalı bir konu. :/

Ben şu sıralarda D.ershane'deki bütün std.cstream'li örnekleri çıkartmakla meşgulüm. Şu anda Dizgiler dersini bitirmek üzereyim. O işi yaparken derslerin bazı yerlerini hem düzeltiyorum hem de yeni paragraflar ekliyorum.

  1. Gösterdiğin program dmd'nin veya Phobos'un bir hatasını sergiliyor. std.cstream, din, ve dout kullanan programlar için artık kafa yormamayı öneriyorum. İzninle onları bir kenara bırakalım.

  2. Girişten dchar okumak, şu kadar kolay olmalı:

   dchar c;
   readf(" %s", &c);

Ne yazık ki ilginç bir hata var: Giriş UTF-8 olduğunda örneğin ö'nün iki baytla temsil edildiğini biliyoruz. readf, o iki bayttan yalnızca ilkini okuyor, dchar'ın değeri yapıyor, ve dchar bambaşka bir karakteri temsil etmeye başlıyor.

Bununla ilgili bir hatayı daha dün açtım:

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

Yani "kod birimi" (code unit) okuyup onu "kod noktası" (code point) olarak kullanıyorlar.

(Not: Standart girişi tek kullananlar biziz galiba. İki seneye yakın D ile ilgileniyorum henüz giriş ve çıkışın tam doğru çalıştıklarını görmedim.)

  1. O hata nedeniyle şimdilik wchar veya dchar okuyamıyoruz. Zaten char okumak tamamen yanlış olur çünkü işimiz kod birimleri ile değil.

O yüzden bugün için satır okumaktan ve ilk karakterini kullanmaktan başka çaremiz yok. (Başka yöntemler de vardır ama bence bu yeterli.) Satır okuma ile de bir soru sormuş ve şu yanıtları almıştım:

http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=25635

O konudan anlaşıldığına göre, satır okunduğunda da satırın sonunda basılan Enter'ın kodu da girişte beliriyor. Eğer onu istemiyorsak satır sonundaki kodlardan kurtulmak için 'chomp''u, dizginin her iki ucundaki bütün boşluklardan kurtulmak için de 'strip''i kullanabiliriz. Bu programda boşluk karakteri de yasal olduğu için ben 'chomp''u kullanacağım.

import std.stdio;
import std.string;

void main()
{
   string dizgi = "Çay bahçesi";

   writeln ('"', dizgi, '"',
            " içinde hangi harfi arayayım? ");

   string harf = chomp(readln());

   /*
    * Burada hata aldım:
    *
    *     int indeks = indexOf (dizgi, harf);
    *
    *   Error: cannot implicitly convert expression
    *   (indexOf(dizgi,harf,cast(CaseSensitive)1)) of type
    *   long to int
    *
    * Hangi sürümü kullanıyorsun? Benimki 2.052
    *
    * auto veya long ile düzeliyor:
    */
   auto indeks = indexOf (dizgi, harf);

   if (indeks == -1) {
       writeln (harf, " harfi yok");

   } else {
       writeln ("Buldum! İndeksi ", indeks);
   }
}

Ama iki sorun var:

i) 'harf' aslında bir dizgi. Eğer onu tek harfle kısıtlamak istiyorsan uzunluğunun 1 olduğunu denetleyebilirsin. Ama string'in uzunluğu harfine göre değişik olur. ö için 2, a için 1... O yüzden okuduğumuz türün dstring olması gerekiyor:

   dstring harf = chomp(readln());

Derlenmez! Çünkü chomp'ün döndürdüğü tür string. İki çözüm var:

a) readln'e dstring okumasını söylemek. readln, ne türde okuyacağını bir şablon parametresi olarak alır. Deneyelim:

   dstring harf = chomp(readln!dstring());

Derlenmez! Çünkü iki farklı readln var: stdin'in üye işlevi olan ve serbest işlev olan. Ben yukarıda serbest işlevi kullanıyorum ve ne yazık ki o "şu türden olsun" olanağını sunmuyor. Peki, stdin'in üye işlevini çağıralım:

   dstring harf = chomp(stdin.readln!dstring());

b) Bence daha temizi, 'chomp''un döndürdüğü string'i dstring'e std.conv.dtext ile dönüştürmektir:

import std.conv;
// ...
   dstring harf = dtext(chomp(readln()));

Güzel... Şimdi artık dstring olarak okuduğumuz harf'in gerçekten tek harf olduğunu denetleyebiliriz. ö de olsa a da olsa dchar bütün Unicode karakterlerini taşıyabilir. Bu gibi denetlemeler için std.exception.enforce kullanılır.

Bugüne kadar hep assert kullandık ama kullanıcı ile ilgili konularda enforce doğru. Çok çok kısa olarak:

  • assert, programcının kendisini denetlemesi ile ilgili. Error atar ve Error'ın yakalanması önerilmez.

  • enforce, işlevlerin aldığı giriş değerleri gibi başka durumlarla ilgili. Exception atar; Exception yakalanabilir ve gerekirse durum kurtarılabilir

(O konuya daha fazla girmek istemiyorum. Parmaklarım ağrıdı ve daha girişten dizgi (aslında harf) okuyamadık. :p)

import std.exception;
// ...
   dstring harf = dtext(chomp(readln()));
   enforce(harf.length == 1, "Tek harf olmalı");

Daha bitmedi...

string ve wstring "harf" kavramını ifade etmeye uygun değiller. O yüzden programın bu haline a harfi verildiğinde çıktısı şöyle oluyor:

"Çay bahçesi" içinde hangi harfi arayayım?
a
Buldum! İndeksi 2

Eğer a'nın 1 indeksinde bulunmasını istiyorsak asıl dizgiyi de dstring seçmemiz gerekir.

İşte doğru çalışan program:

import std.stdio;
import std.string;
import std.conv;
import std.exception;

void main()
{
   dstring dizgi = "Çay bahçesi";

   writeln ('"', dizgi, '"',
            " içinde hangi harfi arayayım? ");

   dstring harf = dtext(chomp(readln()));
   enforce(harf.length == 1, "Tek harf olmalı");

   auto indeks = indexOf (dizgi, harf);

   if (indeks == -1) {
       writeln (harf, " harfi yok");

   } else {
       writeln ("Buldum! İndeksi ", indeks);
   }
}

Tabii açtığım hata giderildiğinde tek harf okumak çok daha kolay olacak.

Bu konuları D.ershane'ye de eklemeye başlamıştım. Yazdığım taslakları size de göstereceğim. Bakalım size mantıklı gelecek mi...

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 17, 2011

Neyse ki onun çözümü çok basit! :)

Alıntı (erdem):

>
kelimeler.length = 3;
kelimeler [0] = "Boğaz";
kelimeler [1] = "Köprüsü";
kelimeler [3] = "Gişeleri";

3 yasal bir indeks değil.

Ayrıca şöyle yazılsa daha basit herhalde:

   string[] kelimeler = [ "Boğaz", "Köprüsü", "Gişeleri" ];

Ama her durumda o kadar basit yazılamaz.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 18, 2011

Alıntı (acehreli):

>
  1. Girişten dchar okumak, şu kadar kolay olmalı:
>     dchar c;
>     readf(" %s", &c);
> ```

>
> Ne yazık ki ilginç bir hata var: Giriş UTF-8 olduğunda örneğin ö'nün iki baytla temsil edildiğini biliyoruz. readf, o iki bayttan yalnızca ilkini okuyor, dchar'ın değeri yapıyor, ve dchar bambaşka bir karakteri temsil etmeye başlıyor.
>
> Bununla ilgili bir hatayı daha dün açtım:
>
>   http://d.puremagic.com/issues/show_bug.cgi?id=5743
>

Hımm. Bu hatayı ilk kez görüyorum.

Alıntı (acehreli):
>
>
>
>

import std.stdio;
import std.string;

void main()
{
string dizgi = "Çay bahçesi";

writeln ('"', dizgi, '"',
         " içinde hangi harfi arayayım? ");

string harf = chomp(readln());

/*
 * Burada hata aldım:
 *
 *     int indeks = indexOf (dizgi, harf);
 *
 *   Error: cannot implicitly convert expression
 *   (indexOf(dizgi,harf,cast(CaseSensitive)1)) of type
 *   long to int
 *
 * Hangi sürümü kullanıyorsun? Benimki 2.052
 *
 * auto veya long ile düzeliyor:
 */
auto indeks = indexOf (dizgi, harf);
>

Aslında ben de dmd v2.052 sürümünü kullanıyorum. Ben direkt 'dmd 'program.d diye basitçe derliyorum.

Alıntı (acehreli):

>

b) Bence daha temizi, 'chomp''un döndürdüğü string'i dstring'e std.conv.dtext ile dönüştürmektir:

> import std.conv;
> // ...
>     dstring harf = dtext(chomp(readln()));
> ```

>

Bence de hem daha temiz hem basit :)

Dilin nasıl tasarlandığını ve işin teknik tarafını bilmiyorum ama aslında **wstring** ya da **dstring'**in **string** sınıfına benzer yöntemleri olsa ve örneğin **'indexOf'** parametre olarak kendisine bir **wstring** ya da **dstring** geçilse bile bir tamsayı döndürse daha mantıklı olmaz mı..

Ben ilk planda D'nin C++'nin karmaşıklığını azaltacağını düşünüyordum ama böyle giderse sanki daha karışık bir yazım biçimi olacak :) O yüzden Basic, Lua gibi dillerin neden popüler olduğunu anlıyorum.

-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
March 18, 2011

Alıntı (acehreli):

>

Neyse ki onun çözümü çok basit! :)

Alıntı (erdem):

>
kelimeler.length = 3;
kelimeler [0] = "Boğaz";
kelimeler [1] = "Köprüsü";
kelimeler [3] = "Gişeleri";

3 yasal bir indeks değil.

Evet. Bu basit hatayı görmemişim.

Programın kodlarını karakter karakter kopyalama huyumdan vazgeçsem çok iyi olacak galiba :)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 18, 2011

Alıntı (erdem):

>

Alıntı (acehreli):

>
> > import std.stdio;
> >     /*
> >      * Burada hata aldım:
> >      *
> >      *     int indeks = indexOf (dizgi, harf);
> >      *
> >      *   Error: cannot implicitly convert expression
> >      *   (indexOf(dizgi,harf,cast(CaseSensitive)1)) of type
> >      *   long to int
> >      *
> >      * Hangi sürümü kullanıyorsun? Benimki 2.052
> >      *
> >      * auto veya long ile düzeliyor:
> >      */
> >     auto indeks = indexOf (dizgi, harf);
> > ```

> >
>
> Aslında ben de dmd v2.052 sürümünü kullanıyorum. Ben direkt 'dmd 'program.d diye basitçe derliyorum.

Anlaşıldı: Ben -m64 seçeneği ile derliyormuşum. indexOf() sizediff_t diye bir tür döndürüyor. O tür de aslında 32 veya 64 olma durumuna göre ya int'in ya da long'un takma ismi oluyor.

auto yerine sizediff_t yazsak da oluyor yani.

Alıntı:
> Ben ilk planda D'nin C++'nin karmaşıklığını azaltacağını düşünüyordum ama böyle giderse sanki daha karışık bir yazım biçimi olacak :) O yüzden Basic, Lua gibi dillerin neden popüler olduğunu anlıyorum.
>

Katılıyorum. Karmaşıklığın bir bölümü işin doğasından geliyor: C gibi olabildiğince hızlı olmaları gerekiyor; yoksa "sistem dili" olarak kabul edilemez. Bir yandan da çok yararlı üst düzey kavramları destekliyorlar.

Örneğin Unicode çok karmaşık. D de o yüzden *birleştirici kod noktası* kavramına kadar desteklemiş ve gerisine karışmamış. O kısıtlama aslında biraz tesadüfi olmuş; çünkü g ve  ̆ şapkasının bileşiminin ğ'ye eşit olma kavramından baş D'cilerin haberi yokmuş. :D Öte yandan, programcılık açısından belki de ğ'nin g ve  ̆ şapkasına eşit olmasını istemiyor da olabiliriz.

Ne yapalım... :-/ Bence diğer dilleri de bilelim ve bilerek kullanalım.

Ali

-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]