Online Pazarlama Bloğu

Veri Yapıları ve Algoritmaları Dönem Projesi

February 14, 2014 • ☕️☕️☕️☕️ 20 dk okuma • 🏷 bilgisayar, yazılım

Geçtiğimiz dönem Veri Yapıları ve Algoritmaları (Data Structures and Algorithms) dersinin dönem projesi olarak, bir öğrenci bilgi sistemini yapılar (“struct”), bağlaçlı listeler(“linked list”) ve dosyalar(“file”) kullanılarak gerçekleştirdik. C ve temel veri yapılarını anlamada çok yararlı olan bu projeyi kendisini geliştirmek isteyenlerin yararlanması adına paylaşıyorum. Aşağıda Proje Metnini ve benim çözümümü bulabilirsiniz.


Proje Metni

Projede bir öğrenci işleri bilgi sistemi simülasyonunun yapılar (“struct”), bağlaçlı listeler(“linked list”) ve dosyalar (“file”) kullanılarak yapılması istenmektedir. Buna göre;

a) course olarak adlandırılan bir yapı oluşturun. Bu yapının üyeleri, code, name, instructor, term (Spring veya Fall değerleri alabilir), year ve bir course işaretçisi olsun. Öğrencilerin aldıkları dersler bağlaçlı liste ile tutulmak istendiğinden course veri yapısı elemanları üzerinde işlem yapacak void insertCourse(CourseNodePtr* cr, CourseNodePtr* inscr, char* code), char* deleteCourse(CourseNodePtr* cr, CourseNodePtr* inscr, char* code) prototipine sahip fonksiyonları yazınız. insertCourse() fonksiyonunu yazarken aynı öğrencinin aynı dersi birden fazla kez almasını engelleyiniz.

b) student olarak adlandırılan bir yapı oluşturun. Bu yapının üyeleri, id, name, surname, department, class (B.Sc., M.Sc., Ph.D. değerlerini alabilir), faculty, gpa, year, bir course işaretçisi ve bir student işaretçisi olsun. Öğrenciler bilgi sisteminde bağlaçlı liste ile tutulmak istendiğinden student veri yapısı elemanları üzerinde işlem yapacak void insertStudent(FILE* filePtr, StudentNodePtr* cr, int id), int deleteStudent(FILE* filePtr, StudentNodePtr* cr, int id) prototipine sahip fonksiyonları yazınız. insertStudent() fonksiyonunu yazarken aynı öğrencinin sisteme birden fazla kez girilmesini engelleyiniz. Hem insertStudent() fonksiyonunda hem de deleteStudent() fonksiyonlarında bağlaçlı listedeki elemanları filePtr ile işaret edilen main() fonksiyonu içinde açtığınız dosyanın içine yazınız. Böylece bağlaçlı listenizin en son hali bir dosya içinde de olacağından programınız farklı çalıştırmalarda da en son veritabanını kullanmış olacaktır.

c) Girilen öğrenci id’sine göre sistemde arama yapan ve eğer öğrenci sistemde mevcutsa onunla ilgili bilgileri ekranda gösteren bir void displayStudent(FILE* filePtr, int id) fonksiyonu yazınız. Fonksiyonunuz öncelikle dosyadan okuma yaparak öğrencileri bir bağlaçlı liste içine yerleştirmelidir. Daha sonra bu bağlaçlı liste üzerinde id’ye göre arama yapmalıdır ve eğer öğrenci mevcutsa onunla ilgili bilgileri ekranda göstermelidir. Örnek çıktı: Öğrencinin id’sini giriniz? > 2008199999 id Name Surname Department Class Faculty Gpa Year Recv. Courses 20 John White ICI M.Sc. Ege 82 2009 UBI501,UBI503,UBI505

d) Her bir öğrenci class’ına ait sistemde mevcut kayıtlı kaç adet öğrencinin bulunduğunu hesaplayan ve bunu ekranda uygun şekilde gösteren bir void displayClassNumbers(FILE* filePtr, int id) fonksiyonu yazınız. Fonksiyonunuz öncelikle dosyadan okuma yaparak öğrencileri bir bağlaçlı liste içine yerleştirmelidir. Daha sonra bu bağlaçlı liste üzerinde class değerlerine göre hesaplama yapmalıdır. Örnek çıktı: Class Number of Students B.Sc. 120 M.Sc. 55 Ph.D. 18

e) Girilen ders code’una, term değerine ve year değerine göre o dersi istenen dönem ve yıl içinde almış olan öğrencileri sistemde bulup ekranda gösteren bir void displayRecvCourse (FILE* filePtr, char* code, char* term, int year) fonksiyonu yazınız. Fonksiyonunuz öncelikle dosyadan okuma yaparak öğrencileri bir bağlaçlı liste içine yerleştirmelidir. Daha sonra bu bağlaçlı liste üzerinde değerlere göre arama yapmalıdır ve eğer öğrenci mevcutsa onunla ilgili bilgileri ekranda göstermelidir. Örnek çıktı: Dersin kodunu giriniz? > UBI503 Dönemi giriniz? > Fall Yılı giriniz? > 2008 id Name Surname 20 John White 25 Jeny McCain 29 Gregory Whitehead

f) a ve b şıkkında tanımlamış olduğunuz insertStudent(FILE* filePtr, StudentNodePtr* cr, int id) ve insertCourse(CourseNodePtr* cr, CourseNodePtr* inscr, char* code) fonksiyonunu kullanarak detaylı bir şekilde kullanıcıdan girdi alıp öğrenci kaydı yapan void registration(FILE* filePtr) fonksiyonu yazınız. Bu fonksiyon kullanıcıdan öğrenci ile ilgili bütün bilgileri aldıktan sonra onun kaydını gerçekleştirmelidir.

g) Bundan önceki yazdığınız bütün şıklardaki fonksiyonları kullanarak bir menu oluşturunuz. Menünüzün öğrenci kaydı girişi, öğrenci kaydı silme, arama gibi temel özellikleri içermesi gerekmektedir.


Proje Çözümü

/* Hüseyin Küçük
* Öğrenci İşleri Bilgi Sistemi
*/
#include
#include
#include

// Student yapısı
struct student{
int id;
char name[20];
char surname[20];
char department[20];
char clas[10];
char faculty[20];
int gpa;
int year;
struct course *coursePtr;
struct student *studentPtr;
};

// Course yapısı
struct course{
char code[10];
char name[30];
char instructor[30];
char term[10];
int year;
struct course *coursePtr;
};

// Kolay kullanabilir hale getirelim
typedef struct course Course;
typedef Course* CourseNodePtr;
typedef struct student Student;
typedef Student* StudentNodePtr;

// Fonksiyon prototype-larımız
void readFile(FILE* filePtr, StudentNodePtr* sPtr); // Veritabanındaki bilgileri belleğe taşıma
void readStudent(StudentNodePtr* sPtr, StudentNodePtr* readingPtr); // Dosyadan okunan öğrenci bilgilerinin belleğe, öğrenci listesine yazılması
void readCourse(CourseNodePtr* crSPtr, CourseNodePtr* crReadPtr); // Dosyadan okunan ders bilgilerinin belleğe, ders listesine yazılması
void registration(StudentNodePtr* sPtr); // Yeni öğrenci kayıt etme
StudentNodePtr insertStudent(StudentNodePtr *sPtr, int id); // Öğrenci ile ilgili bilgilerin alınıp, uygun şekilde listeye eklenmesi
void insertCourse(CourseNodePtr* cr, char* code); // Öğrencinin aldığı derslerin bilgilerinin alınıp listeye eklenmesi
void findStudent(StudentNodePtr* sPtr); // Öğrenci arama
void displayClassNumbers(StudentNodePtr* sPtr); // Öğrenci sınıflarında kaç kişinin olduğunun hesaplanması
void displayRecvCourse(StudentNodePtr* sPtr); // Belli bir dersi alan kişilerin listesi
void deleteStudent(StudentNodePtr* sPtr); // Öğrenci silme
void deleteCourse(StudentNodePtr* sPtr); // Ders silme
void writeDb(FILE* filePtr, StudentNodePtr* sPtr); // Bellekteki verileri dosyaya yazma

// Ana fonksiyonumuz
int main(void){
/* Tanımlamalarımız
* studentStartPtr : student yapısında bir kopya üretir. Bu yapımız aracılığı ile
dosyadaki verilerimizi bellekte tutacağız
* filePtr : dosyamıza ulaşmak için kullanacağımız pointer
* menu : menümüzden yapılan seçimi tutacağımız değişken
*/
StudentNodePtr studentStartPtr = NULL;
FILE *filePtr;
int menu;
// Veri dosyamızdaki tüm bilgileri daha rahat işlem yapabilmek adına linked-list-imiz
// aracılığı ile belleğimize çekiyoruz
readFile(filePtr, &studentStartPtr);
/* Menümüz
* 1: Yeni öğrenci ve ders kaydı
* 2: Öğrenci arama
* 3: Öğrenci silme
* 4: Öğrenci'nin aldığı derslerin arasından silme işlemi
* 5: Öğrenci sayısının sınıfa göre dağılımı
* 6: İstenen dersi alan öğrencilerin listesi
* 7: Çıkış
*/
do{
printf("\n\t------------------------------------------------------\n");
printf("\n\tSTUDENT INFORMATION SYSTEM \n\n");
printf("\tEnter 1 > Registration for Student and Courses\n");
printf("\tEnter 2 > Find a student\n");
printf("\tEnter 3 > Delete a student\n");
printf("\tEnter 4 > Delete a course from a student's courses\n");
printf("\tEnter 5 > Display class numbers\n");
printf("\tEnter 6 > Display received courses\n");
printf("\tEnter 7 > Exit\n");
printf("\n\t------------------------------------------------------\n");
printf("\tYour Choice > ");
scanf("%d", &menu); // Kullanıcının seçimi
// Kullanıcının seçimine göre işlemlere yönleniyoruz
switch(menu){
case 1:
registration(&studentStartPtr); break;
case 2:
findStudent(&studentStartPtr); break;
case 3:
deleteStudent(&studentStartPtr); break;
case 4:
deleteCourse(&studentStartPtr); break;
case 5:
displayClassNumbers(&studentStartPtr); break;
case 6:
displayRecvCourse(&studentStartPtr); break;
case 7:
writeDb(filePtr, &studentStartPtr); break;
}
}while(menu != 7);
return 0;
} // end main

/* return null
* Açıklama: Bu fonksiyon program başlatıldığı anda veritabanı dosyasındaki verileri
düzenli bir şekilde (öğrenci bilgilerini öğrenci listesine, ders bilgilerini ders
listesine) belleğe çekmektedir.
Bu fonksiyon çalışması anında readStudent() ve readCourse() fonksiyonlarını çağırmaktadır.
* Öncelikler: student.dat dosyasının oluşturulmuş ve okuma yazma izinlerinin verilmiş olması gerekmektedir.
*/
void readFile(FILE* filePtr, StudentNodePtr* sPtr){
int counter =0; // Öğrenciye bağlı tüm dersleri okumak için sayacımız
StudentNodePtr studentReadPtr;
StudentNodePtr currentPtr;
CourseNodePtr courseReadPtr;
// Dosyamızı içerisindeki verileri okuyabilecek şekilde hazırlıyoruz.
// Herhangi bir hata durumunda kullanıcıyı bilgilendiriyoruz
if((filePtr = fopen("student.dat", "rb")) == NULL){
printf("\n\tFile couldn't be opened!!!\n");
printf("1. If This is the first run or no data has been saved at first run, IGNORE this message.\n");
printf("2. If it's not the first run, check your file system permitions,\n avaible disk space and avaible memory space\n\n");
}else{
// Dosyanın içerisindeki tüm verileri okuyana kadar dosyada dolaşıyoruz
while(!feof(filePtr)){
// Bilgilerimizi tutmak için bellekten yer alıyoruz
if((studentReadPtr = malloc(sizeof(Student))) == NULL){
printf("No memory space");
}else{
// Öğrenci listemizin büyüklüğü kadar veri yapısını dosyamızdan okuyoruz
fread(studentReadPtr, sizeof(Student), 1, filePtr);
// Öğrenci yapımızın referans göstereceği öğrenci kaydını bilmediğimiz için null atıyoruz
studentReadPtr->studentPtr = NULL;
// Dosyadan gelen verileri öğrenci listemize yazıyoruz
readStudent(sPtr, &studentReadPtr);
// Öğrenciye bağlı ders kaydı var ise o bilgileri de listemize alıyoruz
if(studentReadPtr->coursePtr != NULL){
// Hafızamızda yer var mı? varsa az alalım
if((courseReadPtr = malloc(sizeof(Course))) == NULL){
printf("No memory space");
}else{
// Öğrenciye bağlı dersler bilinmediği için null
studentReadPtr->coursePtr = NULL;
// Ders bilgilerini okuyalım
fread(courseReadPtr, sizeof(struct course), 1, filePtr);
// Okunan dersin referans gösterdiği başka ders var ise sayaç 1
if(courseReadPtr->coursePtr != NULL){
counter = 1;
}else{
counter = 0;
}
// Okunan ders bilgileri belleğe alınıypr
readCourse(&(studentReadPtr->coursePtr), &courseReadPtr);
// Başka ders olduğu sürece okumaya devam ediyoruz
while(counter == 1){
// Bilgilerimizi tutmak için bellekten yer alıyoruz
if((courseReadPtr = malloc(sizeof(Course))) == NULL){
printf("No memory space");
}else{
// Veriyi dosyadan alıyoruz
fread(courseReadPtr, sizeof(struct course), 1, filePtr);
// Bu dersin referans gösterdiği başka ders var mı?
if(courseReadPtr->coursePtr != NULL){
counter = 1;
}else{
counter = 0;
}
// Okunan ders bilgileri belleğe alınıypr
readCourse(&(studentReadPtr->coursePtr), &courseReadPtr);
} // end if
} // end while
} // end if
} // end while
} // end if
} // end while
// Dosyamızı kapatıyoruz
fclose(filePtr);
} // end if
} // end readFile()

/* return null
* Açıklama: Fonksiyon dosyadan okuduğumuz öğrenci bilgilerini öğrenci listemize
eklemektedir.
* Öncelikler: Fonksiyon dosya içerisindeki verilerin doğru sıralanmış olduğu koşuluyla
verileri listenin süreli sonuna eklemektedir.
*/
void readStudent(StudentNodePtr* sPtr, StudentNodePtr* readingPtr){
StudentNodePtr newPtr = *readingPtr; // Dosyadan gelen verilerimiz
StudentNodePtr currentPtr = *sPtr; // Öğrenci listemizin başlangıç noktası
StudentNodePtr previousPtr = NULL; // Bir önceki işlem yapılan alan. Başlangıçta null
// Listemizin sonuna gidiyoruz
while(currentPtr != NULL){
previousPtr = currentPtr;
currentPtr = currentPtr->studentPtr;
}
// Daha önce listeye bir veri eklenmediyse yeni verimiz listemizin başına geliyor
if(previousPtr == NULL){
*sPtr = newPtr;
}else{ // Eğer listede önceden veri varsa yeni verimizi listenin sonuna ekliyoruz
previousPtr->studentPtr = newPtr;
} // end if
} // end readStudent()

/* return null
* Açıklama: Fonksiyon dosyadan okunan öğrenciye bağlı dersleri ders listesine eklemektedir.
* Öncelikler: Fonksiyon dosya içerisindeki verilerin doğru sıralanmış olduğu koşuluyla
verileri listenin süreli sonuna eklemektedir.
*/
void readCourse(CourseNodePtr* crSPtr, CourseNodePtr* crReadPtr){
CourseNodePtr newPtr = *crReadPtr; // Dosyadan okunan ders bilgileri
CourseNodePtr currentPtr = *crSPtr; // Ders listesinin başlangıcı ve dolaşma anında aktif olacak noktası
CourseNodePtr previousPtr = NULL; // Bir önceki noktamız başlangıçta null
newPtr->coursePtr = NULL; // Dersin referans edeceği dersi bilmediğimiz için null

// Ders listemizin sonunu belirliyoruz
while(currentPtr != NULL){
previousPtr = currentPtr;
currentPtr = currentPtr->coursePtr;
}
if(previousPtr == NULL){ // Liste boş ise yeni veri listenin başlangıcı oluyor
*crSPtr = newPtr;
}else{ // Liste boş değil ise listenin sonuna ekleme yapılıyor
previousPtr->coursePtr = newPtr;
} // end if
} // end readCourse()

/* return null
* Açıklama: Bu fonksiyon sisteme yeni öğrenci kaydı yapmamızı ve öğrencinin aldığı derslerin
kaydının yapılmasını sağlamaktadır.
* Fonksiyon işlem aşamasında öğrenciye bağlı ayrıntılı belgeleri alıp kaydetmek için insertStudent()
ve ders kayıdı yapmak için insertCourse() fonksiyonlarını çağırmaktadır.
* Fonksiyon bir sefer de 1 adet öğrenci kaydı yapabilmektedir. Fakat her öğrenciye istenilen sayıda ders
ataması yapılabilmektedir.
* Öncelikler: İstenilen bilgi alanlarına istenilen bilginin tipinde bilgi girileceği ön görülmüştür.
*/
void registration(StudentNodePtr* sPtr){
/* Tanımlamalar
* currentPtr : student yapımız içerisinde işlem yapma aşamasında gezinme işlemimiz sırasında
işlem yapılan geçerli alanı tutacak
* id : öğrenciin id-si
* yesNo : öğrenciye bağlı ders eklemeye devam edilip edilmeyeceğinin cevabı
* code : ders kodu
*/
StudentNodePtr currentPtr = *sPtr;
int id;
char yesNo;
char code[10];
printf("\n Student's Identification Number > ");
scanf("%d", &id);
// girilen id ile daha önceden herhangi bir kayıt oluşturulup oluşturulmadığına bakıyoruz
while((currentPtr != NULL) && (currentPtr->id != id)){
currentPtr = currentPtr->studentPtr;
}

// Eğer bu id ile daha önce kayıt yapıldı ise hata verdiriyoruz
if(currentPtr != NULL && currentPtr->id == id){
printf("\n ID is already in database. Try new one!\n");
}else{ // eğer bu id ile daha önce kayıt yapılmadıysa kayıt işlemine devam ediyoruz
/* insertStudent aracılığı ile öğrenci ile ilgili diğer bilgileri alarak listemize ekliyoruz
Bu fonksiyon bize eklenen veri bloğunun bilgilerini döndürecek.
Eklenen öğrencinin listedeki alanı döndürülerek ona bağlı derslerin kayıt edilmesi sağlanmakta
*/
currentPtr = insertStudent(sPtr, id);
// Birden fazla ders eklemesi yapılabileceği için do - while
do{
// Öğrenciye atanacak olan kurs kodunu alıyoruz
printf("\n\n Enter Course Code (Example: UBI503) > ");
scanf("%s", code);
/* Öğrenci listesinin course pointer adresini fonksiyonumuza gönderiyoruz.
Fonksiyon içerisinde derse ait diğer bilgilerin alınmasının ardından kaydedilecekleri
course listesinin başlangıç noktası bu değer olacak.
*/
insertCourse(&(currentPtr->coursePtr), code);
// Bir öğrenci birden fazla ders alabilir. Ders ekleme işleminin devam edip etmeyeceğini soruyoruz
printf("\n\n Do you want to continue to enter course(Y/N)? >");
yesNo = getch();
}while(yesNo == 'Y' || yesNo == 'y' );
} // end if
} //end registration()

/* return int
* Açıklama: Fonksiyon öğrenci kaydında öğrenci'nin bilgilerini almayı ve bu alınan bilgileri
öğrenci listesinde id-sine göre uygun olan yere yerleştirmektedir. Öğrenci bilgilerinin öğrenci
listesinde eklendiği alanın bilgisi öğrencinin aldığı derslerin kayıt aşamasında gerekli olduğu için
çıktı olarak gönderilmektedir.
* Öncelikler: İstenilen bilgi alanlarına istenilen bilginin tipinde bilgi girileceği ön görülmüştür.
*/
StudentNodePtr insertStudent(StudentNodePtr *sPtr, int id){
/* Tanımlamalar
* newPtr : kullanıcıdan alınacak verilerin tutulacağı student yapısı
* currentPtr : Başlangıç değeri üzerinde işlem yapacağımız ve dosyadan okuduğumuz verilerimizi
tutan listemizin ilk alanı olacak. Liste üzerinde gezinme yaparken o an üzerinde işlem yaptığımız
alan ifade edecek
* previousPtr : Liste üzerinde işlem yaparken o anki alandan önceki son alanımızı ifaed edecek
*/
StudentNodePtr newPtr;
StudentNodePtr currentPtr = *sPtr;
StudentNodePtr previousPtr = NULL; // Başlangıçta null çünkü herhangi bir gezinme yapılmadı
// Kayıtlarımız için hafızadan yer alıyoruz, yani almaya çalışıyoruz
if((newPtr = malloc(sizeof(Student))) == NULL){
printf("No memory space!!!"); // alamazsak hata veriyoruz, oha :D
}else{
newPtr->id = id; // öğrencinin id-sini yapımıza atıyoruz
// ve öğrenci ile ilgili diğer bilgileri almaya başlıyoruz
printf("\n Student Name > ");
scanf("%s", newPtr->name);
printf("\n Student Surname > ");
scanf("%s", newPtr->surname);
printf("\n Student Department > ");
scanf("%s", newPtr->department);
printf("\n Student Class (B.Sc., M.Sc., Ph.D.) > ");
scanf("%s", newPtr->clas);
printf("\n Student Faculty > ");
scanf("%s", newPtr->faculty);
printf("\n Student GPA > ");
scanf("%d", &(newPtr->gpa));
printf("\n Student Year > ");
scanf("%d", &(newPtr->year));
newPtr->studentPtr = NULL; // Bir sonraki adresi bilmediğimiz için null
newPtr->coursePtr = NULL; // Henüz ders eklemesi yapmadığımız için null

// Yeni veri yapımızdaki bilgilerin listemizde nereye yerleşeceğini belirliyoruz
while((currentPtr != NULL) && (newPtr->id > currentPtr->id)){
// Gezinme işlemi
previousPtr = currentPtr; // Şuan baktığımız kayıt en son bakılan oluyor
currentPtr = currentPtr->studentPtr; // Şuan baktığımız kaydın referans gösterdiği
// kayıt yeni şuanki kaydımız oluyor
}

// Verimizi listemize yerleştirelim
if(previousPtr == NULL){ // Eğer liste boş ise kaydımızı listenin başına ekliyoruz
newPtr->studentPtr = *sPtr;
*sPtr = newPtr;
// Kayıt noktamızı döndürüyoruz
return newPtr;
}else{ // Listenin herhangi bir alanına ekliyoruz
previousPtr->studentPtr = newPtr;
newPtr->studentPtr = currentPtr;
// Kayıt noktamızı döndürüyoruz
return newPtr;
}
} // end if
} // end insertStudent()

/* return null
* Açıklama: Fonksiyon yeni öğrenci kaydı sırasında öğrenciye bağlı derslerin ders listesine
uygun şekilde ders koduna göre eklenmesini sağlamaktadır.
* Öncelikler: İstenilen bilgi alanlarına istenilen bilginin tipinde bilgi girileceği ön görülmüştür.
*/
void insertCourse(CourseNodePtr* cr, char* code){
/* Tanımlamalar
* newPtr : Eklenecek ders'in bilgileri
* currentPtr : Ekleme yapılacak ders listemiz
* previousPtr : Ekleme aşamasında ders listesini gezinme işlemimizde en son işlem yapılan
ders listesi alanı
*/
CourseNodePtr newPtr;
CourseNodePtr currentPtr = *cr;
CourseNodePtr previousPtr;
// Daha önce bu ders'in öğrenciye atanıp atanmadığına bakıyoruz
while((currentPtr != NULL) && (strcmp(currentPtr->code, code) != 0)){
currentPtr = currentPtr->coursePtr;
}
// Eğer bu code ile daha önce kayıt yapıldı ise hata verdiriyoruz
if(currentPtr != NULL && strcmp(currentPtr->code, code) == 0){
printf("\n This course is already assinged. Please assign an other one or quit.\n");
}else{ /* Daha önce bu kod ile bir ders eklenmemiş ise ders ile ilgili diğer bilgileri de
alarak listemize ekliyoruz */
// Umarım hafızamızda yer vardır O_o
newPtr = malloc(sizeof(Course));
strcpy(newPtr->code, code);
printf("\n\t Course Name > ");
gets(newPtr->name); // Bu kod parçacığını iki kez yazmamdaki amaç; bir kez yazığımda
gets(newPtr->name); // hata alıyor olmamdır.
printf("\n\t Course Instructor Name > ");
gets(newPtr->instructor);
printf("\n\t Course Term (Spring/Fall) > ");
scanf("%s", newPtr->term);
printf("\n\t Course Year (2014) > ");
scanf("%d", &(newPtr->year));
newPtr->coursePtr = NULL; // Referans edeceği yeni alanı bilmediğimiz için null
previousPtr = NULL; // Bir önce işlem yapılan alan olmadığı için null
currentPtr = *cr; /* currentPtr-i başlangıçta gelen code ile daha önce bir kayıt
girilip girilmediğini belirlemek için kullanmıştık. Bu yüzden tuttuğu değer değişmişti.
Listemizi tekrardan dolaşmak ve yeni kaydın yerleşeceği yeri belirlemek için kayıt
yapacağımız listemizin ilk alanını atıyoruz */
// Yeni kaydın listemiz de nereye yerleşeceği belirliyoruz
while((currentPtr != NULL) && ((strcmp (newPtr->code, currentPtr->code)) == 1)){
previousPtr = currentPtr; // Şuan baktığımız kayıt en son bakılan oluyor
currentPtr = currentPtr->coursePtr; // Şuan baktığımız kaydın referans gösterdiği
// kayıt yeni şuanki kaydımız oluyor
}
// Verimizi listemize yerleştirelim
if (previousPtr == NULL){ // Eğer liste boş ise kaydımızı listenin başına ekliyoruz
newPtr->coursePtr = *cr;
*cr = newPtr;
}else{ // Listenin herhangi bir alanına ekliyoruz
previousPtr->coursePtr = newPtr;
newPtr->coursePtr = currentPtr;
}
} // end if
} //end insertCourse()

/* return null
* Açıklama: Fonksiyon girilecek id-ye göre öğrenci listesinde arama yapmaktadır.
Bulunan öğrencinin tüm bilgileri ve öğrenciye bağlı derslerin kodları listelenmektedir.
*/
void findStudent(StudentNodePtr* sPtr){
int id; // aranan öğrenci id-si
StudentNodePtr currentPtr = *sPtr; // Üzerinde işlem yapılan öğrenci listesi noktası
CourseNodePtr tempCoursePtr; // Öğrenci'nin course listesinde referans ettiği nokta
// Eğer öğrenci listemiz boş ise aranacak öğrenci de yok demektir
if(currentPtr == NULL){
printf("\n There is no student registration in DataBase!!!\n\n");
}else{
// Aranacak öğrenci id-sini alıyoruz
printf("\n Enter Student's ID > ");
scanf("%d", &id);
// Tüm listeyi kontrol ediyoruz, öğrenci bilgilerini bulabilmek için
while(currentPtr != NULL){
// Eğer aranan öğrenci listemizde var ise bilgilerini okuyabiliriz
if(currentPtr->id == id){
// Öğrenci'nin course listesinde referans ettiği noktayı tutuyoruz
tempCoursePtr = currentPtr->coursePtr;
printf("\n%-8s%-8s%-10s%-15s%-8s%-10s%-6s%-8s%-13s", "Id","Name","Surname","Department","Class","Faculty","Gpa","Year","Courses");
printf("\n%-8d%-8s%-10s%-15s%-8s%-10s%-6d%-8d",currentPtr->id, currentPtr->name, currentPtr->surname, currentPtr->department, currentPtr->clas, currentPtr->faculty, currentPtr->gpa, currentPtr->year);
// Referans aldığımız noktadan başlayarak tüm bağlı dersleri okuyoruz
while(tempCoursePtr !=NULL){
printf("%s, ", tempCoursePtr->code);
tempCoursePtr = tempCoursePtr->coursePtr;
} // end while
printf("\n");
// Öğrenciyi bulduğumuz noktadan sonraki kayıtlara bakmamıza gerek yok.
// Zamandan ve kaynak kullanımından tasarruf =)
break;
} // end if
// Öğrenciyi bulamadığımız sürece bir sonraki alana bakıyoruz
currentPtr = currentPtr->studentPtr;
} // end while
// Liste içerisinde öğrenci bulunamazsa olmadığını söylüyoruz
if(currentPtr == NULL){
printf("\n Student couldn't be found in DataBase!!!\n\n ");
}
} // end if
} // end findStudent()

/* return null
* Açıklama: Fonksiyon öğrenci listesinden id değerine göre öğrenci kaydı silme
işlemini yapmaktadır. Silme işlemi gerçekleşmeden önce arama fonksiyonundaki gibi
öğrenci bilgileri (aldığı dersler hariç) gösterilmektedir. Kullanıcının sildiği kayıttan
emin olması sağlanmaktadır.
Öğrenci bilgileri ile birlikte öğrencinin aldığı dersler de ders listesinden silinmektedir.
*/
void deleteStudent(StudentNodePtr* sPtr){
int id; // Silinmek istenen öğrenci'nin id-si
char yesNo; // Silme işlemi onayı
StudentNodePtr currentPtr;
StudentNodePtr previousPtr;
StudentNodePtr tempPtr; // Silinecek noktanın bilgisini tutacak
previousPtr = NULL;
currentPtr = *sPtr;
CourseNodePtr tempCoursePtr; // Öğrencinin derslerini silmede tampon
CourseNodePtr currentCoursePtr; // İşlem yapılan ders alanı
// Silinmek istenen öğrencinin id-sini alıyoruz
printf("\n Enter student's Id that you want to delete > ");
scanf("%d", &id);
// Öğrenci'nin listedeki yerini belirlemeye çalışıyoruz
while(currentPtr != NULL){
// Öğrenci'nin yerini belirlediğimiz anda silme işlemine başlıyoruz
if(currentPtr->id == id){
// Öğrenci'nin ders listesindeki ilk ders kaydının bilgisini alıyoruz
currentCoursePtr = currentPtr->coursePtr;
// Kullanıcının doğru kaydı silip silmediğini görebilmesi için öğrenci bilgilerini ekrana basıyoruz
printf("\nYou're about to delete following student !!!\n");
printf("\n%-8s%-8s%-10s%-15s%-8s%-10s%-6s%-8s","Id","Name","Surname","Department","Class","Faculty","Gpa","Year");
printf("\n%-8d%-8s%-10s%-15s%-8s%-10s%-6d%-8d",currentPtr->id, currentPtr->name, currentPtr->surname,
currentPtr->department, currentPtr->clas, currentPtr->faculty, currentPtr->gpa, currentPtr->year);
// Gerçekten silmek istiyor mu? istemiyor mu?
printf("\n\n Are you sure to delete (Y/N) > ");
yesNo = getch();
if((yesNo == 'y') || (yesNo == 'Y')){

// Öğrenciye bağlı tüm dersleri siliyoruz
while(currentCoursePtr != NULL){
tempCoursePtr = currentCoursePtr;
currentCoursePtr = currentCoursePtr->coursePtr;
free(tempCoursePtr); // Alanımızı bellekten kaldırıyoruz
}

if(id == (*sPtr)->id){ // Silinecek nokta listenin başlangıç noktası ise
tempPtr = *sPtr; // Silinecek alanı tutuyoruz
*sPtr = ( *sPtr )->studentPtr; // Listenin yeni başlangıç listesini silinecek
// alanın referans ettiği alan yapıyoruz
free(tempPtr); // Alanımızı listeden siliyoruz
}else{ // Silinecek nokta başlangıçtan farklı bir yerde ise
tempPtr = currentPtr;
previousPtr->studentPtr = currentPtr->studentPtr;
free(tempPtr); // Alanımızı listeden siliyoruz
//return id;
}
printf("\n\n STUDENT IS DELETED\n");
} // end if
// Öğrenciyi bulduğumuz noktadan sonrasına bakmaya gerek yok
break;
}/*end if*/
// Listeyi dolaşma işlemine devam ediyoruz.
previousPtr = currentPtr;
currentPtr = currentPtr->studentPtr;
} // end while
if(currentPtr == NULL){ // Eğer id listede yok ise yok diyoruz =)
printf("\n Student's ID is not in database!");
}
} // end deleteStudent()

/* return null
* Açıklama: Fonksiyon öğrenci listesinde kayıtlı olan bir öğrenciye atanmış dersler
arasından herhangi bir veya daha fazlasını silme işlemini yapmakltadır.
Girilen id değerine göre öğrenci listesinde bulunan öğrencinin bilgileri ev aldığı derslerin
kodları kullanıcının rahat işlem yapabilmesi adına listelenmektedir.
Kullanıcının gireceği ders koduna göre ders listesinden ilgili dersi silme işlemi gerçekleştirilmektedir.
*/
void deleteCourse(StudentNodePtr* sPtr){
/* Tanımlamalar
id: Öğrenci'nin id-si
wannaDeleteCode : Silinecek course kodu
yesNo : Silme işlemi onayı
currentPtr : Öğrenci listesi'nin o anda işlem yapılan alanı
currentCoursePtr : Üzerinde işlem yapılan ders alanı
tempCoursePtr : Silinecek ders bilgisi
previousCoursePtr : Bir önce üzerinde işlem yapılan ders alanı
*/
int id;
char wannaDeleteCode[10];
char yesNo;
StudentNodePtr currentPtr = *sPtr;
CourseNodePtr currentCoursePtr;
CourseNodePtr tempCoursePtr;
CourseNodePtr previousCoursePtr;
// Öğrenci listemiz boş ise herhangi bir işlem yapamayız
if(currentPtr == NULL){
printf("\n There is no student registration in DataBase!!!\n\n");
}else{
// Ders kaydını sileceğimiz öğrencinin id-sini alıyoruz
printf("\n Enter Student's ID which you want to delete his/her course > ");
scanf("%d", &id);
// Öğrenci listemizi dolaşıyoruz, istenen öğrencinin bilgilerini bulabilmek için
while(currentPtr != NULL){
// Öğrencinin listedeki yerini bulduk isek işlemlere başlayalım
if(currentPtr->id == id){
// Öğrenci'nin ders listesindeki ilk ders kaydının bilgisini alıyoruz
currentCoursePtr = currentPtr->coursePtr;
// Öğrenci bilgilerini kullanıcıya sunalım ki doğru öğrenci üzerinde işlem yaptığından emin olsun
printf("\n%-8s%-8s%-10s%-15s%-8s%-10s%-6s%-8s%-13s", "Id","Name","Surname","Department","Class","Faculty","Gpa","Year","Courses");
printf("\n%-8d%-8s%-10s%-15s%-8s%-10s%-6d%-8d",currentPtr->id, currentPtr->name, currentPtr->surname, currentPtr->department, currentPtr->clas, currentPtr->faculty, currentPtr->gpa, currentPtr->year);
// Öğrenciye bağlı dersleri yazdıralım
while(currentCoursePtr !=NULL){
printf("%s, ", currentCoursePtr->code);
currentCoursePtr = currentCoursePtr->coursePtr;
if(currentCoursePtr == NULL){
printf("\n");
}
}
// Silinmek istenen ders'in kodu-nu alalım
printf("\n Enter Course Code which you want to delete > ");/*course code is got from user*/
scanf("%s", wannaDeleteCode);
/* Dersleri yazdırma aşamasında ders başlangıç noktamızı kaybettiğimiz için
başlangıç noktamızı yeniden alıyoruz */
currentCoursePtr = currentPtr->coursePtr;
// Silinmek istenen dersin alanını bulabilmek için listeyi sonuna kadar dolaşıyoruz
while(currentCoursePtr != NULL){
// Dersin yerini belirlediysek silme işlemine başlıyoruz
if(strcmp(currentCoursePtr->code, wannaDeleteCode) == 0){
// Kullanıcı dersi silmekten gerçekten emin mi?
printf("\n Are you sure to delete (Y/N) ? >");
yesNo = getch();
// Emin ise silme işlemine geçelim
if((yesNo == 'y') || (yesNo == 'Y')){
// Silinecek nokta listenin başlangıcı ise
if(strcmp(currentPtr->coursePtr->code, wannaDeleteCode) == 0){
tempCoursePtr = currentPtr->coursePtr; // Silinecek alanımızı tutuyoruz
currentPtr->coursePtr = currentPtr->coursePtr->coursePtr; // Silinecek alanın referans gösterdiği alanı
// listenin başlangıç npktası yapıyoruz
free(tempCoursePtr); // Alanımızı bellekten kaldırıyoruz
printf("\n\n > COURSE IS DELETED\n");
// Dersi bulduğumuz noktadan sonrasına bakmaya gerek yok
break;
}else{ // Silinecek nokta başlangıçta değilse
tempCoursePtr = currentCoursePtr;
previousCoursePtr->coursePtr = currentCoursePtr->coursePtr;
free(tempCoursePtr); // Alanımızı bellekten kaldırıyoruz
printf("\n\n > COURSE IS DELETED\n");
// Dersi bulduğumuz noktadan sonrasına bakmaya gerek yok
break;
}
} // end if
} // end if
// Listemizi dolaşmaya devam ediyoruz
previousCoursePtr = currentCoursePtr;
currentCoursePtr = currentCoursePtr->coursePtr;
} // end while
// İstenen code ile öğrenciye ders ataması yapılmamış ise uyarıyoruz
if(currentCoursePtr == NULL){
printf("\n This course is not assigned to this student!");
break;
}
// Dolaşmaya evam etmemize gerek yok
break;
} // end if
// Öğrenciyi bulmak için listeyi dolaşmaya devam ediyoruz
currentPtr = currentPtr->studentPtr;
} // end while
// Öğrenci listede yok ise uyarıyoruz
if(currentPtr == NULL){
printf("\n Student couldn't be found in DataBase!!!\n\n ");
}
} // end if
} // end deleteCourse()

/* return null
* Açıklama: Fonksiyon sınıf dönemlerinde kaç adet öğrencinin olduğunu hesaplamakta
ve ekrana yazdırmaktadır.
*/
void displayClassNumbers(StudentNodePtr* sPtr){
StudentNodePtr currentPtr = *sPtr; // Öğrenci listesi başlangıç noktası
int bsc = 0; // B.Sc. olan kişi sayısı
int msc = 0; // M.Sc. olan kişi sayısı
int phd = 0; // Ph.D. olan kişi sayısı
// Öğrenci listesinin tamamını dolaşıyoruz
while(currentPtr != NULL){
// Tipe göre değer arttırmalarımızı yapıyoruz
if(strcmp(currentPtr->clas, "B.Sc.") == 0){
bsc++;
}else if(strcmp(currentPtr->clas, "M.Sc.") == 0){
msc++;
}else if(strcmp(currentPtr->clas, "Ph.D.") == 0){
phd++;
} // end if
// Listeyi dolaşmaya devam ediyoruz
currentPtr = currentPtr->studentPtr;
} // end while
// Sonuçları ekrana basıyoruz
printf("\n\t%-10s%-25s\n","CLASS", "NUMBER OF STUDENTS");
printf("\t%-10s%-25d\n", "B.Sc.", bsc);
printf("\t%-10s%-25d\n", "M.Sc.", msc);
printf("\t%-10s%-25d\n", "Ph.D.", phd);
printf("\n\t> LISTED");
} // end displayClassNumbers()

/* return null
* Açıklama: Fonksiyon kullanıcının gireceği ders kodu, ders dönemi ve yılı bilgileri
ile kısıtlanan arama koşulunda bu dersi alan öğrencileri listelemektedir.
* Öncelikler: İstenilen bilgi alanlarına istenilen bilginin tipinde bilgi girileceği ön görülmüştür.
*/
void displayRecvCourse(StudentNodePtr* sPtr){
StudentNodePtr currentPtr = *sPtr; // Öğrenci listesi başlangıcı
CourseNodePtr courseCurrentPtr; // Ders listesi o anki noktası
char courseCode[10]; // İstenen dersin kodu
char courseTerm[10]; // İstenen dersin dönemi
int courseYear; // İstenen dersin yılı
// Kullanıcıdan ders kriterlerini alalım
printf("\n\tCourse Code > ");
scanf("%s", courseCode);
printf("\n\tCourse Term > ");
scanf("%s", courseTerm);
printf("\n\tCourse Year > ");
scanf("%d", &courseYear);
printf("\n\t%-10s%-20s%-20s\n","ID", "NAME", "SURNAME");
// Öğrenci listesinin tamamını dolaşalım
while(currentPtr != NULL){
// Üzerinde işlem yapılan öğrenciye bağlı ders listesi alanı
courseCurrentPtr = currentPtr->coursePtr;
// Başlangıç liste noktası ve buna bağlı alanların gezerek ders kriterlerimize uygun
// ders olup olmadığına bakıyoruz
while(courseCurrentPtr != NULL){
// O an üzerine işlem yaptığımız ders'in bilgileri kriterlerimize uygun ise ekrana yazdırıyoruz
if((strcmp(courseCurrentPtr->code, courseCode) == 0) && (strcmp(courseCurrentPtr->term,courseTerm) == 0) && (courseCurrentPtr->year == courseYear)){
printf("\t%-10d%-20s%-20s\n", currentPtr->id, currentPtr->name, currentPtr->surname);
// Bir tane uyan bulmamız, öğrencinin o dersi aldığının kanıtı. Diğer dersleri dolaşmamıza gerek yok.
break;
}
// Bakılan kriterlere uygun ders değil ise bir diğer ders ile aramaya devam ediyoruz
courseCurrentPtr = courseCurrentPtr->coursePtr;
} // end while
// Diğer öğrenci'nin dersi alıp almadığına bakıyoruz
currentPtr = currentPtr->studentPtr;
} // end while
printf("\n\t> LISTED");
} // end displayRecvCourse()

/* return null
* Açıklama: Bu fonksiyon kullanıcının sistemden çıkışı sırasında bellekte bulunan
öğrenci ve ders listesi içerisindeki bilgileri veritabanımız olan student.dat
dosyası içerisine kaydetmektedir.
*/
void writeDb(FILE * filePtr, StudentNodePtr * sPtr){
StudentNodePtr currentPtr = *sPtr; // Öğrenci listesinin başlangıç noktası
CourseNodePtr tempCoursePtr; // Öğrenciye bağlı dersleri dolaşmada kullanılacak nokta tutucu

// Veritabanı olarak kullanacağımız dosyayı işlem yapılabilir hale getirelim
if((filePtr = fopen("student.dat", "r+")) == NULL){
printf("\n file can't be opened!!!\n");
}else{
// Öğrenci listesinin tamamını dolaşalım
while(currentPtr != NULL){
// Öğrenciye bağlı derslerin ders listesindeki başlangıç noktasını tutalım
tempCoursePtr = currentPtr->coursePtr;
// O anki öğrencinin bilgilerini dosyamıza yazalım
fwrite(currentPtr, sizeof(struct student), 1, filePtr);
// Öğrenciye bağlı tüm dersleri de dosyamıza yazalım
while(tempCoursePtr != NULL){
// Bilgileri dosyaya yazalım
fwrite(tempCoursePtr, sizeof(struct course), 1, filePtr);
// Bir sonraki derse geçelim
tempCoursePtr = tempCoursePtr->coursePtr;
}
// Bir sonraki öğrenciye geçelim
currentPtr = currentPtr->studentPtr;
} // end while
} // end while
close(filePtr); // Dosyamızı kapatalım
printf("\n Data has been saved to the student.dat File\n");
} //end writeDb()