Forum: D Programlama Dili RSS
string türünden char[] dönüşüm
zafer #1
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: string türünden char[] dönüşüm
Merhaba,

Şu sıralar vibelog üzerinden kendime bir günlük oluşturmaya karar verdim. Ancak mevcut vibelog sürümünde hash işlemi yapan fonksiyonlar devre dışı kalacağı için bende karıştırma (hash) işlemleri için dauth isimli yeni bir paketi kurcalıyorum.

Anladığım kadarıyla metni karıştırmak için makeHash() isimli bir fonksiyon kullanılıyor ve bu fonksiyon Password türünde bir parametre alıyor. İşte benim sorunumda burada başlıyor. Çünkü Password türünü kurmak için char[] gerekiyor. Ancak char[] unicode karakterleri desteklemiyor.

Yani bu paketi kullanan bir sistemde "öküzgözü" şeklinde bir şifre kullanamıyorum. Benim sorum durum böyleyken benim Türkçe veya Çince karaktarler içeren bir şifre ile bu sistemi kullanmak için bir imkanım var mıdır? Umarım doğru anlatabilmişimdir.
https://github.com/zafer06 - depo
acehreli (Moderatör) #2
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4515 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
makeHash, Password türünde veri alıyormuş. Password da, ubyte dizisi üzerinde işliyormuş. Dolayısıyla, verinin türünden bağımsız olarak baytlar üzerinde işliyor; yani, her tür ile kullanılabilir. string'den ve char dizisinden Password oluşturmak için dupPassword işlevini görüyorum:

  https://github.com/Abscissa/DAuth/blob/master/src/dauth/co…

Denemeden şu kodun çalışacağını düşünüyorum:
    Password şifre = dupPassword("öküzgözü");
    auto karışık = makeHash(şifre);
char[] Unicode karakterlerini destekliyor çünkü zaten Unicode'un UTF-8 kodlamasından başka bir şey değil. Evet, o kodlama gereği bazı Unicode karakterleri birden fazla char üzerinde duruyorlar ama destekleme konusunda bir sorun yok.

Ali
Bu mesaj acehreli tarafından değiştirildi; zaman: 2016-12-09, 09:03.
zafer #3
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
dupPassword işlevini görmüştüm ama kopyalama (duplicate) çoğaltma gibi bir iş içindir diye çok dikkat etmemiştim. ubyte dizisinde ise program code -11 ile sonlanıyor. Sanırım bir şeyleri yanlış yaptım. Aşağıda bir örnek var.

string'den ve char dizisinden Password oluşturmak için dupPassword işlevini görüyorum:
Böyle yazmışsın ancak ben örneklerde char dizisi kullanımı için toPassword işleminin gerektiğini görüyorum. Zaten char dizisini dupPassword işlevi ile kullandığınmda şu hatayı alıyorum. "function dauth.core.dupPassword (string password) is not callable using argument types (char[])"

Ayrıca char türünün sadece ascii karaterleri içerdiğini sanıyordum. Eğer durum senin dediğin gibiyse o zaman char dizisi alan işlevide kullanabilirim ama nasıl ? Aşağıdaki örnek üzerinden yardımcı olur musun?

import std.stdio;
import dauth;
 
void main()
{
    writeln("================ İŞLEM SONUCU =======================");
 
    string sifre = "öküzgözü";
    char[] dizi = cast(char[]) "öküzgözü";
    ubyte[] veri = cast(ubyte[]) "öküzgözü";
 
    writeln("-->" ~ karistir(sifre));    // Çalışıyor
    writeln("-->" ~ karistir(dizi));     // Program exited with code -11
    writeln("-->" ~ karistir(veri));    // Program exited with code -11
}
 
string karistir(string sifre)
{
    Password password = dupPassword(sifre);
    return makeHash(password).toString();
}
 
string karistir(T)(T sifre)
{
    Password password = toPassword(sifre);
    return makeHash(password).toString();
}
https://github.com/zafer06 - depo
erdem (Moderatör) #4
Üye Tem 2009 tarihinden beri · 959 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
    writeln("-->" ~ karistir(dizi));

Ben de denemeden yazıyorum ama bu işlev bir dizge alıyorsa

    writeln("-->" ~ karistir(dizi.idup));

şeklinde çağrılması lazım.
acehreli (Moderatör) #5
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4515 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #3
zafer:
dupPassword işlevini görmüştüm ama kopyalama (duplicate) çoğaltma gibi bir iş içindir diye çok dikkat etmemiştim.

Kopyalamak için olduğu doğru çünkü string'in elemanları değiştirilemediğinden, string'le başladığımızda önce char[]'a dönüştürmek gerekiyor.

zafer:
char dizisi kullanımı için toPassword işleminin gerektiğini görüyorum. Zaten char dizisini dupPassword işlevi ile kullandığınmda şu hatayı alıyorum.

Şöyle düşünmek gerek: toPassword Password istiyor, Password ubyte[] istiyor (değişebilmesini gerektiriyor), char[]'ı ubyte[] gibi kullanmak için toPassword var (yaptığı tek şey, cast ile ubyte dizisi gibi kullanmak), ama string'i Password olarak kullanamayız çünkü değişmezdir. Onun için, string'le başlayınca dupPassword'u çağırıyoruz. O arka planda .dup ile char[] oluşturuyor, onu ubyte[] gibi kullanıyor, ve Password'a veriyor.

Ayrıca char türünün sadece ascii karaterleri içerdiğini sanıyordum.

char türü Unicode için hep kullanılıyor. Yalnızca ascii karakterlerden oluştuğunda, elemanlaraa rasgele eriştiğimizde karakterlere de erişmiş oluyoruz. Tek fark o.

    string sifre = "öküzgözü";
    char[] dizi = cast(char[]) "öküzgözü";
    ubyte[] veri = cast(ubyte[]) "öküzgözü";

O tür dönüşümlerinde tanımsız davranış var: "öküzgözü" gibi dizgi sabitleri değişmezdir. Onları char[] veya ubyte[] gibi kullandırdığımızda ve kullanan kod değişiklik yapabileceğine güvenip değiştirmeye yeltendiğinde hata oluşur. Örneğin, öyle dizgiler salt okunan bellekte bulunabilirler.

Eğer char dizisiyle denemek istiyorsan, gerçekten char[] dizisi oluşturmalısın. Eğer elimizde yalnızca "öküzgözü" gibi bir string varsa, Erdem'in dediği gibi .dup doğru çözüm. (Bu adamlar da dupPassword içinde ondan yararlanıyorlar zaten.)

Ali
zafer #6
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlar için çok teşekkürler.

Erdem, evet seninde yazdığın gibi .idup veya .dup kullanınca sorun çözüldü.

... toPassword Password istiyor,

Ali, eğer benim bir hatam yoksa, sanırım burada bir yazım yanlışı var. Password türünde değer isteyen toPassword değil makeHash() işlevi diye biliyorum. toPassword işlevi char veya ubyte dizisi ile çalışıyor. Bizden sonra okuyanların kafası karışmasın.

char türü Unicode için hep kullanılıyor. Yalnızca ascii karakterlerden oluştuğunda, elemanlaraa rasgele eriştiğimizde karakterlere de erişmiş oluyoruz. Tek fark o.
Peki o tek farkın bize etkisi nedir? (Konuyu ele alışını seviyoum, o sebeple bu konuyu biraz daha açmak istiyorum.)

O tür dönüşümlerinde tanımsız davranış var:
Aslında tüm sorunun kaynağı burası. Bu basit satırlar daha derin bilgi ve deneyim gerektiriyorlar. Mesela çift tırnak arasındaki string ifadenin DEĞİŞMEZ olduğu bilgisi gibi. Ayrıca değiştirilemez bir değeri değiştirmeyi amaçlıyorsak .dup gibi bir olanağı kullanmamız gerektiği bilgisi gibi. Tabi bunları deneyimlemek güzel şey :)

Kendi yaptığım çalışmalarda ben çevrim için cast yerine to! kullandım. Bu şekilde .dup olanağınada ihtiyaç kalmadan kullanılabiliyor. Sanırım to! işlevide arka planda bir .dup olanağı kullanıyor bilemiyorum. Ancak ubyte[] çevriminde şöyle bir hata alıyorum. Buna da bir anlam veremedim.

ubyte[] veri = to!(ubyte[])("öküzgözü");
std.conv.ConvException@/usr/include/dmd/phobos/std/conv.d(3390): Can't parse string: "[" is missing
https://github.com/zafer06 - depo
erdem (Moderatör) #7
Üye Tem 2009 tarihinden beri · 959 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Zafer D nin string türü aslında basitçe immutable char[] olmuş oluyor.
    ubyte[] veriler;
    veriler ~= 97;
    veriler ~= 32;
 
    veriler ~= 195;
    veriler ~= 167;
    veriler ~= 195;
    veriler ~= 135;
    
    string deneme = cast(immutable char[]) veriler;
    writeln(deneme);
erdem (Moderatör) #8
Üye Tem 2009 tarihinden beri · 959 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #6
zafer:
ubyte[] veri = to!(ubyte[])("öküzgözü");

Şu şekilde de deneyebilirsin:
    string öküzgözü = "öküzgözü";
 
    ubyte[] veri;
 
    foreach (char item; öküzgözü)
    {
        auto c = cast(ubyte) item;
        veri ~= c;
    }
 
    writeln(cast(immutable char[]) veri);
acehreli (Moderatör) #9
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4515 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #6
zafer:
sanırım burada bir yazım yanlışı var. Password türünde değer isteyen toPassword değil makeHash() işlevi

Evet, yanlış yazmışım. Düzeltme için teşekkürler. :)

elemanlaraa rasgele eriştiğimizde karakterlere de erişmiş oluyoruz. Tek fark o.

Peki o tek farkın bize etkisi nedir?

İşin doğrusu, dizgi karakterlerine rasgele erişmek çok nadir bir işlem. Karakterler genelde baştan sona işleniyorlar, Örneğin; ekrana yazdırmak, hepsini küçük harfe çevirmek, vs. işlemler hiç ilerideki karakterlere bakmak zorunda kalmıyorlar. O yüzden, Unicode için char dizisi kullanmakta bir sakınca yok. Rasgele erişim gerçekten gerektiğinde dchar dizisine dönüştürmek gerekebilir; olsun...

çevrim için cast yerine to! kullandım.

Zaten doğrusu da o. Ben de zamanla her dönüşüm için öncelikle to'nun kullanılması gerektiğini daha sonradan öğrendim. to hem güvenli (çünkü güvensiz dönüşümleri reddediyor) hem de hızlı (çünkü gereksiz bellek ayırmıyor). Hız örneği olarak, eğer bir string'i to!string ile yine string'e dönüştürürsak, hiç emek sarfetmeden aynı string'i döndürüyor. (string immutable karakterlerden oluştuğu için değişmesi olanaksız olduğundan kopyaları farklı olamaz. Bir sistem dili olduğundan bunu ihlal edebiliyoruz ve o zaman başımız belaya girebiliyor.)

Bu arada, bütün Phobos işlevlerinin kodları bilgisayarımızda açık olarak bulunduklarından ben merak ettiğim zaman to gibi işlevleri açıp bakıyorum. Tabii son halleri de şurada:

  https://github.com/dlang/phobos

ubyte[] çevriminde şöyle bir hata alıyorum.

O durumu dizgiden dizi oluşturma olarak algılıyor ve dizginin "[ 1, 2, 3 ]" gibi köşeli parantezler içermesini bekliyor. Bu, programcının "bana güven, aslında UTF-8 dizisi olan bu dizgiyi ubyte[] olarak kullanmak istiyorum" deme ihtiyacının bir örneği. Bu tür ihtiyacın aracı da cast oluyor. Ama yine dikkat: aslında immutable(ubyte)[] dizisine değiştirmek gerek. ;)

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:
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-10-23, 15:26:49 (UTC -07:00)