[Çözüldü] TStrings Tipinde Değer Döndüren Fonksiyon

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Lord_Ares
Üye
Mesajlar: 1070
Kayıt: 15 Eki 2006 04:33
Konum: Çorlu

[Çözüldü] TStrings Tipinde Değer Döndüren Fonksiyon

Mesaj gönderen Lord_Ares »

Merhaba arkadaşlar,
Bass library kullanarak mp3 çalar yapıyorum. Hazır verilmiş bir örnekten yola çıktığım bu projede seçtiğim klasör içindeki mp3 leri çalma listesine eklerken işin içinden çıkamadığım bir sorunla karşılaştım. Sorunum M3u.AddFile adında TStrings tipinde değer alan bir prosedür var. Bu prosedüre verdiğiniz bilgiyi çalma listesine ekliyor.
(Çalma listesi Listbox1 adlı bileşende tutuluyor. Listbox1.Style:=lbVirtual şeklinde. Aşağıdaki prosedür ile bilgiyi direk göndererek olmuyor, M3u.AddFiles prosedürüne göndermem mecburi)
Aşağıda seçtiğiniz klasördeki içindeki mp3leri, seçtiğiniz listboxa dosya yolu ve şarkı adıyla ekleyen prosedürüm var. Bu prosedürü TStrings tipinde değer döndüren bir fonksiyon haline getirip M3u.AddFiles (Mp3leri_Yükle); şeklinde kullanmak istiyorum.

Ek olarak bir soru : Çalma listesi 2000-3000 gibi şarkı olursa TStrings tipte bir değişken kullanmak doğru olur mu ? Eğer doğru değilse başka bir yol gösterirmisiniz.

Prosedürüm şu şekilde;

Kod: Tümünü seç

procedure Mp3leri_yukle(listele:TListBox; const PathName,FileName: string; const InDir: boolean );
var Rec  : TSearchRec;
    Path : string;
begin
Path := IncludeTrailingBackslash(PathName);
if FindFirst(Path + FileName, faAnyFile - faDirectory, Rec) = 0 then
 try
   repeat
     listele.Items.Add(Path + Rec.Name); //şarkının yolu ve adını yükle  
   until FindNext(Rec) <> 0;
 finally
   FindClose(Rec);
 end;
If not InDir then Exit;

if FindFirst(Path + '*.*', faDirectory, Rec) = 0 then
 try
   repeat
    if ((Rec.Attr and faDirectory) <> 0)  and (Rec.Name<>'.') and (Rec.Name<>'..') then
         Klasordeki_Mp3leri_yukle(listele, Path + Rec.Name, FileName, True);
   until FindNext(Rec) <> 0;
 finally
   FindClose(Rec);
 end;
end;


Bu şekilde Fonksiyon haline çevirmeye çalıştım olmadı. Kullanırken herhangi bir hata almadım ama bilgide gelmedi :D

Kod: Tümünü seç

function Mp3leri_yukle(const PathName,FileName: string; const InDir: boolean ):TStrings;
var Rec  : TSearchRec;
    Path : string;
    Cikti: TStrings;
begin
Cikti:=TStringList.Create;
Path := IncludeTrailingBackslash(PathName);
if FindFirst(Path + FileName, faAnyFile - faDirectory, Rec) = 0 then
 try
   repeat
     Cikti.Add(Path + Rec.Name); //şarkının yolu ve adını yükle
    //   Cikti.Add(Rec.Name);
   until FindNext(Rec) <> 0;
 finally
   FindClose(Rec);
 end;

If not InDir then Exit;

if FindFirst(Path + '*.*', faDirectory, Rec) = 0 then
 try
   repeat
    if ((Rec.Attr and faDirectory) <> 0)  and (Rec.Name<>'.') and (Rec.Name<>'..') then
         KMp3leri_yukle( Path + Rec.Name, FileName, True);
   until FindNext(Rec) <> 0;
 finally
   FindClose(Rec);
 end;
 Result:=Cikti;
 Cikti.Free;
end;

En son Lord_Ares tarafından 19 Nis 2015 02:48 tarihinde düzenlendi, toplamda 4 kere düzenlendi.
Kullanıcı avatarı
freeman35
Admin
Mesajlar: 2380
Kayıt: 12 Haz 2003 04:05
Konum: merkez camii yanı

Re: TStrings Tipinde Değer Döndüren Fonksiyon

Mesaj gönderen freeman35 »

TListBox.Items -> TStrings tir, ayrıca bir class a ihtiyaç var mı? TStringList ile TStrings farklı sınıflardır dikkat etmek lazım.
M3u.AddFiles (Mp3leri_Yükle); Bunun başına bir create ve altına freeandnil() eklemek 2 satıra gerek var, bu neden sıkıntı ?
ZAGOR TENAY TÜRK'tür... TÜRK kalacak...
Zoru başarırım, İmkansız zaman alır
FreeMan 35.5

Soru sormaya üşenmiyorsan, sorunun çözümünü yazmaya da üşenme !!!
Kullanıcı avatarı
mucahityagmur
Üye
Mesajlar: 10
Kayıt: 07 Şub 2015 01:47

Re: TStrings Tipinde Değer Döndüren Fonksiyon

Mesaj gönderen mucahityagmur »

Sence de tuhaflık yok mu ?

Kod: Tümünü seç

. . .
 Result:=Cikti;
 Cikti.Free;
. . .
Önce fonkisyonun Result değerini Cikti ile eşitliyorsun, hemen ardından Free ediyorsun.
Free etme-melisin.

Şöyle kullanmalısın.

Kod: Tümünü seç

var Lst : TStrings;
Begin
  Lst:=Mp3leri_yukle('E:\Music','laylaylom.mp3');
  Do_FalanFilan();
 // işin bitince free et
  Lst.Free;
end;
Lord_Ares
Üye
Mesajlar: 1070
Kayıt: 15 Eki 2006 04:33
Konum: Çorlu

Re: TStrings Tipinde Değer Döndüren Fonksiyon

Mesaj gönderen Lord_Ares »

Arkadaşlar verdiğiniz bilgiler için teşekkürler. Böyle bir fonksiyon oluşturamadığım için bende M3u adlı prosedürde değişiklik yaparak çözüme ulaştım.
Kullanıcı avatarı
freeman35
Admin
Mesajlar: 2380
Kayıt: 12 Haz 2003 04:05
Konum: merkez camii yanı

Re: [Çözüldü] TStrings Tipinde Değer Döndüren Fonksiyon

Mesaj gönderen freeman35 »

Yazmayı unutmuşum :S mucahityagmur un dediği doğru. Eşitle atama yapmak pointer ı yani memory aderesi ni eşitlemektir, değişkenin biri freelendiğinde, diğerleri ile erişmekte imkansız hale getirir. Çoğaltmak başka deyişle clone lamak istenirse, yukarıda ki örnekteki gibi, "assign" function kullanılmalıdır.
Kolay gele
ZAGOR TENAY TÜRK'tür... TÜRK kalacak...
Zoru başarırım, İmkansız zaman alır
FreeMan 35.5

Soru sormaya üşenmiyorsan, sorunun çözümünü yazmaya da üşenme !!!
Lord_Ares
Üye
Mesajlar: 1070
Kayıt: 15 Eki 2006 04:33
Konum: Çorlu

Re: [Çözüldü] TStrings Tipinde Değer Döndüren Fonksiyon

Mesaj gönderen Lord_Ares »

:D vallahi Tstrings tipinde değer döndüren bir fonksiyona büyük ihtimal ihtiyacım bitmedi. Neyle uğraşsam hep aynı tipte değer alıyor. Denediklerimde başaralı olamadım inşallah başarıcam :D
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: TStrings Tipinde Değer Döndüren Fonksiyon

Mesaj gönderen mrmarman »

Merhaba.

Function result olarak TStrings tipinde değer döndürmeye ihtiyacın olduğuna eminsen aşağıdaki şekilde kurabilirsin. Sadece merakını gidermek için hazırladım. Evet TStringList ile TStrings farklı sınıflardır. Bir detay eklemek lazım, diğer yandan TStringList de bir TStrings sınıfından türediğinden uyumludur. Zaten TStrings bir abstract class olduğundan öylece create edip kullanamayız. Onun için TStringList'e ihtiyaç duyulmuş olmalı diye değerlendiriyorum. Abstract class dediklerimiz ne işe yarar o zaman, işte TListBox, TMemo.Lines, vb. gibi liste içerikleri tutacak sınıflara yönelik, birbirine benzer ve uyumlu tasarlamak için uydurulmuştur.

Kod: Tümünü seç

  TStringList = class(TStrings)
  private
    FList: PStringItemList;
    FCount: Integer;
    ...
    ...
Ayrıca kodlarını da optimize ettim, biraz fazlalık vardı attım.

Kod: Tümünü seç

function DosyaListesi_01(const PathName, FileExt: string; const InDir: boolean ):TStrings;
var Rec      : TSearchRec;
    Path     : string;
begin
  Result := TStringList.Create;
  Path   := IncludeTrailingBackslash(PathName);
  if FindFirst(Path + '*.*', 183, Rec) = 0 then
  begin
    try
      repeat
        if    (Rec.Name <> '.' )
          AND (Rec.Name <> '..') then
        begin
          if ((Rec.Attr and faDirectory) <> 0) then
          begin // bir klasor demektir..
            if InDir then // alt dizinleri de kapsasın istenmişse...
            begin
              With DosyaListesi_01( Path + Rec.Name, FileExt, True) do
              begin
                Result.Add( Trim( Text ) );
                Free;
              end;
            end;
          end else
          begin // bir dosya demektir.
            if UpperCase(FileExt)  = UpperCase(ExtractFileExt(Rec.Name))
              then Result.Add(Path + Rec.Name); //şarkının yolu ve adını yükle
          end;
        end;
      until FindNext(Rec) <> 0;
    finally
      FindClose(Rec);
    end;
  end;
end;
Kullanımı :

Kod: Tümünü seç

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  With DosyaListesi_01( 'd:\ARMAN-Genel\Music\', '.MP3', True ) do
  begin
    Memo1.Lines.Text := Text;
    Free;
  end;
end;
Ama bunu procedure içinde parametre olarak kullanmak daha rasyonel, yere basan bir çözüm olacaktır.
Örnek :

Kod: Tümünü seç

procedure DosyaListesi_02(const PathName, FileExt: string; const InDir: boolean; UrunIcerik:TStrings );
var Rec      : TSearchRec;
    Path     : string;
begin
  Path   := IncludeTrailingBackslash(PathName);
  if FindFirst(Path + '*.*', 183, Rec) = 0 then
  begin
    try
      repeat
        if    (Rec.Name <> '.' )
          AND (Rec.Name <> '..') then
        begin
          if ((Rec.Attr and faDirectory) <> 0) then
          begin // bir klasor demektir..
            if InDir // alt dizinleri de kapsasın istenmişse...
              then DosyaListesi_02( Path + Rec.Name, FileExt, True, UrunIcerik);
          end else
          begin // bir dosya demektir.
            if UpperCase(FileExt)  = UpperCase(ExtractFileExt(Rec.Name))
              then UrunIcerik.Add(Path + Rec.Name); //şarkının yolu ve adını yükle
          end;
        end;
      until FindNext(Rec) <> 0;
    finally
      FindClose(Rec);
    end;
  end;
end;
Kullanımı :

Kod: Tümünü seç

procedure TForm1.BitBtn2Click(Sender: TObject);
begin
  DosyaListesi_02( 'd:\ARMAN-Genel\Music\', '.MP3', True, Memo1.Lines );
end;
Resim
Resim ....Resim
Lord_Ares
Üye
Mesajlar: 1070
Kayıt: 15 Eki 2006 04:33
Konum: Çorlu

Re: TStrings Tipinde Değer Döndüren Fonksiyon

Mesaj gönderen Lord_Ares »

Mrmarman hocam , emeğine ellerine sağlık. Yine birşeyler öğrendim sayenizde. Hocam zaten TStrings tipde çıktı veren fonksiyon yapmaya çalışmamın nedeni komponentteki prosedürün beni buna zorlaması oldu. Prosedürü her kullandığım yerde bir TStrings yaratıp yok etme kodu epey karıştırıyordu. Bir kez değil defalarca kullanınca epey dertti. Aksi taktirde bende yukarıdaki dosya arama prosedüründen dönen bilgiyi global bir değişkene çekip oradan da komponentin prosedürüne verecektim. Prosedür açıklaması şöyle m3u.AddFiles( Fileaddrs:TStrings ); Bu yüzden öyle bir fonksiyon istedim :D

Birşey daha danışmak isterim, bu dosya arama kodunda kendimce filtre kullanmak istedim. Aşağıdaki kodlamada küçük ve büyük harf sorunu yaşıyorum. Oysa filtre uygulamadan önce hepsini büyük harfe çeviriyorum fakat sonuç olumsuz. Şöyle ki ,
iskender ile İSKENDER adında iki dosyamız olsun.
(i) harfine göre filtre uyguladığımda sadece İSKENDER yani büyük (i) ile yazılmış olanları gösteriyor.Küçük harfle yazılmış olanlar sadece (Irmağın I sı) daki filtrelemede çıkıyor. Küçük i ve büyük i harfleriyle başlayanları bir arada göstermiyor. Acaba kodlamamda mı hata var diye gelen dosya adını ve aldığım harfi başka bir yerde karşılaştırdım sonuç doğru geldi. Sizce neden olabilir ne yapmalıyım
Teşekkürler

Filteleme için kullandığım kod

Kod: Tümünü seç

procedure Klasorleri_Yukle(LS:TStrings;StartDir: String; Harf:string;Filtre:boolean);
var
   SR: TSearchRec;
   IsFound, IsFound1: Boolean;
   dosya,gecici,dosya_adi: string;
   i: integer;
begin
   LS.Clear;
   if StartDir[length(StartDir)] <> '\' then
      StartDir := StartDir + '\';
   IsFound :=FindFirst(StartDir + '*.*', faDirectory, SR) = 0;
   while IsFound do
   begin
       if Filtre=True then begin //filtre var
                       if ((SR.Attr and faDirectory) <> 0) and (SR.Name[1] <> '.') then begin
                           dosya_adi:=UpperCase(sr.Name);
                           Harf  := UpperCase(Harf);
                           gecici:= AnsiLeftStr(dosya_adi,1);
                           if Harf<>'' then begin
                              if gecici=harf then begin
                                   LS.Add(SR.Name);
                                   dosya_adi:='';
                                   gecici:='';
                              end;
                           end;
                       end;
       end; //

       if Filtre=false then begin //filtre yok
                       if ((SR.Attr and faDirectory) <> 0) and (SR.Name[1] <> '.') then begin
                           LS.Add(SR.Name);
                       end;
       end;
   IsFound := FindNext(SR) = 0;
   end;
   FindClose(SR);
   Klasorun_Yeri:=StartDir;

end;
Kullanıcı avatarı
freeman35
Admin
Mesajlar: 2380
Kayıt: 12 Haz 2003 04:05
Konum: merkez camii yanı

Re: TStrings Tipinde Değer Döndüren Fonksiyon

Mesaj gönderen freeman35 »

Muhtemelen Unicode destekli delphi kullanıyorsundur, sorun Türkçe harflerden kaynaklanır, UpperCase yerine AnsiUpperCase i dene
Kolay gele
ZAGOR TENAY TÜRK'tür... TÜRK kalacak...
Zoru başarırım, İmkansız zaman alır
FreeMan 35.5

Soru sormaya üşenmiyorsan, sorunun çözümünü yazmaya da üşenme !!!
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: TStrings Tipinde Değer Döndüren Fonksiyon

Mesaj gönderen mrmarman »

UpperCase(sr.Name) olanı AnsiUppercase deneyebilirsin. Ama ben basit bir fonksiyonla kendim hallediyorum. Sana da öyle tavsiye ederim.

IĞÜŞİÖÇ karşılık ığüşiöç karakterletini küçük veya büyük yönde yer değiştiren bir fonksiyon yaz ve onu kullan bence. Özellikle dile özel davranış sergileme konusunda AnsiUppercase bile bir keresinde (detayını hatırlayamadım) beni zor durumda bırakmıştı.

Edit: Ben yazana kadar hocam da değindi zaten.
Resim
Resim ....Resim
Lord_Ares
Üye
Mesajlar: 1070
Kayıt: 15 Eki 2006 04:33
Konum: Çorlu

Re: TStrings Tipinde Değer Döndüren Fonksiyon

Mesaj gönderen Lord_Ares »

İkinizede çok teşekkürler üstadlar. Evet dediğiniz gibi kullanınca düzeldi.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: [Çözüldü] TStrings Tipinde Değer Döndüren Fonksiyon

Mesaj gönderen mrmarman »

Çözüldüğüne sevindim. Ben de şimdi otelime vardım, ilk işim AnsiUpperCase'in hangi durumda beni hayal kırıklığına uğrattığını ve kullanmayı bıraktığımı hatırladım. Basit bir örnek yetti.

Kod: Tümünü seç

ığüşiöç
içeriğinin AnsiUpperCase karşılığı

Kod: Tümünü seç

ıĞÜŞIÖÇ
yani büyük "I" ve "İ" harfi yok.

Kod: Tümünü seç

IĞÜŞİÖÇ
içeriğinin AnsiLowerCase karşılığında ise daha da dramatikleşiyor...

Kod: Tümünü seç

iğüşİöç
Testlerini yap ve teyit et lütfen. Çünkü kod büyüdükçe zorlaşıyor.

Bir de aşağıdaki fonksiyonu denersen farkı göreceksin.

Kod: Tümünü seç

function BuyukKucuk( strIcerik: String; boolUpper:boolean ): string;
Const
  strBuyuk = 'IĞÜŞİÖÇ';
  strKucuk = 'ığüşiöç';
Var
  i : Integer;
begin
  Result := strIcerik;
  for i := 1 to Length(strBuyuk) do
    if boolUpper // sadece Türkçe karakterler
      then Result := StringReplace( Result, strKucuk[i], strBuyuk[i], [rfReplaceAll] )
      else Result := StringReplace( Result, strBuyuk[i], strKucuk[i], [rfReplaceAll] );

  if boolUpper  // ve diğerleri...
  then Result := UpperCase( Result )
  else Result := LowerCase( Result );
end;
Kullanımı :

Kod: Tümünü seç

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  ShowMessage( BuyukKucuk( 'ığüşiöç' , True ) );
end;
Resim
Resim ....Resim
Lord_Ares
Üye
Mesajlar: 1070
Kayıt: 15 Eki 2006 04:33
Konum: Çorlu

Re: [Çözüldü] TStrings Tipinde Değer Döndüren Fonksiyon

Mesaj gönderen Lord_Ares »

Mrmarman hocam aynen dediğiniz gibi sonuç hüsran. Şöyle bir şey denedim ve açıkcası şaşırdım Edit1 içerisine küçük (i) harfi yazdım ve bunu Ansiuppercase ile bir değişkene atayım içindeki küçük veya büyük i ise bu harf i dir dedim ama o demedi :))) sizin fonksiyondan dönen değeride inceledim. Sanırım uppercase fonksiyonlarını kendimiz yazmamız daha doğru olacak

Kod: Tümünü seç

var
a:string;
begin
a:=AnsiUpperCase(Edit1.Text);
Edit2.Text:=a;
if (Edit2.Text='i') or (Edit2.Text='İ') then ShowMessage('bu harf i');
Cevapla