💻 Bilgisayar, 💾 Programlama

Ödev 4: Doğrudan Erişimli Dosyalarda Hashing ve Bağlaçlı Liste Yaklaşımı

14 Nisan 2008 tarihinde aldığımız, daha adından acılı bir ödev olacağı belli olan Doğrudan Erişimli Dosyalarda Hashing ve Bağlaçlı Liste Yaklaşımı ödevi için teslim ettiğim kaynak kod. Ödevde Vecdi Hoca’nın Ayrık’ta anlattığı Recursive (kendini çağıran fonksiyon) Algorithm kullanmayı denedim. Ödev zaten karışıktı, iyice karıştı ve ben programın yazarı olarak bile neyin ne işe yaradığını bazen anlayamıyorum. Ama buna rağmen programda hata göremedim, sorunsuz gibi gibi geldi bana.

Not: Ödevim içinde kaç tane fseek, fwrite fread var ben bile sayamadım. =)
Not 2: Ne zaman algoritma ödev kağıtlarındaki

“Ödevin değerlendirmesinde; programın doğru ve eksiksiz çalışmasının yanında etkinlik, yapısal ve modüler programlama ilkelerine uygunluk ta dikkate alınacaktır. Global değişken kullanılmaması ve fonksiyon kullanımı özellikle önemlidir.”

ta kelimesi (?) fark edilip düzeltilecek bir buçuk dönemdir heyecanla beklemekteyim.

Kaynak kodunu incelemek ve fikir sahibi olmak amacıyla kullanabilirsiniz. Ama lütfen kaynak kodunu kopyala yapıştır yapmayalım, kendimize mal etmeyelim. Onun yerine nasıl çalıştığını inceleyip kavrama yoluna gidelim.

Sınav dönemine geldik. Haydi hayırlısı.

Kaynak kodunu indirmek istemezseniz, bir kopyasına aşağıdan ulaşabilisiniz.

#include
#include

#define URUN_NO_MIN 1
#define KAYIT_SAY 100
#define STOK_LIMIT_MIN 0
#define ALIS_FIYAT_MIN 0
#define LINK_AYNI -2
#define LINK_GONDER -3

/* Sabitler ve Anlamlari */
/* ——————— */
/* URUN_NO_MIN : Ürün numarasının alabileceği en düşük değer. (negatif değeler özel parametre-
lere karşılık gelebileceği için tercih edilmemelidir.)
KAYIT_SAY : Hash fonksiyonu ile gidilecek, ilk başta yaratılan kısım. Bu değer oynanarak
ilk başta ne kadar boş kayıt olacağı değiştirilebilir.
DİKKAT: Dosyalar yaratıldıktan sonra bunu değiştirmeniz sorun çıkartır.
STOK_LIMIT_MIN : Stok değerinin alabileceği minimum değerdir. Programda depoda olmayan bir ürünün
satılamayacağı düşünülerek bu sabit 0 alınmıştır. Ancak stok değerinin – değer-
lere de düşmesi isteniyorsa bu değer değiştirilebilir.
ALIS_FIYAT_MIN : Birim alış/satış fiyatlarının alabileceği minimum değeri belirler. Bir ürünün
en fazla bedava satılacağı (o da nedense) düşünülmüş ve programda 0 ayarlanmıştır.
Ama eğer ürünü satıp üstüne de para verilmesi isteniyorsa bu değişken her türlü
sayı yapılabilir.
LINK_AYNI : urun_duzenle fonksiyonuna değiştirilen girdideki link değerinin değiştirilmemesi
gerektiğini söyleyen sembolik sabittir.
LINK_GONDER : urun_duzenle fonksiyonuna gönderildiğinde fonksyinonun urun_kodu ile gönderilen
ürüne ait link değerini geri döndürmesini sağlar.

*/

/* Yapılar */
struct URUN_YAPI {
int urun_kodu;
char urun_adi[20];
float birim_alis_fiyati;
int stok_miktari;
int sonraki;
int link;
};

struct SATIS_YAPI {
char fatura_no[6];
char satis_tarihi[6];
int satis_miktari;
float birim_satis_fiyati;
int sonraki;
};

/* Kullanıcı tanımlı tipler */
typedef struct URUN_YAPI URUN;
typedef struct SATIS_YAPI SATIS;

void beklet() {
/* Bu fonksiyonun tek amaci kullaniciyi bir tusa basana kadar
bekletmek, ve sonra ekrani silmektir. */
printf(“\nDevam etmek icin bir tusa basin.”);
getche();
system (“cls”);
}

int hash(int urun_kodu) {
return (urun_kodu % KAYIT_SAY) + 1;
}

int urun_var_mi(int urun_kodu,int kayit_no, int link_yolla) {

/* Ürünün olup olmadığını kontrol eder. Aşağıdaki değerlerden birini dönüdürür. */

/* 0: Urun yok. */
/* -1: Dosya açılamadı. */
/* -2: Urun var. */

FILE *fp;
URUN oku;

if ((fp=fopen (“urunler.dat”,”rb+”))== NULL) {
printf(“Urunler.dat acilamadi. Gidiyorum ben.”);
return -1;
}

if (kayit_no == -1) { /* Eğer fonksiyona ilk defa geldiysek hash ile asıl kaydı kontrol etmeliyiz. */
fseek(fp,(hash(urun_kodu) – 1) * sizeof(URUN),0);
} else {
fseek(fp,(kayit_no) * sizeof(URUN),0); /* Eğer fonksiyon kendini çağırdıysa dosya sonuna gidip bağlayacağız. */
}

fread(&oku,sizeof(URUN),1,fp);

if (oku.urun_kodu == urun_kodu) {

fclose(fp);
if (link_yolla == 0) { /* Eğer link numarasını gönderme parametresiyse çağrıldıysa */
return oku.link;
} else {
return -2;
}
}

if (oku.urun_kodu == -1) {
fclose(fp);
return 0;
} else {
if (oku.sonraki == -1) {
fclose(fp);
return 0;
} else {
fclose(fp);
return urun_var_mi(urun_kodu, oku.sonraki, link_yolla);
}
}
}

int urun_ekle(int urun_kodu, char urun_adi[20], float birim_alis_fiyati, int stok_miktari, int kayit_no) {

/* Adı üstünde: Ürün ekler */
/* 0: Başarılı. */
/* -1: Dosya açılamadı. */

FILE *fp;
URUN oku;
int sayac;
int gecici_konum;

if ((fp=fopen (“urunler.dat”,”rb+”))== NULL) {
printf(“Urunler.dat acilamadi. Gidiyorum ben.”);
return -1;
}

if (kayit_no == -1) { /* Eğer fonksiyona ilk defa geliysek hash ile asıl kaydı kontrol etmeliyiz. */
fseek(fp,(hash(urun_kodu) – 1) * sizeof(URUN),0);
} else {
fseek(fp,kayit_no * sizeof(URUN),0); /* Eğer fonksiyon kendini çağırdıysa dosya sonuna gidip bağlayacağız. */
}

fread(&oku,sizeof(URUN),1,fp);

if (oku.urun_kodu == -1) {
/* Burası boş, yazabiliriz. */

/* Gerekli atamalar */
oku.urun_kodu = urun_kodu;

for (sayac=0;sayac<20;sayac++) { oku.urun_adi[sayac] = urun_adi[sayac]; } oku.birim_alis_fiyati = birim_alis_fiyati; oku.stok_miktari = stok_miktari; oku.sonraki = -1; oku.link = -1; fseek(fp,-sizeof(URUN),1); // Denetlemek için ileri gitmiştik, dön geri. fwrite(&oku,sizeof(URUN),1,fp); // ve büyülü satır... fclose(fp); } else { /* Bu kayıt dolu, hadi başka bulalım. */ /* Eğer bu kayıt bağlı listenin son kaydıysa bu kaydı sonraki kısmını değiştirerek yeniden yaz. */ if (oku.sonraki == -1) { gecici_konum = ftell(fp); fseek(fp,0,2); oku.sonraki = ftell(fp)/sizeof(URUN); fseek(fp,gecici_konum,0); fseek(fp,-sizeof(URUN),1); fwrite(&oku,sizeof(URUN),1,fp); /* Sonra yeni ekleneceği ekleyelim. */ fseek(fp,0,2); oku.sonraki = -1; oku.link = -1; oku.birim_alis_fiyati = birim_alis_fiyati; oku.stok_miktari = stok_miktari; oku.urun_kodu = urun_kodu; for (sayac=0;sayac<20;sayac++) { oku.urun_adi[sayac] = urun_adi[sayac]; } fwrite(&oku,sizeof(URUN),1,fp); fclose(fp); } else { /* eğer bağlı listenin son elemanı değilse onu bulana kadar aynı algoritmayı tekrarla */ fclose(fp); return urun_ekle(urun_kodu, urun_adi[20], birim_alis_fiyati, stok_miktari, oku.sonraki); } } return 0; } int urun_guncelle(int urun_kodu, float birim_alis_fiyati, int stok_miktari, int kayit_no, int link) { /* 0: Başarılı. */ /* -1: Dosya açılamadı. */ FILE *fp; URUN oku; if ((fp=fopen ("urunler.dat","rb+"))== NULL) { printf("Urunler.dat acilamadi. Gidiyorum ben."); return -1; } if (kayit_no == -1) { /* Eğer fonksiyona ilk defa geliysek hash ile asıl kaydı kontrol etmeliyiz. */ fseek(fp,(hash(urun_kodu) - 1) * sizeof(URUN),0); } else { fseek(fp,kayit_no * sizeof(URUN),0); /* Eğer fonksiyon kendini çağırdıysa dosya sonuna gidip bağlayacağız. */ } fread(&oku,sizeof(URUN),1,fp); if (oku.urun_kodu == urun_kodu) { /* İşte düzenlenecek ürünümüzü bulduk, mutluyuz biz. 🙂 */ if (link == LINK_GONDER) { fclose(fp); return oku.link; } else { if (birim_alis_fiyati != ALIS_FIYAT_MIN - 1) { oku.birim_alis_fiyati = birim_alis_fiyati; } if (stok_miktari != STOK_LIMIT_MIN - 1) { oku.stok_miktari = stok_miktari; } if (link != LINK_AYNI) { oku.link = link; } fseek(fp,-sizeof(URUN),1); // Denetlemek için ileri gitmiştik, dön geri. fwrite(&oku,sizeof(URUN),1,fp); // ve büyülü satır... fclose(fp); } } else { /* Bu kayıt dolu, hadi başka bulalım. */ fclose(fp); return urun_guncelle(urun_kodu, birim_alis_fiyati, stok_miktari, oku.sonraki, link); } return 0; } int satis_ekle(int urun_kodu, char fatura_no[6], char satis_tarihi[6], int satis_miktari, float birim_satis_fiyati, int sonraki, int simdiki) { /* 0: Sorunsuz tamam */ /* -1: Dosya hatası */ FILE *fp; SATIS oku; int link_konum; int sayac; /* Önce urune bakalım... Eğer üründeki link -1 ise bu ürüne daha önce satış eklenmemiştir ki, ilk olduğu için işimiz çoooook basit olur. */ if (sonraki == -2) { /* Eğer fonksiyon kendini çağırmadıysa */ link_konum = urun_var_mi(urun_kodu,-1,0); if (link_konum == -1) { /* O zaman linki yaratacağız. */ if ((fp=fopen ("satislar.dat","rb+"))== NULL) { return -1; } fseek(fp,0,2); /* Dosya sonuna uç, ciiiik */ link_konum = (ftell(fp) / sizeof(SATIS)) + 1; for (sayac=0;sayac<6;sayac++) { oku.fatura_no[sayac] = fatura_no[sayac]; } for (sayac=0;sayac<6;sayac++) { oku.satis_tarihi[sayac] = satis_tarihi[sayac]; } oku.satis_miktari = satis_miktari; oku.birim_satis_fiyati = birim_satis_fiyati; oku.sonraki = -1; fwrite(&oku,sizeof(SATIS),1,fp); // ve büyülü satır... fclose(fp); urun_guncelle(urun_kodu, ALIS_FIYAT_MIN - 1, STOK_LIMIT_MIN - 1, -2, link_konum); /* Şu hayatta zaten ne oluyorsa iletişimsizlikten kaynaklanıyor. Bağlantıyı koparmamak lazım. urunler.dat ile satislar.dat da yukarıdaki satırla birbirine bağlanacak. */ } else { /* Eğer o ürüne dair daha önceden bir satış kaydı varsa bu biraz uğraştırıcı... Tüm kayıtları sıradan gezmeye başlayalım, uygun olan bağı bulalım ve hooop yeni satış bilgilerini yazalım. */ return satis_ekle(urun_kodu, fatura_no, satis_tarihi, satis_miktari, birim_satis_fiyati, link_konum, simdiki); } } else { if ((fp=fopen ("satislar.dat","rb+"))== NULL) { return -1; } fseek(fp,(sonraki-1) * sizeof(SATIS),0); fread(&oku, sizeof(SATIS),1,fp); if (sonraki == -1 || strncmp(oku.satis_tarihi,satis_tarihi,6) < 0) { /* Eğer girilen kayıt dosyadakinden daha büyükse işlem yapılacak */ /* Eğer sonraki != 0 AMA simdiki == -1 ise o zaman urunler.dat'dan ulaşılan ilk satışdayız demektir. Eğer yeni kaydedeceğimiz satış bu satıştan önce gelecekse o zaman urunler.dat'daki bağ da değişicek demektir ki işte bunun için bu özel şartı yerine getiren bir kod parçası yazacağım şimdi. */ for (sayac=0;sayac<6;sayac++) { oku.fatura_no[sayac] = fatura_no[sayac]; } for (sayac=0;sayac<6;sayac++) { oku.satis_tarihi[sayac] = satis_tarihi[sayac]; } oku.satis_miktari = satis_miktari; oku.birim_satis_fiyati = birim_satis_fiyati; oku.sonraki = sonraki; fseek(fp,0,2); /* Dosya sonuna ışınlan */ link_konum = (ftell(fp) / sizeof(SATIS)) + 1; fwrite(&oku,sizeof(SATIS),1,fp); if (simdiki == -1) { /* Önceki bağ düzelt */ fclose(fp); urun_guncelle(urun_kodu, ALIS_FIYAT_MIN - 1, STOK_LIMIT_MIN - 1, -2, link_konum); } else { fseek(fp,(simdiki-1) * sizeof(SATIS),0); fread(&oku, sizeof(SATIS),1,fp); fseek(fp,-sizeof(SATIS),1); oku.sonraki = link_konum; fwrite(&oku,sizeof(SATIS),1,fp); fclose(fp); } } else { /* Yok girilen kayıt dosyadakinden daha büyük değilse bir sıkıntı yok, taramaya devam... */ return satis_ekle(urun_kodu, fatura_no, satis_tarihi, satis_miktari, birim_satis_fiyati, oku.sonraki, sonraki); } } return 0; } int satis_listele(int urun_kodu, char ust_limit[6], char alt_limit[6]) { /* 0: Başarılı. */ /* -1: Dosya açılamadı. */ FILE *fp; SATIS oku; int sayac=0; int konum; printf("%d numarali urunun satis listesi\n",urun_kodu); printf("\n"); printf(" NO FATURA NO SATIS TARIHI SATIS MIKTARI BIRIM SATIS FIYATI\n"); printf("---- --------- ------------ ------------- ------------------\n"); konum = urun_guncelle(urun_kodu, ALIS_FIYAT_MIN-1,STOK_LIMIT_MIN-1,-1,LINK_GONDER); if (konum == -1) { printf("(hic satis kaydi yok.)\n"); return 0; } if ((fp=fopen ("satislar.dat","rb+"))== NULL) { return -1; } while (konum != -1) { fseek(fp,(konum-1) * sizeof(SATIS),0); fread(&oku,sizeof(SATIS),1,fp); konum = oku.sonraki; if (strncmp(oku.satis_tarihi,alt_limit,6) >= 0 && strncmp(oku.satis_tarihi,ust_limit,6) <= 0 && oku.fatura_no[0] != '|') { sayac++; printf("%4d %c%c%c%c%c%c %c%c%c%c%c%c %13d %18.4f \n",sayac,oku.fatura_no[0],oku.fatura_no[1],oku.fatura_no[2],oku.fatura_no[3],oku.fatura_no[4],oku.fatura_no[5],oku.satis_tarihi[0],oku.satis_tarihi[1],oku.satis_tarihi[2],oku.satis_tarihi[3],oku.satis_tarihi[4],oku.satis_tarihi[5],oku.satis_miktari,oku.birim_satis_fiyati); } } fclose(fp); } int satis_sil(int urun_kodu, char fatura_no[6]) { /* 1: Öyle bir fatura no yok */ /* 0: Başarılı. */ /* -1: Dosya açılamadı. */ FILE *fp; SATIS oku; int konum; konum = urun_guncelle(urun_kodu, ALIS_FIYAT_MIN-1,STOK_LIMIT_MIN-1,-1,LINK_GONDER); if (konum == -1) { return 1; } if ((fp=fopen ("satislar.dat","rb+"))== NULL) { return -1; } while (konum != -1) { fseek(fp,(konum-1) * sizeof(SATIS),0); fread(&oku,sizeof(SATIS),1,fp); konum = oku.sonraki; if (strncmp(oku.fatura_no,fatura_no,6) == 0) { /* EVET! Silinecek faturayı bulduk!!!!! */ fseek(fp,-sizeof(SATIS),1); oku.fatura_no[0] = '|'; fwrite(&oku,sizeof(SATIS),1,fp); fclose(fp); return 0; } } fclose(fp); return 1; } void listele() { /* Bu fonksiyon kontrol için, asıl programda işe yaramaz. */ FILE *fp; URUN urun; int sayac=0; int gecici; if ((fp=fopen ("urunler.dat","rb+"))== NULL) { printf("Urunler.dat acilamadi. Gidiyorum ben."); return -1; } fseek(fp,0,2); gecici = ftell(fp)/sizeof(URUN); printf("Kayit sayisi: %d\n\n", gecici); fseek(fp,0,0); for (sayac=1;sayac<=gecici;sayac++) { fread(&urun,sizeof(URUN),1,fp); printf("%3d %4d %20s %6.2f %2d %4d %2d\n",sayac,urun.urun_kodu,urun.urun_adi,urun.birim_alis_fiyati,urun.stok_miktari, urun.sonraki, urun.link); } fclose(fp); } void listele2() { /* Bu fonksiyon kontrol için, asıl programda işe yaramaz. */ FILE *fp; SATIS urun; int sayac=0; int gecici; if ((fp=fopen ("satislar.dat","rb+"))== NULL) { printf("satislar.dat acilamadi."); return -1; } fseek(fp,0,2); gecici = ftell(fp)/sizeof(SATIS); printf("Kayit sayisi: %d\n\n", gecici); fseek(fp,0,0); for (sayac=1;sayac<=gecici;sayac++) { fread(&urun,sizeof(SATIS),1,fp); printf("%3d %c%c%c%c%c%c %c%c%c%c%c%c %5d %6.2f %2d\n",sayac,urun.fatura_no[0],urun.fatura_no[1],urun.fatura_no[2],urun.fatura_no[3],urun.fatura_no[4],urun.fatura_no[5],urun.satis_tarihi[0],urun.satis_tarihi[1],urun.satis_tarihi[2],urun.satis_tarihi[3],urun.satis_tarihi[4],urun.satis_tarihi[5],urun.satis_miktari,urun.birim_satis_fiyati,urun.sonraki); } fclose(fp); } int main() { /* Acilis yazilari BASLANGICI */ printf("Umut BENZER\n"); printf("05-06-7670\n"); printf("Ege Universitesi Bilgisayar Muhendisligi 1. Sinif\n"); printf("https://ubenzer.com\n"); printf("Odev 4 (0.1)\n\n"); /* Acilis yazilari SONU */ int sag_serbest=-1; int sayac; int girdi; char girdi2[20]; float girdi3; int girdi4; char girdi5[6]; char girdi6[6]; char secenek; /* Girdi degiskenleri main fonksiyonun her bir yerinde farkli farkli bir sürü amaçla kullanıldığı için özel isimler vermedim. */ /* Dosyayi sifirdan yaratalim */ /* Odev kontrolunde kolaylik saglamasi acisindan dosyanin her acilista silinmesi ve tekrar yaratilmasi istendi. Programin gerceginde bunun iptal edilmesini saglamak icin asagidaki satirlar comment yapilabilir. */ FILE *fp; URUN yaz={-1,"",0,0,-1,-1}; remove ("urunler.dat"); // Eğer dosyalar varsa silinir. remove ("satislar.dat"); // Eğer dosyalar varsa silinir. if ((fp=fopen ("urunler.dat","w+b"))== NULL) { printf("Urunler.dat yaratilamadi. Gidiyorum ben."); return 0; } for (sayac=0;sayac

👋 🚨 Yeni yazılardan haberdar olmak ister misiniz? 👇

Ödev 4: Doğrudan Erişimli Dosyalarda Hashing ve Bağlaçlı Liste Yaklaşımı 4 yorum aldı.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir