Forum: D Programlama Dili RSS
Dosyadan bayt okumak
Sayfa:  1  2  sonraki 
zafer #1
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Dosyadan bayt okumak
Merhaba,

Bir mp3 dosyasını okuyup içindeki ID3 bilgilerini almak istiyorum. Ancak bir türlü dosyayı bayt olarak okuyup yapamadım.

http://en.wikipedia.org/wiki/ID3 bu adresteki bilgilerden anladığım kadarıyla bilgiler belli bir bayt düzeninde yerleştirilmiş ama D ile bu düzeni okumayı başaramadım hatta daha güzeli bu yapıyı birebir bir yapı (struct) içine aktarabilsem çok daha güzel olur.

Bu konuda yardım istiyorum??
https://github.com/zafer06 - depo
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ı
selamlar zafer

http://javamusictag.sourceforge.net/download.htm adresinde java icin bir kutuphane var. bu kutuphaneyi incelemeni tavsiye ederim.

ek olarak, dosyadan nasil byte okuruz diye #d kanalinda sordugumda soyle cevap verildi:

auto bytes = cast(byte[])std.file.read("test.d");
http://www.mengu.net - some kind of monster
acehreli (Moderatör) #3
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ı
std.file.read'in seçime bağlı ikinci parametresi de kaç bayt okunacağını belirliyormuş.

İki seçenek daha var: std.stdio.File.rawRead ve belki readf'i "%r" ile kullanmak. Sonuncuyu hiç denemedim ama writef'yin "%r" (raw) diye bir belirteç desteklediğini öğrendim. Belki readf'te de vardır. "%-r" küçük soncul (little endian) olarak, "%+r", büyük soncul (big endian), "%r" de platformun yerel sonculluğunu kullanıyormuş.

Ali
Avatar
Ronin #4
Üye Nis 2011 tarihinden beri · 39 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Şöyle birşey yaptım fakat ihtiyacı karşılamıyor.
import std.stdio;
import std.file;
import std.stream;
void main()
{
    char[21]  filename  = "BenzemezKimseSana.mp3";    
  if (exists(filename)!=0) {
    ulong size = getSize(filename);
    
    writefln("%r", cast(char[])read(filename,-128));
  } else {
    writefln("File not found. Please try again later :-)");
    /* File does not exist! */
  }    
}

Çıktısı da şu şekilde
I   D   3   ♥                   ☺   #   T   I   T   2               ¶
    B   e   n   z   e   m   e   z       K   i   m   s   e       S   a   n   a
T   R   C   K               ♣               1   /   1   2   T   L   E   N
                       2   1   8   0   2   7   T   A   L   B               ‼
           E   n       S   o   n       O   k   u   d   u   k   l   a   r   i   m
   T   P   E   1               ☼               M   u   z   e   y   y   e   n
   S   e   n   a   r   C   O   M   M
std.utf.UTFException@std\utf.d(644): Invalid UTF-8 sequence (at index 1)
47A6E8
47A55F
40462D
4051B7
404DB6
404C2F
4024AB
40213C
4020AE
4075B8
4075FC
4071F3
4DB26D
               e   n   g       M   U   Y   A   P   T   C   O   N               ☻
               1   T   Y   E   R               ♣               2   0   0   0
   7
C:\Users\workspace\d1\bin>
Adaletli olmak zor iş.
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ı
Önce önemsiz bir ayrıntı: :)

Ronin:
  if (exists(filename)!=0) {

exists() kendisi bir mantıksal ifade (bool) olduğundan, false ve true'nun 0 ve 1'e otomatik olarak dönüşme özelliğini kullanmak yerine yine mantıksal ifadede kalınabilir:

    if (!exists(filename)) {


    writefln("%r", cast(char[])read(filename,-128));
...
std.utf.UTFException@std\utf.d(644): Invalid UTF-8 sequence (at index 1)

Onun çalışmasını bekleyemeyiz, çünkü hatırlarsan char[], UTF-8 olarak kodlanmış dizgidir. İçinde yasal UTF-8 kodları bulunmayan dosyaya o biçimde davranamayız.

Zaten o yüzden read()'in dönüş değeri ubyte[]. O ubyte kendimiz ne anlama geldiklerine göre dönüştürebiliriz.

Örneğin mp3 dosyasının baş tarafını ifade eden bir yapı olsa:

    auto başlık = cast(Mp3Başlığı)baytlar;

Ama o durumda da soncullukla ilgili sorunlar olacaktır. O yüzden en hızlı yöntem olmasına karşın her ortamda doğru olmayabilir.

Ali
zafer #6
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Mengü, teşekkürler javadan çok anlamasamda adresteki kütüphaneyi inceledim. Daha öncede bu alanda çok bilinen   taglib (http://developer.kde.org/~wheeler/taglib.html) kütüphanesine bakmıştım. Hatta şu adresde D ile kullanım için proje geliştirilmiş. https://github.com/AndrejMitrovic/DTagLib Bunlar hazır kütüphane kullanmak isteyenler için güzel özellikleride var ama ben dosyayı kendim direk okumak istiyorum D ile belki sizlerde yardım ederseiniz küçük bir kütüphane hazırlayıp insanlığa hediye de edebiliriz tabi :)

Ronin, kodlar için teşekkürler, umarım bu desteğin devam eder. Hep beraber D kodu yazmak keyifli olur diye düşünüyorum.

Ali, mesajının sonunda bahsettiğin yapı şöyle bir şey olabilir mi;

struct TAGdata
{
    char tag[3];
    char title[30];
       char artist[30];
    char album[30];
    char year[4];
    char comment[30];
    int genre;
};

Aslında benimde yapmak istediğim dosyadan okudum bilgiyi bu yapı içine doldurmak, bunun için şöyle bir kod yazmaya çalıştım ama çalışmadı tabi;

import std.stdio;
import std.file;
 
struct TAGdata
{
    char tag[3];
    char title[30];
       char artist[30];
    char album[30];
    char year[4];
    char comment[30];
    int genre;
};
 
void main()
{
    string dosyaYolu = "Fading.mp3";
 
    TAGdata data = cast(TAGdata) read(dosyaYolu, 128);;
    
    writeln("Okunan : ", data.tag);
}

Bu kod derleme esnasında aşağıdaki hatayı veriyor;

Error: Error: cannot cast from void[] to TAGdata

Bu void[] nedir onuda anlamadım zaten, bu bilgiyi TAGdata yapısına çevirmeyide başaramadım. Arkadaşlar yardımmm!!

Not: Bu arada işlerim yoğunluğundan bir süre buraya uğrayamadım. Buradaki küçük ama sıcak ve samimi ortamı çok özlemişim, bunuda belirtmek isterim :)
https://github.com/zafer06 - depo
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ı
void[], türsüz baytlar anlamına geliyor. Yani en çiğ haliyle hiçbir tür bilgisi taşımayan veri.

void* ve void[] ile ilgili şu bölümler var ama tam bu dönüşümlerin oralarda olmadıklarını görüyorum.

"Her türü gösterebilen void*" başlığı altında:

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

void[] dilimleri ile ilgili olarak:

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

Ayrıca dizilerin .ptr niteliği ile ilk elemanın adresi elde edebiliyor.

Daha önceki koddaki sorun, ubyte[]'ın TAGdata'ya dönüştürülememesi idi. Biraz araştırınca void[] dizilerinin uzunluk doğru olduğu sürece başka her türün dizilerine dönüştürülebildiklerini öğrendim. O yüzden dosyadan bu aşamada TAGdata.sizeof kadar okumak önemli:

    void[] baytlar = read(dosyaYolu, TAGdata.sizeof);
    TAGdata data = (cast(TAGdata[])baytlar)[0];

Yukarıdaki kod void[] dizisinden tek elemanı bulunan bir TAGdata[] dizisine dönüştürüyor. Onun sıfırıncı elemanı da başlık bilgisini veriyor. (Belki Mengü bunun daha etkin bir yolunu çevrimiçi arkadaşlarından öğrenir. :))

Sonuçta şu çalışıyor:

import std.stdio;
import std.file;
 
struct TAGdata
{
    char tag[3];
    char title[30];
    char artist[30];
    char album[30];
    char year[4];
    char comment[30];
    int genre;
};
 
void dosyayi_olustur(string dosyaYolu)
{
    auto dosya = File(dosyaYolu, "w");
 
    ubyte[1000] baytlar = 'a';
 
    dosya.rawWrite(baytlar);
}
 
void main()
{
    string dosyaYolu = "deneme_dosyasi.mp3";
 
    dosyayi_olustur(dosyaYolu);
 
    void[] baytlar = read(dosyaYolu, TAGdata.sizeof);
    TAGdata data = (cast(TAGdata[])baytlar)[0];
 
    writeln("Okunan : ", data.tag);
}

Ama bunun önemli sorunları var. Yukarıdaki TAGdata, ID3v1'i gösteriyor. O biçimde okumak için dosyanın gerçekten de o düzeni içerdiğini önceden bilmek gerekir. O düzendeki char[] dizileri ISO-8859-1 kodları taşıyorlarmış. Yani onların içindeki ASCII dışındaki ilk karakter Ronin'in karşılaştığı hatayı oluşturacaktır.

Daha sonraki ID3 düzenleri UTF-16 çeşitlerini destekliyorlarmış. O zaman ya wchar[] kullanılmalı, ya da başka bir yolla okunmalı. Zaten yukarıda da dediğim gibi, baytları önceden biliyormuş gibi cast(TAGdata) ile dönüştürmek doğru değil.

Kaynaklar:

http://en.wikipedia.org/wiki/ID3

http://www.id3.org/id3v2.4.0-structure

Dosyanın başında hangi ID3 düzeni bulunduğu id3.org'un sayfasında görülüyor. Şunun gibi ilginç bilgiler var:

An ID3v2 tag can be detected with the following pattern:
     $49 44 33 yy yy xx zz zz zz zz
   Where yy is less than $FF, xx is the 'flags' byte and zz is less than
   $80.

ID3v2 olduğunu anlamak için ilk üç baytın "ID3" (0x49, 0x44, 0x33) olmalarından başka, yy'ler 0xff olamıyorlar, xx bayrak baytının kurallarına uymalı (son dört biti sıfır), ve zz'lerin en üst bitleri 0.

Mengü'nün gösterdiği Java kodlarına bakmadım ama bence baytlarımızı teker teker okuyarak hangi ID3 düzeni bulunduğuna karar verip o düzeni ifade eden bir nesne döndürmeliyiz:

ID3v1 ID3v1_oku(ubyte[] baytlar);
ID3v2 ID3v2_oku(ubyte[] baytlar);
// ... 

Baytlara ilk bakan kod hangi düzen olduğunu anlayıp o işlevi çağırır.

Şimdilik bu kadar. :) (Çünkü aslında bilgiVer() gibi bir işlevi bulunan bir sınıf arayüzü daha uygun olabilir. Yani yukarıdaki ID3v1, ID3v2 gibi türler o arayüzü gerçekleştiren alt sınıflar olabilirler.)

Ali
zafer #8
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Malesef olmadı :(

Yazdığın kodları denemek için önce bir mp3 dosyasının diğer tüm bilgilerini silip sadece ID3v1 bilgilerini tanımladım. Bu işlemi winamp ile yaptım. Ardından eklediğin kodları kullanarak Id3v1 bilgisini okumaya çalıştım. Bu arada bu bilgiler tamamen ASCII karakterleri içeriyor. Buna rağmen düzgün bir çıktı elde edemedim.

Ayrıca mp3tag isimli program ile dosyayı kontrol ettiğimde ID3v1 bilgisini düzgün bir şekilde görebiliyorum.

Bir diğer konu daha önce bu konu ile ilgili bir C++ kodu yazmışım ve o kod dorunsuz çalışıyor. D ile neden bu kadar zorlandık anlamıyorum. Yardımları bekliyorum.İlgili C++ kodunuda aşağıya ekliyorum.

#include <iostream>
#include <fstream>
 
#define ETIKET_BOYUT 128
 
using namespace std;
 
struct ETIKETLER
{
    char baslik[31];        // title
    char sanatci[31];        // artist
    char album[31];            // album
    char yil[5];            // year
    char mesaj[31];            // comment
    char bos;                // zero
};
 
int main()
{
    ETIKETLER etiketPaketi;
    ifstream mp3Dosya("D:\\test.mp3", ios::binary);
    char etiketKontrol[4] = {0};
 
    memset(&etiketPaketi, 0, sizeof(etiketPaketi));
 
    char *tampon = new char[ETIKET_BOYUT + 1];
 
    mp3Dosya.seekg(-ETIKET_BOYUT, ios::end);
    mp3Dosya.read(tampon, ETIKET_BOYUT);
 
    strncpy(etiketKontrol, tampon, 3);
 
    if (strcmp(etiketKontrol, "TAG") == 0)
    {
        strncpy(etiketPaketi.baslik, tampon + 3, 30);
        strncpy(etiketPaketi.sanatci, tampon + 33, 30);
        strncpy(etiketPaketi.album, tampon + 63, 30);
        strncpy(etiketPaketi.yil, tampon + 93, 4);
        strncpy(etiketPaketi.mesaj, tampon + 97, 28);
 
        // Etiket bilgilerini ekrana yaz.
        //EtiketBilgisiYaz(etiketPaketi);
    }
 
    return 0;
}
https://github.com/zafer06 - depo
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ı
Ben ID3v1 düzeninin dosyanın sonunda olduğunu anlamamışım. Baktığım site ID3v2.4.0'ı gösteriyordu. Zafer'in C++ programından öğrendim ve şu sayfadaki "ID3v1/ID3v1.1 test suite" ile denedim:

  http://www.id3.org/Developer_Information

Yalnızca başlığı yazdırıyor ama oldu:

import std.stdio;
import std.string;
import std.exception;
import std.conv;
 
struct ID3v1Pakedi
{
    char[3]  TAG;           // "TAG" belirteci
    char[30] başlık;        // title
    char[30] sanatçı;       // artist
    char[30] albüm;         // album
    char[4]  yıl;           // year
    char[30] mesaj;         // comment
    char[1]  tarz;          // genre
 
    string toString() const
    {
        return to!string(başlık);
    }
 
    static ID3v1Pakedi oku(File dosya)
    {
        scope(exit) dosya.seek(dosya.tell(), SEEK_SET);
        dosya.seek(-ID3v1Pakedi.sizeof, SEEK_END);
 
        ID3v1Pakedi[1] paketler;
        dosya.rawRead(paketler);
 
        ID3v1Pakedi paket = paketler[0];
 
        enforce(paket.TAG == "TAG",
                format("'%s', bir ID3v1 dosyası değil!", dosya.name()));
 
        return paket;
    }
}
 
int main(string[] args)
{
    if (args.length < 2) {
        stderr.writefln("Kullanım: %s dosya1.mp3 [dosya2.mp3 [...]]", args[0]);
        return 1;
    }
 
    foreach (dosyaİsmi; args[1..$]) {
        auto etiketPakedi = ID3v1Pakedi.oku(File(args[1], "r"));
        writeln(etiketPakedi);
    }
 
    return 0;
}

Notlar:

  • oku(), akıllı bir işlev olarak kendisine verilen dosyanın başlangıçtaki yerini scope(exit) ile garantiliyor. dosya.seek() yaparak okuma yerini bozmadan hemen önce "buradan nasıl çıkarsak çıkalım şu temizlik işlemini yap" demiş oluyor. D'nin en güçlü olanaklarından birisi! C++'ta olsa bir RAII sınıfı yazmak zorunda kalırdık veya daha da belalısı olarak try-catch yazmak zorunda kalırdık.

  • oku()'yu çağıranların bu dosyanın kesinlikle bir ID3v1 dosyası olduğunu bilmeleri gerekiyor. Yoksa oku() enforce() ile bir hata atıyor. Daha temizi, ID3v1Pakedi.oku()'yu başka bir işlevin çağırması olur. Bu işlev önce hangi düzende olduğunu anlar ve ondan sonra doğru oku() işlevini çağırır.

Ali
acehreli (Moderatör) #10
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ı
acehreli:
oku(), akıllı bir işlev olarak kendisine verilen dosyanın başlangıçtaki yerini scope(exit) ile garantiliyor.

Öyle olsun istiyor ama programcı hatası var! :( scope(exit)'in ifadeleri bu kapsamdan çıkılırken işletileceği için seek.tell()'i çıkarken çağırmak geç olur. Onun başlangıçtaki değerini saklamamız gerekir:

        immutable dosyaYeri = dosya.tell();    // <-- değişkende sakla
        scope(exit) dosya.seek(dosyaYeri, SEEK_SET);
        dosya.seek(-ID3v1Pakedi.sizeof, SEEK_END);

Ali
zafer #11
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Ali merhaba, üzülerek söylemek isterim ki kodu yine çalıştıramadım :( Senin yazdığın kodun aynısını kopyaladım ve çalıştırmak istediğimde şu hatayı aldım.

std.conv.ConvOverflowException@std\conv.d(1302): Conversion positive overflow
C:\Users\Zafer\Documents\Projects\Etiket\Etiket\main.d(44): _Dmain
Press any key to continue . . .

Kullandığım sürüm 2.057 ve Windows sistemi üzerinde MonoDevelop ile çalışıyorum. Komut satırı üzerinden derlemeye çalıştığımda aşağıdaki hatayı alıyorum.

C:\Users\Zafer\Documents\Projects\Etiket\Etiket>dmd
DMD32 D Compiler v2.057
Copyright (c) 1999-2011 by Digital Mars written by Walter Bright
Documentation: http://www.digitalmars.com/d/2.0/index.html

C:\Users\Zafer\Documents\Projects\Etiket\Etiket>dmd -w main.d

C:\Users\Zafer\Documents\Projects\Etiket\Etiket>main
std.conv.ConvOverflowException@std\conv.d(1302): Conversion positive overflow
423F30
423DA7
4021BE
403ADC
403B20
403717
4BCBE1

C:\Users\Zafer\Documents\Projects\Etiket\Etiket>

Ayrıca scope() sayesinde Hata Atma ve Yakalama (http://ddili.org/ders/d/hatalar.html) bölümünü tekrar bir gözden geçirdim. Doğrusu çokta iyi oldu hem bilgilerimi tazeledim hemde biraz daha pekiştirdim.

Scope() oldukça kullanışlıymış daha önce dikkat etmeden geçmişim sanırım, try-catch kısmını okuyup devamını atlamışım sanırım. Özellikle bazen try blogunda tanımlı değişkenlere catch veya finally bloklarında ulaşamadığım zamanlarda sorun olurdu ama scope() bu işe gerçekten güzel bir çözüm bulmuş.

Benim o yazıda aklıma takılan sadece scope()'un yaşam alanı oldu. Yani örnekte bir metod verilmiş ve o metodun çıkışında scope() çalıştırılmış ama örneğin o metod içinde iç içe geçmiş yapılar varsa, örnegin if-else veya for döngüsü gibi bunların içindede yaşayıp sonlanan scope tanımları yapılabilir mi?

D dilinde gerçekten güzel ve kullanışlı yapılar var ve bunlarıda güzel bir araya getirmişler, umarım ilgilenen arkadaşlar çoğalır ve D dilini hep beraber daha detaylı irdeleriz.
https://github.com/zafer06 - depo
acehreli (Moderatör) #12
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:
std.conv.ConvOverflowException@std\conv.d(1302): Conversion positive overflow
C:\Users\Zafer\Documents\Projects\Etiket\Etiket\main.d(44): _Dmain
Press any key to continue . . .

conv.d'yi açıp hatanın yerini buldum. O hatayı atan işlevin tamamını kopyalıyorum (bu galiba 2.057'den daha eski ama olsun) :

T toImpl(T, S)(S value)
    if (!isImplicitlyConvertible!(S, T) &&
        (isNumeric!S || isSomeChar!S) &&
        (isNumeric!T || isSomeChar!T))
{
    enum sSmallest = mostNegative!S;
    enum tSmallest = mostNegative!T;
    static if (sSmallest < 0)
    {
        // possible underflow converting from a signed
        static if (tSmallest == 0)
        {
            immutable good = value >= 0;
        }
        else
        {
            static assert(tSmallest < 0);
            immutable good = value >= tSmallest;
        }
        if (!good)
            throw new ConvOverflowException("Conversion negative overflow");
    }
    static if (S.max > T.max)
    {
        // possible overflow
        if (value > T.max)
            throw new ConvOverflowException("Conversion positive overflow");
    }
    return cast(T) value;
}

Yani dönüştürülmekte olan değerin hedef türün en büyük değerinden büyük olduğunu farkediyorlar. Bizim kodda yalnızca to!string var ama stdio.d'nin içine baktığımda seek()'in içinde de to!int(offset) görüyorum. O daha şüpheli çünkü offset bir long. Eğer değeri int.max'tan büyükse sorun oradadır.

Ek: Aşağıda yazdıklarımı unut. -m32 seçeneği ile derleyince ben de hata görüyorum ama başka türlü... Zaman bulunca daha ayrıntılı bakacağım.

Hatayı ben yaşamadığım için bu noktada senin tarafında debugging gerekiyor. writeln satırları serpiştirerek hatanın tam olarak hangi işlem sırasında atıldığını yakalayabilir misin.

Rastgele öneri: 'tarz' üyesi tek karakterden oluşuyor ama aslında string'e dönüştürülemez çünkü sonunda '\0' için yer yok. 'tarz' kullanım açısından olsa olsa bir int'tir. Hangi müzik tarzında olduğunu kod olarak saklıyor. Acaba onu mu to!string yapınca oluyor?


Benim o yazıda aklıma takılan sadece scope()'un yaşam alanı oldu. Yani örnekte bir metod verilmiş ve o metodun çıkışında scope() çalıştırılmış ama örneğin o metod içinde iç içe geçmiş yapılar varsa, örnegin if-else veya for döngüsü gibi bunların içindede yaşayıp sonlanan scope tanımları yapılabilir mi?

Sonra deneriz ama scope()'un öyle kısıtlamaları olduğundan haberim yok.

D dilinde gerçekten güzel ve kullanışlı yapılar var ve bunlarıda güzel bir araya getirmişler, umarım ilgilenen arkadaşlar çoğalır ve D dilini hep beraber daha detaylı irdeleriz.

Şimdilik bu kadar, :)
Ali
acehreli (Moderatör) #13
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ı
İşaretli/işaretsiz int konusuna bağlı olan bir programcı (yani Ali :-p) hatası bu. :( .sizeof'un türü size_t (işaretsiz) olduğundan onun eksi işaretlisi de çok büyük bir tamsayı oluyor. Önce işaretli bir tür olan sizediff_t'ye dönüştürünce bende çalıştı:

        dosya.seek(-cast(sizediff_t)ID3v1Pakedi.sizeof, SEEK_END);

Aslında cast(int) de çalışır tabii çünkü ID3v1Pakedi'nin büyüklüğü 128 gibi küçük bir değer.

Ben bunları 64-bitlik dmd ile hem -m32 hem de -m64 ile denedim. Sanıyorum hata oydu; bence Windows'da da çalışacaktır.

Ali
acehreli (Moderatör) #14
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ı
Yanıtlanan mesaj #11
zafer:
Benim o yazıda aklıma takılan sadece scope()'un yaşam alanı oldu. Yani örnekte bir metod verilmiş ve o metodun çıkışında scope() çalıştırılmış ama örneğin o metod içinde iç içe geçmiş yapılar varsa, örnegin if-else veya for döngüsü gibi bunların içindede yaşayıp sonlanan scope tanımları yapılabilir mi?

Soru için teşekkürler. Benim de tekrar etmeme neden oldun. :) scope deyimleri içinde bulundukları en iç kapsamla ilgili. (Bu bilgiyi eklemem gerek.) O yüzden isim alanı karmaşaları da yaşanmıyor.

Şöyle denedim:

import std.stdio;
 
void foo()
{
    writeln("foo() ilk satır");
 
    int dış;
    scope (exit) {
        --dış;
        writeln("dış scope(exit): ", dış);
    }
    ++dış;
 
    if (dış) {
        writeln("if ilk satır");
 
        int iç;
        scope (exit) {
            --iç;
            writeln("iç scope(exit): ", iç);
        }
        ++iç;
 
        writeln("if son satır");
    }
 
    writeln("foo() son satır");
}
 
void main()
{
    foo();
}

Çıktısı:

foo() ilk satır
if ilk satır
if son satır
iç scope(exit): 0
foo() son satır
dış scope(exit): 0


D dilinde gerçekten güzel ve kullanışlı yapılar var ve bunlarıda güzel bir araya getirmişler, umarım ilgilenen arkadaşlar çoğalır ve D dilini hep beraber daha detaylı irdeleriz.

Doğru. scope deyimleri Andrei Alexandrescu'nun özenle hatırlattığı bir konudur. D'nin en yararlı tarafları arasında bir de 'static if'i öne sürer. Tabii bunların ikisi de kendisinin C++ sihirbazlığı yaptığı zamanlarında acı çektiği konulardır. :)

Ali
acehreli (Moderatör) #15
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ı
Yanıtlanan mesaj #13
acehreli:
        dosya.seek(-cast(sizediff_t)ID3v1Pakedi.sizeof, SEEK_END);

Bu günlerde çok hata yapıyorum! :( Neden sizediff_t'ye dönüştürülsün ki? seek()'in belgesi 'long' türünde parametre diyor. Doğrusu, long vermektir:

        dosya.seek(-cast(long)ID3v1Pakedi.sizeof, SEEK_END);

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:
Sayfa:  1  2  sonraki 
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:41:19 (UTC -08:00)