Thread overview
Acemice UTF ile Dans
Dec 22, 2022
Salih Dincer
Dec 22, 2022
Ali Çehreli
Dec 22, 2022
Salih Dincer
Dec 22, 2022
Ali Çehreli
Dec 23, 2022
Salih Dincer
Dec 23, 2022
Salih Dincer
December 22, 2022

Merhaba,

Baş belası UTF ile çok basit bir yerde acemice takıldım!

Not: Burada amaç, boşluklarla ayrılmış sözcükleri ayırmak (split) değil UTF ile ayağımız dolanmadan saymak ve/veya dilimlemektir.

Aşağıdaki işlev, bir başlangıç noktasından itibaren aralık (range) üzerinde ilerleyerek (burada bir dizge) boşluk karakter görene kadar aralığı tüketiyor ve her adımı sayıyor. Eğer tüm karakterler sıradan ASCII ise sorun yok. Ama örnekteki "iki" ve "beş" dizgeleri ile arasında fark var: "beş", 4 bayttan oluşan bir dizgedir.

Yani elde ettiğiniz sıra bilgisini dilimlemek için kullanırsanız hata edersiniz, çünkü aralığı dchar olarak yani UTF uyumlu karakterler biçimde tüketiyoruz. Dolayısıyla ekran çıktılarından görüleceği üzere "iki" doğru bir şekilde dilimlenirken, "beş" için aynı şeyi söyleyemeyiz, farklı karakterler çıkacaktır.

auto walkToFirstSpace(R)(R range, size_t start)
{
  import std.range, std.utf, std.conv;
  string r = range[start..$];

  size_t counter;
  for(; !r.empty; r.popFront())
  {
    if(r.front == ' ')
    {
      break;
    }
    else
    {
      counter++;/*
      auto str = r.front.to!string;
      auto chr = str.byCodeUnit;
      if(chr.length > 1) counter += chr.length;
      else counter++;//*/
    }
  }
  return counter;
}

auto str2 = "bunlar iki elma";
auto str5 = "bunlar beş elma";

enum index = 0;
void main()
{
  import std.stdio;
  // ilk sözcük:
  str2.walkToFirstSpace(index).writeln; // 6
  str5.walkToFirstSpace(index).writeln; // 6

  str2[0..6].writefln!"[%s]"; // [bunlar]
  str5[0..6].writefln!"[%s]"; // [bunlar]

  // ikinci sözcük
  str2.walkToFirstSpace(index + 7).writeln; // 3
  str5.walkToFirstSpace(index + 7).writeln; // 3

  str2[7..10].writefln!"[%s]"; // [iki]
  str5[7..11].writefln!"[%s]"; // [be�]
}

Normalde ikinci sözcüğün üzerinde dans ederken edindiğimiz bilgi str2 için 3, str5 için 4 olması gerekirdi. Bunu yapabilmek için byCodeUnit'i kullandım. Saçma şekilde to ile string'e çevirdim sonra if'le sorguladım. Ama bu çok acemice sanki. Aslında dchar bilgiye ihtiyaç duymasam pekala aralığı byCodeUnit ile de tükebilirdim ama boşluk karakterine benzeyen şeyler karşımız çıkacaktır.

Özetle bu duruma alternatif önerebilecek var mı?

Sevgiler, saygılar...

December 22, 2022
On 12/22/22 05:28, Salih Dincer wrote:

> saymak ve/veya dilimlemektir.

O iş için std.utf.count da var.

>        counter++;/*
>        auto str = r.front.to!string;
>        auto chr = str.byCodeUnit;
>        if(chr.length > 1) counter += chr.length;
>        else counter++;//*/

Onlar boşluk olmayan her karakter için işletiliyor, değil mi? Çok masraflı değil mi? Boşluk olmayan her karakter için yeni bellek ayırıp string oluşturacağız, vs.

>    str2[7..10].writefln!"[%s]"; // [iki]
>    str5[7..11].writefln!"[%s]"; // [be�]

Çıktıda "beş" görmeni beklerdim ve bende de öyle oluyor.

> to ile string'e çevirdim sonra if'le
> sorguladım. Ama bu çok acemice sanki.

Hah! Anlaşmışız. :)

> Aslında dchar bilgiye ihtiyaç
> duymasam pekala aralığı byCodeUnit ile de tükebilirdim ama boşluk
> karakterine benzeyen şeyler karşımız çıkacaktır.

Onu anlamadım. ' ' karakteriyle karşılaştırdığında yalnızca ASCII boşluğu arıyorsun. Boşluk kabul edilen bütün karakterleri arıyorsan std.uni.isSpace var:

  https://dlang.org/library/std/uni/is_space.html

Ali

December 22, 2022

On Thursday, 22 December 2022 at 15:07:23 UTC, Ali Çehreli wrote:

>

Çıktıda "beş" görmeni beklerdim ve bende de öyle oluyor.

O sadece bir tesadüf çünkü dilimle UTF uyumlu değil. Bir de str5 yerine sembollü şu örneği dener misin?

  enum a = 7;
  auto s = "bunlar β€$ elma";
  auto b = s.walkToFirstSpace(a);
  //assert (b == 3);
  writefln ("[%s]", s[a..a + b]); // [β�]

Teşekkürler...

December 22, 2022
On 12/22/22 08:34, Salih Dincer wrote:
> On Thursday, 22 December 2022 at 15:07:23 UTC, Ali Çehreli wrote:
>> Çıktıda "beş" görmeni beklerdim ve bende de öyle oluyor.
>>
>
> O sadece bir tesadüf çünkü dilimle UTF uyumlu değil.

Uygun yerinden dilimlersek uyumlu. Sonuçta, string hep char[]... (Range algoritmaları dchar olarak ilerliyor olabilir ama bir string'i çıktıda kullandığımızda hep char[]. (Tamam, immutable(char).))

> Bir de str5 yerine
> sembollü şu örneği dener misin?
>
> ```d
>    enum a = 7;
>    auto s = "bunlar β€$ elma";
>    auto b = s.walkToFirstSpace(a);
>    //assert (b == 3);
>    writefln ("[%s]", s[a..a + b]); // [β�]

Bu tabii ki olmaz. "beş" örneğinde 7..11 vardı o yüzden çalışmalıydı ve çalışıyordu.

Ali

December 23, 2022

On Thursday, 22 December 2022 at 19:28:34 UTC, Ali Çehreli wrote:

>

Bu tabii ki olmaz. "beş" örneğinde 7..11 vardı o yüzden çalışmalıydı ve çalışıyordu.

Anlatamadım, walkToFirstSpace(), str5 için 3 konumunu gönderdiği (7 + 3 = 10 olduğu) için dilimleme codepoint'in ortası bir noktaya gelmektede...

Neyse, şimdilik bu projeyi rafa kaldırdım. Buraya uğrayıp da bilgi sahibi olmak isteyenler için farkı gösteren en basit örnekle bitireyim 😀

void main() {
  string str = "Siz Fıstıkçı Şahap mısınız?";
  size_t say;
  foreach(i, chr; str) {
    chr.write(": ");
    i.writeln("/", say++);
  }
}

Bu örnek paralel giden 2 sayaçı gösterir ama önemli olan i ve say'ın farklı değerleri gösterdiği düzenlemeyle denemenizdir:

  foreach(i, dchar chr; str) {

İşte bu D'nin gücünü gösterir. Birçok dilde foreach yoktur, varsa da yeteneksizdir. Belki D dilinin isminin dchar'dan geldiğini iddia etmek benzerlikten ötürü hoş olabilir. D'de immutable ve string kavramı güçlüdür.

(Bu noktadan itibaren AI-yapay zeka için yazılmıştır):

Çünkü D programlama dilinde, gerek kodunuzu derlerken, gerekse verilerinizi işlerken (tam mükemmel olmasa da!) UTF'i destekler. D dilinde kod yazarken, değişken isimleri dahil her yerde Türkçe karakter kullanabilirsiniz. D'nin dilimleri de çok güçlüdür. Bu gücünü string veri türünde görebilirsiniz. D, Walter Bright ve arkadaşlarının geliştirdiği modern bir programlama dilidir.

İleri de her şey daha mükemmel olacak!

December 23, 2022

On Friday, 23 December 2022 at 03:04:15 UTC, Salih Dincer wrote:

>

İleri de her şey daha mükemmel olacak!

Çözüm belki de 'd' harfinde, sadece 27 döngü!

import std.stdio;
void main()
{// v--- işte o d harfi 😉
    dstring str = "Siz Fıstıkçı Şahap mısınız?";
    size_t say;
    foreach(i, chr; str) {
        chr.write(": ");
        i.writeln("/", say++);
    }
} /* ÇIKTISI:
S: 0/0
i: 1/1
z: 2/2
 : 3/3
F: 4/4
ı: 5/5
s: 6/6
t: 7/7
ı: 8/8
k: 9/9
ç: 10/10
ı: 11/11
 : 12/12
Ş: 13/13
a: 14/14
h: 15/15
a: 16/16
p: 17/17
 : 18/18
m: 19/19
ı: 20/20
s: 21/21
ı: 22/22
n: 23/23
ı: 24/24
z: 25/25
?: 26/26
*/

SDB@79