Üniversite otomasyonuna kayıtlı öğrencileri listeleme

C üzerinden yazdığım üniversite otomasyonuna kayıtlı tüm öğrencileri öğrenci numarasına göre küçükten büyüğe listelemek istiyorum, yardımcı olabilir misiniz?

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


char const  FILE_NAME[] = "OGRENCI.TXT";
char const  BOS[]       = "\r\r\r\r\r\r\r";
#define     ANHTR_UZ    7
char const  AKD[]       = "%7s";
#define     ISIM_UZ     15
#define     KAYIT_BOYU  ((long)(ANHTR_UZ+ISIM_UZ+4))
char const  KKD[]       = "%7s%15s%4d";

struct kayit {
  char anhtr[ANHTR_UZ+1], isim[ISIM_UZ+1];
  int  yil;
};


char   satir[2];
FILE * dg;

int dizioku             
  (char d[], int u)
{
  int  i, c;

  for (i=0; (c=getchar())!='\n'; i++)
    if (i<u)
      d[i] = c;
  for (; i<u; i++)
    d[i] = '\0';
  d[u] = '\0';
  return d[0];
}  

long bul                
  (char const anhtr[])  
{
  int   drm, kar = 1;
  long  dns;
  char  d1[ANHTR_UZ+1], d2[ANHTR_UZ+1];

  sprintf(d2, AKD, anhtr); 
  dg = fopen(FILE_NAME, "rb");
  if (dg == NULL)
    return -1L;
  drm = fseek(dg, -KAYIT_BOYU, SEEK_END);
  while (drm == 0 && fgets(d1, ANHTR_UZ+1, dg) != NULL  &&
    (kar=strcmp(d2,d1)) != 0)
      drm = fseek(dg, -KAYIT_BOYU-ANHTR_UZ, SEEK_CUR);
  dns = (kar == 0) ? ftell(dg)-ANHTR_UZ : -1L;
  fclose(dg);
  return dns;
}  

void ekleme (void)
{
  long          konum;
  struct kayit  k;
  int           scd;

  puts("Eklenecek ogrenci numarasini girin:");
  dizioku(k.anhtr, ANHTR_UZ);
  if (bul(k.anhtr) == -1L) {
    puts("Ogrenci adini girin:");
    dizioku(k.isim, ISIM_UZ);
    do {
      puts("Kayit yilini girin:");
      scd = scanf("%d", &k.yil);
      dizioku(satir, 0);   
    } while (1!=scd || k.yil<1980 || k.yil>9999);
    konum = bul(BOS);
    dg = fopen(FILE_NAME, "ab");  
    fclose(dg);
    dg = fopen(FILE_NAME, "r+b");
    if (konum == -1L)
      fseek(dg, 0L, SEEK_END);    
    else
      fseek(dg, konum, SEEK_SET); 
    fprintf(dg, KKD, k.anhtr, k.isim, k.yil);
    fclose(dg);
    puts("Ekleme islemi tamamlandi.");
  }
  else
    fprintf(stderr, "Ogrenci zaten eklenmis!\n\a");
}  

void goruntuleme (void)
{
  long          konum;
  struct kayit  k;

  puts("Goruntulenecek ogrenci numarasini girin:");
  dizioku(k.anhtr, ANHTR_UZ);
  if ((konum = bul(k.anhtr)) != -1L) {
    dg = fopen(FILE_NAME, "rb");
    fseek(dg, konum+ANHTR_UZ, SEEK_SET);
    printf("Ogrenci adi: %s\n", fgets(k.isim,ISIM_UZ+1,dg));
    fscanf(dg, "%d", &k.yil);
    fclose(dg);
    printf("Kayit yili : %d\n", k.yil);
  }
  else
    fprintf(stderr, "Ogrenci bulunamadi!\n\a");
}  

int menu (void)
{
  int  secenek;

  do {
    puts("\n\t1.EKLEME\n\t2.GORUNTULEME"
      "\n\t0.CIKIS");
    printf("Seciminizi yapin:");
  } while ((secenek=dizioku(satir,1))<'0' || secenek>'2');
  putchar('\n');
  return secenek - '0';
}  

int main (void)
{
  static void (*fd[])(void) = { (void (*)(void)) exit,
    ekleme, goruntuleme };

  while (1)
    (*fd[menu()])();
  return 0;
} 

Merhaba, gördüğüm kadarıyla
struct kayıt OGRENCI_LISTESI[1000] gibi bir şey yok.

Ben olsaydım önce dosyanın öğrenebiliyorsak kaç bayt olduğunu öğrenip bu öğrendiğim bilgiyi sizeof(struct kayit) a bölerek oluşturacağım dizinin kaç elemandan oluşacağını bulurdum. Ondan sonra yukarıda yazdığım şekilde bir dizi(ama dynamic dizi bahsettiğim şey, static değil) oluştururum. Ondan sonra da bu diziyi kullanarak bubble sort vs. yaparak teker teker öğrenci bilgilerini sıralayarak ya print ederim ya da dosyaya bastırırım. Ha bu arada dynamic dizi oluşturmak istemiyorsanız da

struct kayıt OGRENCI_LISTESI[1000000];

şeklinde bir dizi tanımlarsınız, daha sonra ise dosyadan her eleman okudugunuzda dizinin uzunluğunu da 1 artırarak yine işlem yapabilirsiniz.

Ha bu arada şimdi fark ettim de, realloc , yukarıda anlattığım dosyanin kaç bayt olduğunu öğrenme zorunluluğunu giderir sanırım.

realloc ile tahsis ettiğiniz hafıza alanını yeniden ayarlayabilirsiniz. Netten araştırırsınız onu bence.
Pseudo

int length = 0;
struct kayit* LISTE = (struct kayit*) malloc(length*sizeof(struct kayit));

while:
   data = read file
    length++
     realloc(length*sizeof(...))
     LISTE[length-1] = data

Struct dizisi (struct kayit *kayitlar) dogru cozum fakat dosya uzunlugu ve iceriginin struct’larin hafizadaki sekillerinden bagimsiz olmasi lazim. Ama zaten uzunluga bakmak yerine dosyayi program acilisinda bastan sona okuyup kayit’lara gecirmek daha kolay. Kisaca database’i dinamik aloke tutup save ve load fonksiyonlari yazmaktan bahsediyorum.

Bir alternatif de dosyayi insertion sort gibi bir mekanizmayla surekli sirali tutup kayitlari hic hafizaya almamak (su anki kod gibi). Dosya ortasina byte eklemek (sonraki byte’lari kaydirmak) mumkun mu bile, bilmiyorum.

Bunun disinda genel olarak:

  • C89 baya eski. Ozel bir gereksinim yoksa degiskenleri kullanildiklari yerde, loop icinde vs. tanimlamak daha iyi.
  • Genel olarak degisken ve parametre isimleri daha okunakli olabilir.
  • Tek statement’lik bloklarda bile {} kullanmak iyi bir aliskanlik. (Sahsi fikir)
  • Kodun gereginden fazla bir kismi durum kontrolu ifadelerinin icine girmis. Onlari disari cikartmak kodu cok daha okunabilir kilacaktir. (Mesela do…while’in icindeki secenek atamasi while’in hemen ust satirina alinabilir.)
  • Gordugum en temiz “odev seviyesi” C kodu olabilir. Bravo.

malloc’un donus degerini cast etmek kotu bir aliskanlik. (Header include etmeyi unutursan bu hatayi maskeliyor.)

1 Beğeni

Cevaplarınız için teşekkür ederim kısıtlı zamanım olan bir final projesi üzerine çalışıyordum projeyi yarım hali ile teslim ettim, ama yine de kodları inceleyim düzelteceğim.