Volkan Atasever

mühendislik, edebiyat, retro computer, yazılım, şiir, nümismatik, bilişim, podcast ve daha bir çok yazılarım...

Multithreading Programlama

clock Aralık 6, 2006 07:52 by author Volkan Atasever

       Multithreading programlamaya ve kodlara girmeden önce bu makalemde multitasking ve multithreading’in ne anlama geldiğini ve prensiplerini anlatmaya çalışacağım.
         PC’ler ilk çıktığında multitasking işletim sistemlerine sahip değildiler. Bu bir programı çalıştırmak için ilk önce çalışan programı kapatıp, çalıştırmak istediğiniz programı açmak anlamına geliyordu. Zaman kaybı olduğu gibi verimde de büyük düşüşler yaşanıyordu.
         Multitasking Türkçe ifadesiyle çok işlemli anlamına gelmektedir. İşlemler zamanı paylaşır ve bir işlemin bittiği yerde diğeri başlar bunun için 20ms gibi bir süreçte bu işler olur. Diğer işlemde 20ms çalışır ve tekrar yine diğer işleme geçilir. Win32 sistemlerde 20ms belirlenmiştir bu süre quanta süresi olarak adlandırılmıştır. Bu çok işlemli sisteme(Multi Processing) Multitasking sistemler denir.
         Bizim inceleceğimiz konu ise bir işlemdeki parçacıklardır.Burada da aynı işlemlerin zaman paylaşımında olduğu gibi işlemdeki parçacıklar kendi aralarında bir zaman paylaşımı oluştururlar.
         Multi Thread sayesinde aynı anda bir uygulamada birden fazla işlem yapabilmekteyiz. Multi Processing’in, process seviyesine indirilmiş bir özeliği gibi düşünebilirsiniz. Böylece uygulamalarımız daha stabil, kararlı ve bazı durumlarda performans da artış da getirmektedir.
         VB.NET ile multi thread yapmamız için bize gereken sadece System.Threading namespace’idir.

         Dim parcacik as Thread
         parcacik = new Thread(new ThreadStart(AddressOf fonksiyon))

         Thread sınıfından parcacik isimli bir nesne oluştuyor ardından bir alt satırda ThreadStart isminde delegate türünden nesnemizi parametre olarak veriyoruz. Bu delegeyede parametre olarak fonksiyon isimli fonksiyonumuzun başlangıç adresini gönderiyoruz.
         Kanalımızı çalıştırmak için ise;
         Dim instance As Thread
         instance.Start()
         Start metodunu kullanmalıyız.
         Çalışan kanalı sonlandırmak için;

         Dim instance As Thread
         instance.Abort()
         Abort Metodunu kullanmalıyız.
         Diğer önemli metodlar ise Suspend() , Resume() ve Sleep() metodlarıdır.
         Public Sub Suspend()
         Public Sub Resume()
         Sleep metodu ise kanalımızı belirlenen süre içerisinde çalışmasını yarıda keser.Metod, integer tipinde parametre alır ve bu tamsayıyı milisaniye cinsinden değerlendirir.

         Public Shared Sub Sleep ( _
                   millisecondsTimeout As Integer _
         )

         Bazı önemli özellikler ise şunlardır:

         IsAlive:
         Dim instance As Thread
         Dim value As Boolean
         value = instance.IsAlive

         IsBackGround:
         Dim instance As Thread
         Dim value As Boolean
         value = instance.IsBackground
         instance.IsBackground = value

         IsAlive propertys’i üzerinde çalıştırılan kanal halen çalışıyorsa true değerini aksi halde false değerini döndürür bu da bize avantajlar sağlamaktadır.
         IsBackGround özelliği ise kanalın arka planda çalışmasını gerçekleştirir kanalın arkaplanda çalışmasını istiyorsanız IsBackground’a true değerini atamalısınız.
         Her uygulamada varsayılan olarak bir thread ile çalışır ve zaten programımızın çalışmasını sağlayan bu ana thread’dir. Bu thread’e ulaşmak içinde CurrentThread özelliğini kullanabiliriz.
         Deklarasyonu aşağıdaki gibidir:
         Public Shared ReadOnly Property CurrentThread As Thread
         Teorik olarak öğrendiğimiz multithreading programlamayı basit bir örnekle irdeleyelim;

Imports System.Threading

Public Class Form1
          Dim thr As Thread
          Private Sub arkaplan()
                   Dim i As Integer = 1

                   Do While True
                            ListBox1.Items.Add("Tekrarlama: " + i.ToString())
                            i += 1
                   Loop
          End Sub

          Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
                   thr = New Thread(AddressOf Me.arkaplan)
                   thr.Start()
          End Sub

          Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
                   thr.Abort()
          End Sub

          Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
                   thr.Sleep(2000)
          End Sub
End Class

         Bu örneğimizdede göreceğiniz gibi thr isimli thread’imizi buton 1’e basmamızla birlikte canlandırıyoruz ve thread’i başlatıyoruz. İkinci butona basmamızla thread sonlanmış oluyor.
         Kanallardan bahsederken unutmamız gereken kanalların önceliğidir. Bir kanalın önceliğini CPU belirler. Düşük öncelikli kanallar az CPU zamanı, yüksek öncelikli kanallar ise daha fazla CPU zamanı gerektirirler. Kullandığımız kanallar varsayılan bir öncelik atarlar. Tabiki bu önceliği bizim atamamızda mümkün ve böylece daha fazla performans elde edebiliriz. Bunun içinde Thread sınıfının üyesi olan priority özelliğini kullanabiliriz.
         Public Property Priority As ThreadPriority
         5 adet öncelik ataması mevcuttur. Bunlar sırasıyla;

         Highest
         AboveNormal
         Normal
         BelowNormal
         Lowest
         Oluşturduğumuz kanala biz bir öncelik atamassak varsayılan olarak Normal atanacaktır. Öncelik ataması ile ilgili açıkca önceliklerin ve CPU zamanını test eden bir örnek yapalım ve bu zamanlamayı görelim.
         Konsoldan çalışan örneğimiz:

Imports System
Imports System.Threading

Module Module1
          Sub Main()
                   Dim priorityTest As New PriorityTest()

                   Dim threadOne As Thread = _
                   New Thread(AddressOf priorityTest.ThreadMethod)
                   threadOne.Name = "ThreadOne"
                   Dim threadTwo As Thread = _
                   New Thread(AddressOf priorityTest.ThreadMethod)
                   threadTwo.Name = "ThreadTwo"
                   threadTwo.Priority = ThreadPriority.BelowNormal
                   threadOne.Start()
                   threadTwo.Start()

                   ' 10 Saniye
                   Thread.Sleep(10000)
                   priorityTest.LoopSwitch = False
          End Sub
End Module


Public Class PriorityTest
          Dim loopSwitchValue As Boolean
          Sub New()
                   loopSwitchValue = True
          End Sub
          WriteOnly Property LoopSwitch() As Boolean
          Set(ByVal value As Boolean)
          loopSwitchValue = value
          End Set
          End Property
          Sub ThreadMethod()
                   Dim threadCount As Long = 0
                   While loopSwitchValue
                            threadCount += 1
End While                   
                   Console.WriteLine("{0} with {1,11} priority " & _
                   "has a count = {2,13}", Thread.CurrentThread.Name, _
                   Thread.CurrentThread.Priority.ToString(), _
                   threadCount.ToString("N0"))
          End Sub

End Class


         Çıktı: 

  Multithreading programlamayı anlatırken Thread’lerin çalışma mantığı içerisindeki bazı çelişkileri engellemek için senkronizasyon sağlamak için bazı yöntemlere başvurmamız gerekmektedir. Aksi halde programımız istenmeyen sonuçlar doğuracaktır. Senkronizasyonu kullanma nedenimiz çoğunlukla aynı veriye erişimin söz konusu olduğu durumlarda meydana gelebilecek karışıklıkdır. Eğer ben integer bir değere bir thread’de 5 atayıp diğer thread’de aynı anda 7 atıyorsam ve ilk thread’de atadığım 5 sayısına göre işlem yapmam gerekirken 7 değerine göre işlem yapıyorsam ortada bir karışıklık olacaktır.
         Synclock ifadesi bu senkronizasyonu sağlayan kurallardan bir tanesidir.
         Synclock(“locking”)
                   ‘Kodlar
         End Synclock

         Monitor sınıfıda senkronizasyonu sağlamanın yollarından bir tanesidir. 11 adet metoda sahiptir. Bunlardan ikisi en önemlileridir. Bunlar Enter() ve Exit metodlarıdır.
         Dim obj As Object
         Monitor.Enter(obj)
         Ve
         Dim obj As Object
         Monitor.Exit(obj)
          Monitor sınıfı, Synclock ile aynı işi yapmaktadır.Microsoft bir Synclock bloğunun monitor sınıfı ile ilk önce Enter() metodunu ardından Exit() metodunu çağırmanın eşdeğer olduğunu bildirmiştir.
          Bu iki yöntem ile küçük bir uygulama yapacak olursak;
         Synclock Örneğimiz:

Imports System.Threading
Public Class Form1
          Public Sub fonk()
                   Dim i As Integer

                   SyncLock ("locking")
                            For i = 1 To 10
                            ListBox1.Items.Add("Sayı: " + i.ToString())
                            Next
                   End SyncLock

          End Sub
          Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
                   Dim thr1 As New Thread(AddressOf Me.fonk)
                   Dim thr2 As New Thread(AddressOf Me.fonk)
                   Dim thr3 As New Thread(AddressOf Me.fonk)
                   thr1.Start()
                   thr2.Start()
                   thr3.Start()
          End Sub
End Class

         Monitor Sınıfı Örneğimiz:
Imports System.Threading
Public Class Form1
          Public Sub fonk()
                   Dim i As Integer

                   Monitor.Enter(Me)
                   For i = 1 To 10
                   ListBox1.Items.Add("Sayı: " + i.ToString())
                   Next
                   Monitor.Exit(Me)

          End Sub

          Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
                   Dim thr1 As New Thread(AddressOf Me.fonk)
                   Dim thr2 As New Thread(AddressOf Me.fonk)
                   Dim thr3 As New Thread(AddressOf Me.fonk)
                   thr1.Start()
                   thr2.Start()
                   thr3.Start()
          End Sub
End Class

         Gördüğünüz gibi kodumuzda fazla bir değişiklik olmadı. Sadece Synclock bloğunun yerine Monitor.Enter(object) ve Monitor.Exit(object) metodlarının geldiğine dikkat edin.
          Çok kanallı programlama yapabildiğimiz gibi makalemizin başındada belirttiğim gibi çok işlemli programlama da yapabilirsiniz. Bunun için tek gerekli olan Process sınıfını kullanmak oalcaktır. Bir işlemi başlatmak için Start() metodunu kullanmamız yeterli olacaktır.
         Process başlatmak için:
          Dim prsc As New Process
          prsc.Start(“wordpad.exe”)

         Process sınıfı ile ilgili bir örenk yapmak gerekirse:
          Dim prsc As New Process
          prsc.Start(“wordpad.exe”)
         prsc.WaitForExit()
         prsc.Close()
         Bu kod bloğunu projenizde çalıştırdığınız zaman wordpad başlayacaktır. Siz wordpad’i kapatana kadar programınız beklemede kalacaktır. Siz programı kapattığınız zaman Close() metodu ile ilgili işleme ayrılan bellek serbest bırakılacaktır.
          Sorularınızı,yorumlarınızı ve görüşlerinizi volkan@volkanatasever.com adresine mail olarak atabilirsiniz.



BitArray sınıfı, indeksleyiciler ve özellikler

clock Aralık 6, 2006 07:39 by author Volkan Atasever

Bu yazımda sizlere BitArray sınıfının kullanımı ve tanımı hakkında bilgiler vereceğim. Bunu yaparken de C# a yeni başlayanlar için indeksleyiciler ve özellikler kavramına da bir göz kırpacağız. BitArray sınıfı, adından da anlaşıldığı gibi bitlerden oluşan bir koleksiyondur. Bitler bilgisayar dünyasının temelini oluşturduğu ve bu bağlamda hayati bir önem taşıdığı için bir çok uygulamamızda kullanabileceğimiz çok faydalı bir sınıftır. Birden fazla kurucusu mevcuttur isterseniz önce bunlara değinelim.

Constructors (Kurucular) Açıklama
public BitArray(bool[] bims) Burada boolean türündeki dizimiz aynen BitArray koleksiyonumuzun elemanları olur.
public BitArray(byte[] bims) Byte türünden dizimizin uzunluğunun 4 olduğunu varsayarsak bims[0] ilk 8 biti bims[1],bims[2] ve bims[3] sırasıyla diğer 8 bitleri temsil eder. Sonuç olarak 32 biti koleksiyonumuzda barındırmış oluruz.
public BitArray(int[] bims) Aynen byte türünden dizi kabul eden kurucumuzdaki gibi aynı mantıkla çalışır bims[0] ilk 32 biti ve sırasıyla diğer 32 bitlik gruplar koleksiyonumuzun elemanı olarak karşımıza çıkar.
public BitArray(int boyut) Burada direkt olarak sınıfımız içindeki bitlerin sayısını belirleyebiliriz. Not: Ilk değer olarak false atandığını unutmamız gerekir.
public BitArray(int boyut,bool xyz) Burada ise direkt olarak boyutunu verdiğimiz gibi ikinci parametre oalrak verdiğimiz bool türünden değişken sayesinde sınıfımıza ilk değeri otomatik değil bizim kontrolümüz altında istediğimiz seçenek atanır. True veya False.
public BitArray(BitArray bims) bims sınıfımızdaki bitler aynen yeni oluşturduğumuz sınıfta da kullanılacaktır. Unutulmaması gereken bir değer kopyalanması olduğu ve referanslarının aynı olmadığıdır.

Kurucularımızı irdeledikten sonra bir uygulama için gerekli olan diğer silahlarımızı kuşanalım ve bunlarda bu sınıfa ait olan üyelerden metotlarımız olsun. Bildiğiniz gibi metotlar, kurucular, özellikler ve indeksleyiciler bir sınıfın vazgeçilmez araçlarıdır.

Yeni başlayanlar ve dah önceden C ile upraşanlar için Not: Metotların C deki karşılığının Fonksiyon olduğunu belirtmeden geçemeyeceğim aşağıdaki metotları eğer C biliyorsanız fonksiyon mantığıyla düşünmeniz işlerinizi eminim çok rahatlatacak. Yeni bir kavram ve C nin NYP(Nesne Yönelimli Programlama (Ingilizce deyimiyle OOP)) eklenmiş hali olarak görmeniz bir adım daha ileri gitmemiz için bir avantaj kazandırır.

Metodlar Kısa Örnek Açıklama
public BitArray And(BitArray isim) BitArray sınıfında kadir1 kadir2 kadir3 olsun.
kadir3=kadir2.And(kadir3);
kadir2 ile kadir3 bitsel ve ye sokulup kadir3 e atanıyor.
BitArray sınıfından isim adlı nesnenin bitlerine ve bu metodun üstünden kullanılan nesnenin bitlerine bitsel ve uygular ardından tekrar geri dönüş değeri olarak kullanır.
public BitArray Not() kadir3=kadir2.Not(); Fazla üstünde durmaya gerek yok sanırım. Üzerinden çağrılan BitArray sınıfını bitlerinin değilini alır ve geri dönüş değeri de bu sonuç içeren BitArray nesnesidir.
public BitArray Or(BitArray isim)   BitArray And() ten tek farkı bitsel ve yerine bitsel or yapmasıdır.
public BitArray Xor(BitArray isim)   Bu da bitsel Xor yapmaktadır kullanımı BitArray Or() veya And() ile aynıdır.
public bool Get(int indeks)
public void Set(int indeks,bool abc)
  Indeksleyicilerden ve özelliklerde kullanılan get ve set den pek de bir farkı olduğu söylenemez. Get metotumuz BitArray sınıfındaki belirttiğimiz indeks deki biti döndürür. Set ise aynen dediğim gibi indeksini belirttiğimiz bite abc değerini koyar.


Yeni Başlayanlara Için:

Makalemizde bahsedilen indeksleyicilerde veya özelliklerdeki Get ve Set in tanımı şöyleydi; en basit tanımıyla get değer döndürür ve set değer atar. Tabi ki çok daha kullanışlı olduğunu belirtmek isterim kısa bir indeksleyici örneği verirsek: dizi adında bir dizi tanımlandığı farzedilmiştir. value atanan değerdir.
 

public int this[indeks]
{
    get{ return dizi[indeks]; };
    set{ dizi[indeks]=value; };
}

Özellikleri gösteren küçük bir örnek: (deger isminde bir int tipinde alanımız olduğu farzedilmiştir.)

public int isim
{
    get{ return deger; }
    set{ deger=value; }
}

Indeksleyicilere ve özelliklere dair böyle bir noktada ufak bir örnek vermemenin tuzsuz bir çorba yapmaktan pek bir farkı olduğunu sanmıyorum. Indeksleyiciler ve özellikler nesne yönelimli programlama mantığının temellerinden biridir öyle ki nesne üzerinden en azından bir diziye bizim verdiğimiz kurallara göre değer atamak ve değer okumak işi kolaylaştıran bir unsurdur en iyisi örneğimizi verelim. Bu aşamada eminim indeksleyicilerin kullanımı size bir çok şey katacaktır. Örneğimiz:

using System;
using System.Text;

namespace indeksleyiciler
{
    class Program
    {
        static void Main(string[] args)
        {
            indexersinifi ind=new indexersinifi(10);
            Console.WriteLine("Özelliğimiz çalışıyor...");
            Console.WriteLine("Dizinin Boyu"+ind.boyut);

            Console.WriteLine("indeksleyici sayesinde sınıfımızın içindeki dizimiz doluyor...");
            for(int i=0;i<10;++i)
                ind[i]=(i+1)*2;
            Console.WriteLine("Get Eden Bölüm Çalışıyor ve sonuçlar...");
            for(int i=9;i>=0;--i)
                Console.WriteLine("Dizinin "+i+". elemanı "+ind[i]);
        }
    }
    class indexersinifi
    {
        int[] dizi;
   
        public indexersinifi(int aa)
        {
            dizi = new int[aa];
        }

        public int this[int index]
        {
            get{
                return dizi[index];
            }
            set{
                dizi[index]=value;
            }
        }
        public int boyut{
            get{
                return dizi.Length;
            }
        }
    }
}

Programımızın Çıktısı:  
 

Metodlar Açıklama
public void SetAll(bool abc) BitArray sınıfının içerdiği bütün bitlere abc değerini atar. Yukarıda anlatılan set mantığının tek bir bite değil sahip olduğu bütün bitlerine uygulanmış bir varyasyonudur. Bu sınıf içinde ayrıca bir indeksleyici ve bir özellik tanımlıdır (Ingilizce karşılıkları indexer ve properties dir).
object this[int indeks] { get; set; }
ve
public int Length { get; set; }
Not: BitArray, ICollection IEnumerable uygular ve IClonable’ı destekler.

Arayüzlere bu makalemde değinmiyorum. Kısaca teknik özelliklerinden bahsedersek interface anahtar kelimesi ile belirtilir. Metot imzalarını taşır ve sınıflar kalıtım yoluyla bir yada birden fazla arayüz alabilir. C# da eksik olan çoklu kalıtımın bir nevi değişik şekillerden gerçekleştirilmesidir. Bu bilgiler ışığında oluşturulmuş olan C# örneğimiz:

using System;
using System.Collections;

class Program
{
    static void Main(string[] args)
    {
        byte[] bKadir ={ 67 };
        bool[] bKadir2={true,false,false,true,true,false,true,false};
        BitArray BBitler1 = new BitArray(bKadir2);
        BitArray BBitler2 = new BitArray(8, false);
        BitArray BBitler3 = new BitArray(bKadir);
        BBitler2 = BBitler2.Xor(BBitler3);
        BBitler3=BBitler3.Or(BBitler1);
        BitArray BBitler = new BitArray(BBitler2.Not());

        //indeksleyicinin kullanımı
        BBitler3[1] = false;

        BBitler2.SetAll(true);
        Console.WriteLine("BBitler in son degeri");
        foreach (bool xyz in BBitler)
            Console.Write(xyz + " ");
        Console.WriteLine();
        Console.WriteLine("BBitler1 in son degeri");
        foreach (bool xyz in BBitler1)
            Console.Write(xyz + " ");
        Console.WriteLine();
        Console.WriteLine("BBitler2 in son degeri");
        foreach (bool xyz in BBitler2)
            Console.Write(xyz + " ");
        Console.WriteLine();
        Console.WriteLine("BBitler3 in son degeri");
        foreach (bool xyz in BBitler3)
            Console.Write(xyz + " ");
        Console.WriteLine();
        Console.WriteLine("BBitler in uzunluğu "+BBitler.Length);
        Console.WriteLine("BBitler1 in uzunluğu "+BBitler1.Length);
        Console.WriteLine("BBitler2 in uzunluğu "+BBitler2.Length);
        Console.WriteLine("BBitler3 in uzunluğu "+BBitler3.Length);    
    }
}

Çıktımız ise şöyledir: 

Başka bir uygulama olarak int[] dizisi ile bir BitArray sınıfı canlandıralım:

using System;
using System.Collections;

class Program
{
    static void Main(string[] args)
    {

        int[] bKadir ={ 960167 };
        BitArray BBitler1 = new BitArray(bKadir);
        BitArray BBitler2=new BitArray(bKadir);
        BBitler1.Not();
        BBitler2.SetAll(true);
        Console.WriteLine("BBitler1 in son degeri");
        foreach (bool xyz in BBitler1)
            Console.Write(xyz + " ");
        Console.WriteLine();
        Console.WriteLine("BBitler2 in son degeri");
        foreach (bool xyz in BBitler2)
            Console.Write(xyz + " ");

        Console.WriteLine();
        Console.WriteLine("BBitler1 in uzunluğu "+BBitler1.Length);
        Console.WriteLine("BBitler2 in uzunluğu "+BBitler2.Length);
    }
}

Çıktımız ise şöyle: 

Gördüğünüz gibi hemen hemen bütün metotları, indeksleyicileri ve özellikleri kullanarak kompleks bir BitArray sınıfı uygulaması yaptık. Kurucu metotların değişik varyasyonlarını da rahatlıkla deneyebilirsiniz. C# ın ve Visual Studio.NET in .Net Framework gibi bir bileşenler yumağıyla oluşturduğu çıkış ve desteklediği geniş çaplı ve yapılabilir hemen hemen her şey sayesinde uygulayabileceğiniz her türlü alt seviyeli programlama içinde uygun bir sınıf. Bana kalırsa robotik deneylerinin de bir nevi vazgeçilmezi.

Değişik kalıplar bulup BitArray dizisinin metotlarını kullanarak ilginç sonuçlar elde edebilirsiniz. C# ın hissettiğine inanmıyorum yani şu intellisense olayına çünkü asıl hisseden sizlersiniz ve bu kalıpları bulup kullanırsanız yapacağınız işlemler o kadar kompleks olacaktır. Unutmayın programlama dilleri ve bu yazıyı okuduğunuza göre C# sizin için ana diliniz gibi olmalıdır. 1 ve 0 mantığı her zaman işe yaramaktadır düşünsenize programcı mantığıyla bir 0 dan 1 elde etmek isteseniz yapacağınız şey bir 0’ın içinde kaç tane 0 olduğunu saymaktır. O halde bu BitArray sınıfının önemini kavramak da bizim için zor olmasa gerek. Siz bir adım öne gidin ve çeşitli atraksiyonlarını uygulayın. Yaptığınız programları da mail adresime yollayabilirsiniz. Herhangi bir soru ve yorum için inhoftec@gmail.com adresinden bana ulaşabilirsiniz.

Yazan: Volkan Atasever



VB.NET ile Ses İşlemleri

clock Kasım 17, 2006 07:55 by author Volkan Atasever

  VB.NET’in biz programcılar için yapabilecekleri gerçekten neredeyse sınırsıza yakın. .NET ortamını, Visual Basic’in kolaylığıyla ve .NET’in kompleks içeriğiyle birleştirdiğimiz zaman inanılmaz özelliklere imza atan bir ortam görüyoruz.
        Programlarımızı zenginleştirmek için görsel öğeleri bolca kullanmaktayız. Ses unsuru da unutulmaması gereken başlıca özelliklerden. Ses bildiğimiz gibi kulağımıza gelen ve beynimizin uyarılmasını sağlayan dış unsurlarla duyumsamamızı etkileyen bir titreşim topluluğudur.
        Biz ise sıradan ses den değil ses sinyallerinden bahsedeceğiz İngilizce terimi ile ifade edersek: “audio”.
        Fazla derinlemesine girmeden standart ve standart dışı olarak VB.NET projelerimizde bu sesi nasıl kullanabileceğimizi örneklendireceğiz. Gerek Directx Sound gerekse apilerle veya directx audioplayback ile bunları nasıl elde edeceğimizi inceleyeceğiz.
        Bir oyun yazıyorsanız sizin için çok yararlı olacaktır veya kullanıcı ile etkileşime giren bir program.
        Başlangıç olarak makalemin teknik kısmına directx sound ile başlamak istiyorum. Başlamadan önce directx sdk nın bilgisayarınıza yüklü olduğuna emin olmalısınız ben şubat 2006 dağıtımını kullandım.

        http://www.microsoft.com/windows/directx/default.mspx
        Yukarıdaki bağlantının download kısmında sdk yı indirebilirsiniz.
        Projenize ileriki adımlarda da kullanmak için bazı referanslar eklemek zorundayız. Aşağıdaki resimde görebilirsiniz. 

Projemize sağ tıklayıp add reference kısmına basıyoruz.
        Ardından; 

Microsoft.DirectX.DirectSound , Microsoft.DirectX.AudioVideoPlayBack ve Microsoft.DirectX referanslarını projenize ekleyin.
        Not: Burada projenin bütün kodlarını değil de can alıcı noktalarını açıklayacağım. Uygulamanın tam kodlarını örnek kodlar bölümünden indirebilirsiniz.

        Imports Microsoft.DirectX.DirectSound
        Imports Microsoft.DirectX
        ile namespacelerimizi projemize dahil ediyoruz.
        İlk başta bize gereken bilgisayarımızdaki herhangi bir yoldan ses dosyamızı çağırmaktır. Bunun için bir textbox ve bir browse butonuna ihtiyacımız var. Textbox bileşenimizde de ses dosyamızın yolunu görebileceğiz bunun için gerekli olan toolbox’ımızdan OpenFileDİalog isimli bileşinimizi projememize eklememizdir. 

OpenFileDialog1.ShowDialog()
         filename = OpenFileDialog1.FileName
         TextBox1.Text = filename

        Filename ise bir string olarak tanımlanmıştır.
        Temel kodumuz ise aşağıdaki gibidir:


                  Dim dev As New Device()
                  dev.SetCooperativeLevel(Me, CooperativeLevel.Normal)
                  Dim dsc As New BufferDescription()
                  dsc.ControlVolume = True
                  dsc.ControlFrequency = True
                  Dim snd As New SecondaryBuffer(filenamedxsound, dev)
                  snd.Volume = volume
                  snd.Frequency = frekans
                  snd.Play(0, BufferPlayFlags.Default)

          Device nesnemizi ses kartınız olarak düşenebilirsiniz sesimizi çalmamız için gereken en temel bileşendir. Yani ilk önce ses aygıtımızı oluşturduk. Ardından aygıtımızın üzerinden setcooperativelevel’i çağırmamız gerekir. Burada Normal’i kullandık çoğunluklada bu seçenek yeterli olacaktır. Ayrıca bir BufferDescription nesnesini canlandırdık bunun sebebi bu nesne üzerinde dahil olan ses yüksekliğini ve ses frekansının değerlerini aktif hale getirmek için kullanılmıştır. Ardından SecondaryBuffer’ımızı oluşturup filenamdxsound adını verdiğimiz dosya ismimizi çağırıyor ve ikinci parametre olarakda aygıtımızız gösteriyoruz. Snd.Volume e ses yüksekliği değerimizi Frequency’e ise bizim seçtiğimiz frekansı aktarıp . snd.Play’e 0 değerini veriyoruz ve varsayılan değer olarak çalmasını yani bir kere çalıp durmasını söylüyoruz.
          Örnek uygulamamızda kullandığımız gibi bir trackbar kullanmak isterseniz maximum ve minimum değerlerini doğru seçmeniz gerekecektir. Bunun içinde volume trackbar’ımızın maximumunu 0 ve minimumunu ise -3000 olarak ayarlamalısınız.
          Frekans’ımızın minimumumu ise 100 maksimumuda 10000’dir.
          Sesi ve frekansı trackbarla ayarlamamıza yarayacak örnek kodumuz:
           If TrackBar1.Value = TrackBar1.Minimum Then
                      volume = -3000
           Else
                     volume = TrackBar1.Value
           End If
           If TrackBar2.Value = TrackBar2.Minimum Then
                      frekans = 100
           Else
                      frekans = TrackBar2.Value
           End If
          Directx sound ile ses çaldırırken daha bir çok özellik yer almaktadır. Bunlardan bazıları,
          Sağ ve sol balansı kontrol etmek için gereken özellik:
          Yukarıdaki kodumuzda aşağıdaki modifikasyonları yapabilirsiniz.
                     Dim dev As New Device()
                      dev.SetCooperativeLevel(Me, CooperativeLevel.Normal)
                     Dim dsc As New BufferDescription()
                     dsc.ControlVolume = True
                      dsc.ControlPan = True
                     Dim snd As New SecondaryBuffer(filenamedxsound, dev)
                     snd.Volume = volume
                      snd.Pan = 3000
                     snd.Play(0, BufferPlayFlags.Default)

          Speaker seçiminide kolay bir şekilde projenize ekelmeniz olası:
          ‘ Yeni Speaker Nesnesi yarat
          Dim spk As New Speakers();

          ‘ Properties’ler
          spk.Mono = false ‘ mono speaker
          spk.Headphone = false ‘ headphones
          spk.Stereo = false ‘ stereo speakers
          spk.Quad = true ‘ quad system (iki ön, iki arka)
          spk.FiveDotOne = false ‘ 5.1 surround system
          spk.SevenDotOne = false ‘ 7.1 surround system
          spk.Surround = false ‘ surround system
          dev.SpeakerConfig = spk;

          Directx.AudioVideoPlayback ile ses çaldırmak ise Directxsound’dan daha kolay ve birkaç kod satırı ile sesi çaldırabiliyoruz.
          Bunun içinde
          Imports Microsoft.DirectX.AudioVideoPlayback
          Namespace’imizi import etmemiz gerekecek.
          Kodumuz ise:
                     Dim audio As New Audio(filenameaudiopb)
                     audio.Volume = volume
                     audio.Play()

                    Burada filenameaudiopb ses dosyamızın ismi ve Audio nesnemizde ses dosyasını çalmamızı yarayan nesnemiz. audio.Volume ve audio.Play() ile default olarak sesimizi çaldırabiliriz.
          Ses dosyalarını çaldırmak için diğer bir yöntemimiz ise DLL import ile API’ler kullanılarak eskiden kalma yöntemlerle oluşturacağımız bir sistemdir.
                    Imports System.Runtime.InteropServices
          Projemize yukarıdaki namespace’i ekleyelim.
          Ardından;
                      Declare Auto Function PlaySound Lib "winmm.dll" (ByVal name _
                     As String, ByVal hmod As Integer, ByVal flags As Integer) As Integer
                      Public Const SND_SYNC = &H0 ' Senkron
                      Public Const SND_ASYNC = &H1 ' Asenkron
                     Public Const SND_FILENAME = &H20000

          ile DLL dosyamızı import edelim ve sabitlerimizi belirleyelim SND_SYNC müzik dosyamızı Senkron bir şekilde çalmamızı SND_ASYNC ise asenkron şekilde çalmamızı gerçekleyecektir. SND_FILENAME ise adından anlayacağınız gibi dosyamızın ismi.
          Tanımlamalarımız biraz karmaşık olmasına rağmen çalma işlemimiz çok daha basittir. Bunun için yapacağınız tek şey PlaySound metodunu kullanmanız olacaktır.
          PlaySound(filename,0,SND_FILENAME)
          Senkron veya asenkron çaldırmak için ise
          PlaySound(filename,0,SND_FILENAME or SND_SYNC)
          Veya
          PlaySound(filename,0,SND_FILENAME or SND_ASYNC)
          Şeklinde kodumuza ekleme yapabiliriz.
          Diğer sabitlerimiz ise aşağıdaki gibidir:
                     Public Const SND_SYNC = &H0
                     Public Const SND_ASYNC = &H1
                     Public Const SND_MEMORY = &H4
                     Public Const SND_ALIAS = &H10000
                     Public Const SND_NODEFAULT = &H2
                     Public Const SND_FILENAME = &H20000
                     Public Const SND_RESOURCE = &H40004
           Not: Directx Sound ve API’lerle wav dosyalarını çalıp üstünde işlem yapabilirken Directx audio playback ile mp3 dosyalarını da çaldırabilirsiniz.



Yapılar, Birlikler ve Bit Alanları

clock Mart 30, 2006 08:13 by author Volkan Atasever

Özet: Yapı tanımı ,örnekleri ve yapı işaretçileri. Yapı’ların fonksiyonlara parametre olarak gönderilmesi ve yapı döndüren fonksiyonlar. Birlik tanımı ve örnekleri. Yapı ile Birlik’ların iç içe kullanımı. Bit Alanları’nın açıklanması ve örnekleri.

Bu makalemde yapı, birlik ve bit alanları ile ilgili tanım,tanımlamalar ve örnek uygulamalar üzerinde duracağım. C dilinde int, float, char vb. ilkel veri tiplerimiz olduğu gibi bir çeşit kendi veri tipimizi tanımlama olanağımız da vardır. Bu tanımlamayı da struct anahtar sözcüğümüz ile gerçekleştirebiliyoruz. Küçük bir örnek vermek gerekirse:

struct ornek{
     int a;
    char b;
    float c;
};

Şeklinde olacaktır.

Yapımızın yapısını incelersek struct anahtar sözcüğü ve örnek adında bir yapı etiketi kullandık. Her yapı ‘;’ ile bitmek zorundadır. Yapıların boyutu ise içindeki veri tiplerinin toplam boyu kadardır. int,float ve char veri tiplerimizin sırayla 2,4 ve 1 byte büyüklüğünde bellekte yer kapladıklarını düşünelim (Farklı derleyiciler de farklı temel veri tipi boyutuna rastlamak mümkün), o zaman struct örnek adındaki veri tipimizin toplam boyutu 7 byte olacaktır. Not: Alignment kavramı göz ardı edilerek 7 byte olacağı farzedilmiştir. Eğer alignment parametresi ile programımızı derlersek bir hizalama olacağı için göz önüne aldığımız sistemde 7byte yerine 8 byte yer kaplayacaktır. Alignment gerçekten programımızı hızlandıran bir seçenek olarak karşımıza çıkar ve CPU nun daha az yorulmasını sağlar. Eğer yapımızı bir veri tipi olarak düşünürsek fonksiyonlara parametre olarak göndermek ve geri dönüş değeri kullanmak bizim için daha da kolay bir hal alacaktır. Yapıların fonksiyonlarla kullanılmasına ve genel kullanımına ilişkin bir senaryo oluşturalım. Senaryomuz, iki tane farklı yapının farklı bellek bölgelerine kopyalanması olacaktır ve bunu bir fonksiyon yardmıyla gerçekleyecektir.
İlk önce yapı tasarımımızı oluşturalım:

typedef struct{
    char ad[15],
    soyad[15];
    int borc;
}kadir;

Burada typedef anahtar kelimesi sayesinde uygulamamızda veri tipimizi kadir adında kullanabilmekteyiz. Yapımızın boyu 32 byte’dır. Kullandığımız uygulamalarda direk hesaplamak yerine sizeof(kadir) veya sizeof(struct etiket_ismi) şeklinde de öğrenebilriz.
Fonksiyonumuz ise:

kadir *kopy(kadir *al){
    rewind(stdin);
    puts("String gir");
    gets(al->ad);
    puts("2. String gir");
    gets(al->soyad);
    puts("rakam gir");
    scanf("%d",&al->borc);
    return al;
}


Şeklinde olsun.Burada kopy adındaki fonksiyonumu parametre olarak kadir tipinden bir adres beklemektedir. kadir isimli veri tipimizi de typedef ile yapımız üzerinde tanımladık. Fonksiyonumuzun geri dönüş değeri ise yine kadir tipinden bir adres olacaktır. rewind(stdin) ile standart input’umuzu geriye sardık. Ve puts fonksiyonları ile bir adres yazdırdık. Dikkat edilmesi gereken yer ise gets fonksiyonumuz parametre olarak yolladığımız kadir tipinden al adında değişkenin elemanlarına ‘->’ işaretiyle ulaşıyoruz. Eğer işaretçi üstünden değil de direkt değer türünden oluşturmuş olsaydık ‘.’ İşaretiyle elemanlarımıza ulaşabilirdik(Örnek: gets(al.ad); ) . scanf fonksiyonumuzun ise geleneksel olarak okuttuğumuz temel veri tiplerinden farklı bir yazım olarak sadece &borc olması gereken yerde &al->borc şeklinde yazılmıştır. Son olarak da kadir tipinden al adresini döndürüyoruz. main fonksiyonumuz ise şöyle olmalıdır:

int main(void)
{
    kadir *x1;
    kadir *x2;
    clrscr();
    x1=(kadir *)calloc(sizeof(kadir),5);
    x2=(kadir *)calloc(sizeof(kadir),5);
    for(int j=0;j<5;++j) {
         *(x2+j)=*(kopy(x1+j));
    }
    for(int r=0;r<5;++r){
        puts((x2+r)->ad);
        puts((x2+r)->soyad);
        printf("%d",(x2+r)->borc);
    }
    getch();
    return 0;
}


kadir tipinden iki adet işaretçi tanımladık ve bunlara calloc fonksiyonu ile sizeof(kadir)*5 kadar yer aldık yani toplamda 5’er adet yapımız için yer açtık. Eğer sizeof() işlecini kullanmasaydık ‘(kadir *)calloc(32,5);’ da diyebilirdik. Ardından for döngümüzü 5 kere dönecek şekilde kurduk ve içinde kopy fonksiyonumuzu çalıştırdık. x1+j adresini fonksiyona parametre olarak verdik(x1+0,x1+1,…x1+4 olarak parametreler gidecektir) ve geri dönüş değerimizi işaretçi olduğu için onun * operandıyla değerini *(x2+j) nin gösterdiği adresinin değerine yerleştirmiş olduk.

Not: Yapı işaretçilerinin 1 adres ileri gitmesi yapının boyu kadar olur. Diyelim yapımız 64 byte biz adresimizi bir arttırdığımızda 64 byte ileri gider. Veya 4 adres ileri gidersek 64*4 kadar yani 256 byte kadar ilerlemiş olur.
Bu şekilde x1 adresimize bilgileri kopy fonksiyonuyla okuyup yine sırasıyla x2 ye yerleştirmiş olduk. Adresler hakkında ki bilgi ve RAM’lerdeki yerleşimleri için alttaki resmi inceleyebilrisiniz.

İkinci for döngümüzde ise x2+r diyerek sırasıyla 5 adet yapımızın içinde olan bilgileri konsola yazdırdık. union yani birliklerin tanımları ve kullanılması da struct’larla benzerlik gösterirler. union’ların bize getirmiş olduğu en büyük kazanç aynı bellek adresini değişik veri tipleri için kullanabilmemizdir. Basit bir union tanımlamak gerekirse:

union deneme{
    int a;
    char b;
    int dizi[3];
};

Birliğimizde bir tam sayı değişkeni, bir karakter değişkeni ve bir de tam sayı dizisi bulunmaktadır. union deneme isimli birliğimizin boyu en büyük elemanının boyu kadardır burada da 3 elemanlı tam sayı dizimiz 6 byte olduğu için toplam boyut da 6 byte dır. Yapı ve birliklerin iç içe kullanımı ile ilgili bir örnek düşünürsek:

struct AYIR{
    char cIlk,
    cSon;
};
typedef union kisa{
    short int shSayi;
    struct AYIR AKrktr;
}sayim;

Öncelikle birliğimizi inceleyecek olursak içinde kısa bir tam sayı ve struct AYIR tipinden AKrktr isimli bir değişken tanımlanmış bulunuyor. Yapımızda ise cIlk ve cSon adında iki karakter değişkeni barındırmaktadır. İsterseniz bu tasarımımızın pratikte nasıl kullanılabileceğini düşünebiliriz. main() fonksiyonumuzu oluşturalım:

int main(){
    sayim saTest;
    saTest.shSayi=19527;
    printf("shSayi:%d cIlk: %c\n
    cSon:%c\n",saTest.shSayi,
    saTest.AKrktr.cIlk,
    saTest.AKrktr.cSon);
    printf("int: %d short int: %d char: %d",
    sizeof(int),sizeof(short int),sizeof(char));
    getch();
    return 0;
}

Burada typedef ile ile belirttiğimiz kendi oluşturduğumuz türden bir değişken tanımlıyoruz aynı zamanda bu birliğimizi barındırmaktadır. Ardından değişken üzerinden birliğimizin elemanlarından olan shSayi adlı değişkene 19527 sayısını atıyoruz. Çalıştırdığımızda ise çıktımız:

Kısa tamsayının 2 byte, karakterin ise 1 byte yer kapladığını çıktıdan görebiliyoruz. Birliklerin aynı bölgeyi kullandığını ve bu bölgeninde bizim yapımıza tekabül ettiğini unutmamız lazım. Yapımızda ise kendi içindeki 1 byte lık değişkenler sayesinde 19527 sayısının ilk 8 bitini cIlk ikinci 8 bitini ise cSon karşılamaktadır. İlk 8 bitin karşılığı G ve ikinci 8 bitin karşılığı ise L’dir. En basit tanımıyla herhangi bir karakterin bitlerini elde etmek için kullanacağımız ve bit düzeyinde işlem yapacağımız silahımız bit alanlarıdır. Alt seviyeli programlamada vazgeçilmezler arasında yer almaktadır düşünüyorum da sıradan bir com port’u programlamak ve bir protokol meydana getirip bit bit ele alınmadada faydalı olabilir. Biz şu anda temelini irdelemek için basit bir bitlere ayrıştırma programı tasarlayalım.

struct bitler {
    int iIlkBit: 1;
    int iIknci: 1;
    int iUcncu: 1;
    int iDrdncu: 1;
    int iBsnci: 1;
    int iAltnci: 1;
    int iYednci: 1;
    int iSonBit: 1;
};
union ikili {
    char ch;
    struct bitler test;
}ayir;

Bir önceki verdiğimiz örnek ile yapımızın ve birliğimizin uyumu aynıdır. Tek fark ise yapımızın artık sıradan bir yapı olmayıp bit alanı diye isimlendirilmesidir. Basit manada : işlecinin hemen ardından o değişkene kaç bit yer ayırdığımızı belirleyebiliriz. Şu anda bit alanımız 8 bitlik veriyi saklayabilme kapasitesine sahiptir. Eğer birliğimizde bir 4 byte’lık tam sayı tanımlamış olsaydık, ilk iki bitine ve son bitine ulaşmak bizim için önemli olsaydı bit alanımızda şöyle bir oynama yapabilirdik.
Not: 4 byte 32 bittir.

struct tamsayı{
    int birinci:1;
    int ikinci:1;
    :29;
    int son:1;
};

‘:’ işlecinden sonra yazdığımız 29 ilk iki bitten sonraki 29 biti önemsememiz gerektiğini belirtmektedir. Son olarak örneğimize dönecek olursak bitlerine ayırmak için kullanacağımız main() fonksiyonumuz şöyle olacaktır:

 

int main(void)
{
    printf("Bir Karakter Giriniz\n");
    scanf("%d",&ayir.ch);
    printf("\nKarakterin Bitlerine Ayrilmis Sekli:\n");
    if(ayir.test.iSonBit)
         printf("1");
    else
        printf("0");
    if(ayir.test.iYednci)
        printf("1");
    else
        printf("0");
    if(ayir.test.iAltnci)
        printf("1");
    else
        printf("0");
    if(ayir.test.iBsnci)
        printf("1");
    else
        printf("0");
    if(ayir.test.iDrdncu)
        printf("1");
    else
        printf("0");
    if(ayir.test.iUcncu)
        printf("1");
    else
        printf("0");
    if(ayir.test.iIknci)
        printf("1");
    else
        printf("0");
    if(ayir.test.iIlkBit)
        printf("1");
    else
         printf("0");

     getch();
    return 0;
}

 

Gördüğünüz gibi 99 sayısının bitlerine ayrılmış şekli çıktıda verilmiştir basit bir if else mantığıyla çok kolay bir şekilde elde edebildik. Unutmamanız gereken bit alanları alt seviyeli programlarda gerçekten çok faydalı işlere imza atmaktadır.

Sorularınızı ve yorumlarınızı volkan@volkanatasever.com adresine yollayabilirsiniz.
Yazan: Volkan Atasever



Basit Dosya İşlemleri - 3

clock Kasım 25, 2005 08:09 by author Volkan Atasever

Basit dosya işlemleri ve Basit Dosya İşlemleri – 2 adlı makalelerimin devamı olan bu makalemde sizlere dosyalar üstünde yapabileceğimiz diğer incelikleri göstereceğim. Mesela soyadına göre arama yapma veya dosyamızdaki bir kaydı değiştirme gibi. Dosyamız önceki makalede oluşturulmuş tu, buradaki anlatacaklarım da oraya bağımlı olarak devam edecektir.

Kayıt numarasına göre arama vb. uygulamalar karışıklığa yol açtığı için alt kriterlerde arama yapma ihtiyacı doğmuştur. Bir kütüphane uygulaması düşünelim. Kitabın sadece yazarını biliyoruz ve bize o yazara ait kitaplar lazım. Veya kitap adını biliyoruz, yazar adı lazım. Hepsi kod yazma sanatının incelikleridir. Yine de hepsi bir oluşumu işaret etmektedir, yani dosyayı.

Bir program yaparken de en memnuniyetsiz müşterinin ihtiyaçlarını karşılamak bizim için bir çıtadır (Bill Gates de sırlarını açırken buna benzer bir uygulamaya değinmiştir).

Şu anda ki temel ihtiyaçlarımız bunlardır. O zaman şimdi başlık (header) dosyalarımızı ve define ile belirttiğimiz ifadeleri tekrar hatırlayalım.  

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

#define MAX1 15
#define MAX2 15
#define MAX3 12
#define MAX4 45
#define MAX5 10
#define MAX6

//Yapımızı ise şöyleydi :

typedef struct kayit {
    char soyad[MAX1];
    char ad[MAX2];
    char tel[MAX3];
    char adres[MAX4];
    char no[MAX5];
    char not[MAX6];
}muvk;

Yapımız bir avukatın minimum ihtiyaçlarını karşılayacak şekilde tasarlanmıştır. İsterseniz ilk önce dosyamızda kriterlere göre arama yapan fonksiyonumuzu yazalım. Tek bir fonksiyon bize bütün kriterleri gerçekleştirmemizi sağlayacak minimum bilgiyi içermektedir.

void soyad()
{
    clrscr();
    FILE *fp;
    muvk *kayit;
    int i,kadir;
    char ara[15];

    do{
       kayit=(muvk *)calloc(sizeof(muvk),1);
    }while(kayit==NULL);

    fp=fopen("Muvekkil.vol","r");
    fseek(fp,0,2);
    kadir=ftell(fp)/sizeof(muvk);
    puts("Aranan kisinin Soyadi:");
    gets(ara);

    for(i=0;i kadir;++i){
       fseek(fp,i*103,0);
       fread(kayit->soyad,MAX1,1,fp);
       if(strcmp(ara,kayit->soyad)==0){
          rewind(fp);
          fseek(fp,i*103,0);
          fread(kayit->soyad,MAX1,1,fp);
          fread(kayit->ad,MAX2,1,fp);
          fread(kayit->tel,MAX3,1,fp);
          fread(kayit->adres,MAX4,1,fp);
          fread(kayit->dogum,MAX5,1,fp);
          fread(kayit->not,MAX6,1,fp);
          puts("Soyadi:");
          puts(kayit->soyad);
          puts("Adi:");
          puts(kayit->ad);
          puts("Telefonu:");
          puts(kayit->tel);
          puts("Adresi:");
          puts(kayit->adres);
          puts("Dogum Tarihi:");
          puts(kayit->dogum);
          puts("Not Ortalamasi:");
          puts(kayit->not);
       }
    }

    getch();
    fclose(fp);
    free(kayit);
}

Burada dikkat edilmesi gereken en önemli noktalardan biri, kadir değişkenine dosyanın hangi konumundaysak muvk veritipinin büyüklüğünü bölmüş olup kaç kayıt olduğunu bulmamızdır.

For döngümüzde her seferinde o anki kayıt açılmaktadır. For döngümüzün içinde kaçıncı kayıtsa, fseek hazır fonksiyonuyla o kısma konumlandırıyoruz. Sadece soyad kısmını okuyoruz. Hemen ardında if deyimimiz işletiliyor. strcmp() fonksiyonu if deyiminin vermiş olduğu müstesna kolaylıklardan ötürü bizim programımızla çok mükemmel bir şekilde işlemektedir.

İsterseniz strcmp() fonksiyonumuzu inceleyelim: strcmp() fonksiyonu, iki stringi karşılaştırıp bize bir tamsayı döndürür. (printf() ve scanf() fonksiyonlarının da bize geri dönüş değeri açısından sağladıkları faydaları unutmamak gerekir. Misal scanf() le klavyeden aldığımız herhangi bir basımın sayı veya karakter olduğunu bulabiliriz). strcmp() fonksiyonunun döndürdüğü sayıların anlamları şöyledir:

Değer Açıklaması
Sıfırdan Küçük İlk string, ikinci string’den küçük
Sıfır İlk string, ikinci stringe eşit
Sıfırdan Büyük İlk string, ikinci string’den büyük

Bizim uygulamamızda da sıfıra eşit mi diye kontrol yapılıyor. Bu eşitlik sağlanırsa if deyimi icra ediliyor yani girdiğimiz karakter katarı dosyadan okuduğumuz karakter katarına eşit çıkmış oluyor ve aradığımız kritere uygun kayıtlar listeleniyor. İf deyimi için de kullandığımız rewind(fp) fonksiyonumuz dosyanın geri sarılmasını ifade edip, o an ki döngüdeki i değerinin saklanmasından faydalanılarak yapılmış bir eylemdir. Kaçıncı kayıtta koşul sağlanmışsa, tekrar fseek() fonksiyonu bize kolaylık sağlamaktadır. Dosyadaki herhangi bir kaydı düzeltmek ise yine bizim vazgeçilmezlerimizden ve temel işlemlerden biridir. Düzelteceğimiz kayda gidip bu işlemleri yapmak bizi oldukça memnun edecektir. Her türlü işlemi, bu fonksiyonları kullanarak yerine getirebilirsiniz.

void change()
{
    FILE *fp;
    muvk *kayit;
    int kadir,number;

    clrscr();

    do{
       kayit=(muvk *)calloc(sizeof(muvk),1);
    }while(kayit==NULL);

    fp=fopen("Muvekkil.vol","r+");
    fseek(fp,0,2);
    kadir=ftell(fp)/sizeof(kayit);
    puts("Kayıt No Giriniz:");
    scanf("%d",number);
    fseek(fp,&number*103,0);
    fflush(stdin);
    puts("Yeni Soyad:");
    gets(kayit->soyad);
    puts("Yeni Ad:");
    gets(kayit->ad);
    puts("Yeni Telefon:");
    gets(kayit->tel);
    puts("Yeni Adres:");
    gets(kayit->adres);
    puts("Yeni Dogum Tarihi:");
    gets(kayit->dogum);
    puts("Yeni Not Ortalamasi:");
    gets(kayit->not);
    fwrite(kayit,sizeof(muvk),1,fp);
    fclose(fp);
    getch();
    free(kayit);
}

Bu fonksiyonumuzda ise kayıt no’suna göre bir arama yapılmaktadır. Kayıt no’su alınarak o kayda gidilip yeniden o bölgede değiştirilme yapılmıştır. Yazıda kullanılan fonksiyonların prototipleri ve açıklamaları:

Fonksiyon Adı Açıklaması
puts #include <stdio.h>
int puts(const char *str);
gets #include <stdio.h>
char gets(char *str) ;
ftell #include <stdio.h>
long int ftell(FILE *stream);
fseek #include <stdio.h>
int fseek(FILE *stream, long int offset,int origin);
fclose #include <stdio.h>
int fclose(FOLE *stream);
Stream ile ilişkili dosyayı kapatır ve tamponu temizler.
free #include <stdlib.h>
void free(void *ptr);
ptr’nin gösterdiği bellek bölgesini serbest bırakır ve bu bölgenin sonraki tahsisatlara hazır hale gelmesini sağlar.
calloc #include <stdlib.h>
void *calloc(size_t num, size_t size);
(num * size ) büyüklüğünde bellek tahsisatı yapar. Özetle size büyüklüğünde, num sayıda nesne içeren bir dizi için yeterli bellek tahsisatını yapar.

Bu makale veya diğer makalelerim hakkında görüşlerinizi ekleyebileceklerinizi veya yorumlarınızı volkan@volkanatasever.com adresine mail olarak ulaştırabilirsiniz.



Volkan Atasever Kimdir ?

E-Mail: volkan(et)volkanatasever.com

Genel Müdür/S4G 
Bilgisayar Mühendisi

mühendislik, edebiyat, retro computer, yazılım, şiir, nümismatik, bilişim, podcast ve bir çok kategoride yazılarım...

Yazılım Kitaplarım

   

Şiir Kitaplarım

Dergi Yazılarım

 

Sosyal Ağlarım

 

 

 

 

Retro Bilgisayar Dergimiz

Türkçe Retro Bilgisayar dergimiz haziran 2016'da ilk sayısını çıkardı. ilk sayı yeni bir internet sitesinden tekrar yayınlanacaktır. Retro camiası tüm dünyada oldukça eğlenceli bir camia. Sizde katkıda bulunmak isterseniz bana mail atmanız yeterli. Dergimiz PDF formatında ve tamamen ücretsizdir.

Yasal Bilgi

Sitedeki yazıları,kodlar ve diğer materyaller Volkan Atasever'e aittir. Yazarı ve siteyi kaynak göstererek yazıları paylaşabilirsiniz.  Copyright(c)2004-2017

Sign In

Yazılım