Yazan : Şadi Evren ŞEKER

Gelen bir soru üzerine, C dilinde bir dosyanın içeriğini tersten ekrana basan kodu yazıp sitede yayınlıyorum.

Öncelikle algoritmamızı inşa edelim.

Ters almak gibi işlemler yapı olarak özyineli (recursive) fonksiyonlara çok uygundur. Genelde stack (yığın) yapısının kullanıldığı özyineli fonksiyonlar bilgiyi tutma ve ters çevirme (son giren ilk çıkar (LIFO) algoritması) için elverişli olurlar. Bu yüzden biz de bir özyineli fonksiyon kullanarak dosyamızdan karakter karakter değerleri okuyacak sonra da bunları ekrana basacağız.

Kodu aşağıda veriyorum:

Kodumuzdaki main fonksiyonu sadece dosyayı açmakta ve sonra ters fonksiyonunu çağırmaktadır. Dosya ters fonksiyonunda işlendikten sonra (ki bu işleme dosyayı tersten basmak olacak) dosya kapatılmakta ve program sonlandırılmaktadır.

Gelelim ters fonksiyonuna. Bu fonksiyon, dosya göstericisini (file pointer) parametre olarak alıp, dosya sonu olup olmadığını kontrol ediyor. Feof fonksiyonu, şayet dosyanın sonuna ulaştıysa, return; satırını çalıştıracak ve dolayısıyla fonksiyondan çıkılacak. Aslında bu durum bizim dosyamızın sonu ve dolayısıyla fonksiyonumuzun sonu ve dolayısıyla özyineleme yığınımızın (recursion stack) sonu olmaktadır.

Fonksiyonun geri kalanında işlem gayet basit bir şekilde fscanf ile dosyadan okumak ve ardından tekrar ters fonksiyonunu çağırmak ve sonra da okunan karakteri ekrana basmak şekline ilerler.

Buradaki kritik nokta, ters fonksiyonunu, ekrana karakter basmadan çağırmaktır. Şayet kodun 11. ve 12. satırları yer değiştirecek olsaydı, yani önce ekrana basıp sonra ters fonksiyonunu çağıracak olsaydık, bu durumda dosyanın içeriği olduğu gibi ekrana basılacaktır. Biz bunun yerine o andaki okunan karakteri bekletiyoruz ve sonraki karakteri basması ve ters çevirmesi için yeniden fonksiyona veriyoruz. Bu işlem dosya sonuna kadar gidiyor. Nihayet dosya sonuna erişilince özyineli yığınımız (recursion stack) toparlanmaya başlıyor ve bu toparlanma sırasında ekrana karakterleri basarak ilerliyor.

Yukarıdaki kod, Dev-CPP ile test edilmiş ve çalışmaktadır. Örneğin girdi.txt dosyası olarak aşağıdaki içerikte bir dosyayı verirsek:

Programın çıktısı aşağıdaki şekilde olur:

 

Yorumlar

  1. killer

    Hocam cevabiniz için çok teşekkür ederim. Bunları satır satır ters cevirmek için karakter karaktermi okuyayım?
    Diğer 1. sorumda dosyada kayıtlı “bilgisayar kavramları” ‘ar’ lar ‘as’ olacaksa yani metini “bilgisayas kavramlası” şeklinde yazmak için sormuştum.İlginize çok teşekkür ederim hocam…

  2. Şadi Evren ŞEKER Article Author

    Sorunuzun çözümü için aşağıdaki yöntemi önerebilirim:
    Dosya içerisindeki bilgilerin tamamı bir diziye (char dizisi yani string (dizgi) ) okunur ardından bu dizi üzerinde karakter karakter işlem yapılarak aranan string (dizgi) bulunur. Bu dizginin yerine yenisi yazılır.

    Buradaki bir probleminiz aradığınız dizgiyi (string) nasıl bulacağınız. Burada kullanabileceğiniz bazı algoritmalar aşağıdaki listede sunulmuştur:

    Knuth-Morris Prat arama algoritması http://www.bilgisayarkavramlari.com/2009/04/11/knuth-morris-prat-algoritmasi-kmp-algorithm/
    Boyer-Moore Arama algoritması http://www.bilgisayarkavramlari.com/2009/05/19/boyer-moore-dizgi-arama-algoritmasi-boyer-moore-string-search/
    Kaba Kuvvet Metin Arama Algoritması (Brute Force Text Search, Linear Text Search) http://www.bilgisayarkavramlari.com/2009/11/24/kaba-kuvvet-metin-arama-algoritmasi-bruteforce-text-search-algorithm/
    DFA Metin Arama Algoritması http://www.bilgisayarkavramlari.com/2009/11/24/dfa-metin-arama-algoritmasi-dfa-text-search/

  3. tuna

    Hocam merhaba.öncelikle siteniz için teşekkür ederim.Oldukça yararlı dosyalar var.Özellikle benim gibi yeni başlayanlar için.

    c++ da bir çoklu liste uygulaması geliştirmeye çalışıyorum.ayrı ayrı 2 dosyada cep, ev numaraları var.Bir dosyada da öğrenci numarası ve ad soyadı var.Ben öğrenci no, ad soyadı birinci listede cep ,ev numaralarınıda ikincilistede tutmaya çalışıyorum.Sorum şu: öğrenci no dosyası şu şekilde.
    29439293 mehmet ali gültekin
    34243543 aytunç demir
    böyle 100den fazla kayıt var.numarayı, ismi ve soyismi nasıl alabilirim bu dosyada.(2 isimli olanları beceremedim.).
    kullandığım struct
    struct ogr{
    char ogrnum[20];
    char name[20];
    char surname[20]}; şeklinde.
    Teşekkürler.

  4. Şadi Evren ŞEKER Article Author

    Problem dosyaya, yapıyı (struct) nasıl yazıp okuduğunuz ile ilgili. Şayet yapı olarak yazdırıp okuyorsanız, yukarıdaki struct tanımı içerisine ikinci bir isim tanımlamalısınız ( char secondname[20] gibi) ve bu şekilde okuyup yazmalısınız.

    Şayet satır satır okuyorsanız (örneğin fgets gibi) bu durumda kelime sayısı 4 olduğunda yukarıdaki yapıda bulunan name[] dizisine ikinci ismi boşluk ile ilave edersiniz.

    Başarılar

  5. mercan

    soru2:tersine çevrilmiş dosya yapısını 3. sorudaki kayıt desenine göre sadece yaş alanı üzerinde yapan C programını yazınız
    soru 3:”veri.dat” isiml, bir dosya içerisinde kişi adi,soyadi,yasi ve boy ölçüsü bulunmaktadır. boy degerlerine göre “kabarcık” sıralaması ile küçükten büyüge sıraya dizen ve sonucu “siralaveri.dat” isimli yeni bir dosyaya yazan C proğramını yazınız?

    Tersine çevrilmiş dosya yapısı nasıl oluyor??

  6. musa

    hocam ben bu kodları dev c++ da yazıyorum ama sürekli şu hatayı alıyorum “stray ‘221’ in program”
    acaba kodlar mı hatalı yoksa derleyiciden mi kaynaklanıyor??

  7. Soner Çökmen

    Merhabalar,
    Çözümünüz ile ilgili bir kaç şeyden bahsetmek istiyorum. Öncelikle büyük boyutlu dosyalarda her karakter için özyinelemeli fonksiyonları çağırmak yığının şişmesine sebep olabilir. Bunun yerine fseek fonksiyonu ile dosya sonundan başlayarak dosya imlecini her okumadan sonra bir byte geriye çekmek daha iyi bir performans sağlayabilir.

  8. bedo

    Hocam bir sorum olacaktı ben dosyadan 8 bitlik kelimeler cekiyorum ama sadece bu kelimelerin sondan başa doğru başka dosyaya çekmek istiyorum yani harflerin yeri değişsin istemiyorum bunu nasıl yaparım.

Şadi Evren ŞEKER için bir cevap yazın Cevabı iptal et

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir