C'de Dosyalama(Yardım)
-
#include<stdio.h> #include<locale> FILE *dsy; char TCNo[11]; char ad[20]; char soyad[20]; char odaNo[10]; char tarih[11]; int giris=0; int main() { //Türkçe karakterler setlocale(LC_ALL,"TURKISH"); //Dosya oluşturma & açma dsy = fopen("hastalistesi.dat","a+"); //Menü while((giris!=5)) { printf(" MENÜ\n----------------\n[1]Kayıt ekle\n[2]Kayıt düzenle\n[3]Kayıt sil\n[4]Kayıt bul\n[5]Çıkış\n"); scanf("%d",&giris); if(giris==5) { break; } else if(giris==1) { printf ("T.C. No:\n"); fgets (TCNo,11,stdin); fputs (TCNo,dsy); printf ("Ad:\n"); fgets (ad,20,stdin); fputs (ad,dsy); printf ("Soyad:\n"); fgets (soyad,20,stdin); fputs (soyad,dsy); printf ("Oda No:\n"); fgets (odaNo,10,stdin); fputs (odaNo,dsy); printf ("Tarih:\n"); fgets (tarih,11,stdin); fputs (tarih,dsy); fclose (dsy); } else if(giris==2) { fclose (dsy); } else if(giris==3) { fclose (dsy); } else if(giris==4) { fclose (dsy); } else printf("Yanlış giriş!!!\n\n"); } }
--------------------------------------------------------------
Yazdığım kod henüz bu kadar.Önümde 2 hafta falan var daha teslim etmek için.Zaman bol olunca sallaya sallaya yapıyorum tabi işin aslı :D eksiklerimde var ayrıca,işin içinden tam çıkamıyorum...Şimdi bu kodlar hastalistesi.dat dosyasını oluşturup kayıt yapıyo ama her değişken bir alt satıra kayıt oluyo. Ve bir problemde şu ki ben arama yaptırdığım zaman bulunan tc kimlik no değerine ait tüm bilgiler gelmeli ama nasıl olacak? Birde kodları çalıştırırsanız görürsünüz,tc no sormadan direk ad soruyo. Bunları nasıl halledebilirim,bi yol gösterin :/
-
Öncelikle son sorunun sebebi şu, scanf veri okurken enter tuşunu (\n) okumaz, doğal olarak bu stdin de kalır, sonraki fonksiyon, scanf , fgets vb veri okumaya kalktığında bu \n karakterini görür ve onu okuyarak sonlanır. Bu karakteri stdin den silmek için çeşitli yollar var, mesela fflush fonksiyonu kullanılır genelde ancak input stream için bu fonksiyon tanımsız davranışlıdır (undefined behavior), yani tüm derleyiciler bu fonksiyon ile stdin buffer ini boşaltmana izin verir ancak standartlarca garanti edilmez. Bu yüzden diğer yöntemlerden birisini kullan, scanf den sonra, getchar ile o karakteri oku ve buffer i boşalt.
...
scanf("%d",&giris);
getchar();
...
Altalta yazma meselesine gelince, bu fgets ile ilgili, scanf in aksine fgets girişten veriyi okuduktan sonra enter tuşunu da (\n) okur, doğal olarak stringin sonunda bu karakterde olur. sen bunu dosyaya yazdığın zaman doğal olarak sonraki veri bir alt satırdan başlar.
Aslında bu iyi bişey, çünkü verileri yan yana tutarsan, ayraç olarak boşluk kullanmak zorundasın ve dosyadan okuma için fscanf kullanmalısın. fscanf boşluğa göre verileri ayıracak ama mesela iki isimli (ali osman gibi) kişilerde bu sorun olur.
Aramayı senin kodu etkilemeden şu şekilde yazabilirim, fseek ile dosya başına konumlan, counter 5 in katı ise, o okunan veri tc no dur. her veri okumada counter i bir arttır, tc no yu okuduğunda aranan ile strcmp kullanarak karşılaştır, aynı ise bulundu yaz ve sonraki 4 veriyi de ekrana yaz. counter e -1 koy ve döngüden çık. döngüden 2 şekilde çıkılabilir, ya dosya sonlanır, ya da kayıt bulunmuştur, kayıt bulunduysa counter -1 dir, aksi halde pozitif bir sayı. döngü sonunda counter in değerine göre döngüden ne şekilde çıkıldığı anlaşılabilir ve eğer kayıt bulunamamışsa (counter != -1) bulunamadı yazılır.
kodu yazmadan önce bir kaç tavsiye.
- Eğer yapıları gördüyseniz kullanıcı bilgilerinin hepsini tek bir yapı içinde tut.
- fonksiyonları gördüyseniz kullanıcı seçeneğini girdiğinde yapılacak olan işi ayrı bir fonksiyon olarak yaz ve yapı adresini parametre olarak yolla.
- dosyayı binary olarak aç, yapının toplam boyutuna göre kaydı dosyadan fread ile oku ve okunan veri doğrudan yapıya aktarılsın.
- her seçenekten sonra dosyayı açıp kapama yapma, birkez aç ve kayıttan sonra fflush ile bufferi boşaltarak tüm verinin diske yazılmasını sağla.
- karakter dizilerini 10-20 baytlık yapma en az 128 olsun, mesela tc no 11 hane, eğer 9 hane girersek \n i de alıyor ve dosyaya yazıyor, ancak 11 hane girersek sadece tam olarak tc no yu alıyor ve sonraki girdi dosyada tc no ile bitişik oluyor. fgets de pek kaliteli bir fonksiyon sayılmaz. (cogu standart C fonksiyonu gibi)
kod :
#include <stdio.h> FILE *dsy; char TCNo[128]; char ad[128]; char soyad[128]; char odaNo[128]; char tarih[128]; int giris=0; int main() { //Dosya oluşturma & açma dsy = fopen("hastalistesi.dat","a+"); //Menü while((giris!=5)) { printf(" MENU\n----------------\n[1]Kayit ekle\n[2]Kayit duzenle\n" "[3]Kayit sil\n[4]Kayit bul\n[5]Cikis\n"); scanf("%d",&giris); getchar(); // dikkat if(giris==5) { break; } else if(giris==1) { printf ("T.C. No\t: "); fgets (TCNo,11,stdin); fputs (TCNo,dsy); printf ("Ad\t: "); fgets (ad,20,stdin); fputs (ad,dsy); printf ("Soyad\t: "); fgets (soyad,20,stdin); fputs (soyad,dsy); printf ("Oda No\t: "); fgets (odaNo,10,stdin); fputs (odaNo,dsy); printf ("Tarih\t: "); fgets (tarih,11,stdin); fputs (tarih,dsy); fflush(dsy); // dikkat. } else if(giris==2) { fclose (dsy); } else if(giris==3) { fclose (dsy); } else if(giris==4) { char tmp[128] , tc[128]; int counter = 0; fseek(dsy,0,SEEK_SET); // dosya basina konumlan printf("aranacak tc no: "); fgets(tc,sizeof(tc),stdin); while(!feof(dsy)) // dosya sonuna gelindi mi? { fgets(tmp,sizeof(tmp),dsy); // dosyadan satir oku if( counter++ %5 == 0) { if(!strcmp(tc,tmp)) // tc kimlik no bu mu { printf("--Bulundu--\a\n"); printf("Ad\t: %s",fgets(tmp,sizeof(tmp),dsy)); printf("Soyad\t: %s",fgets(tmp,sizeof(tmp),dsy)); printf("Oda No\t: %s",fgets(tmp,sizeof(tmp),dsy)); printf("Tarih\t: %s",fgets(tmp,sizeof(tmp),dsy)); printf("\n\n"); counter = -1; // bulundu break; } } } if(counter != -1) // donguden ne sekile cikildi { printf("Bulunamadi!\a\n\n"); } fseek(dsy,0,SEEK_END); } else printf("Yanlış giriş!!!\n\n"); } }
-
Çok sağol demek istediklerini anladım.
EDİT: string.h ekleyince sorun düzeldi.verdiğin kodlarda arama işi tamam ama kayıtta haala sorun var tcden sonra ad ve soyadı birlikte soruyo,değerlerden biri null oluyo bu seferde bi sonraki kayıdın bilgileriyle karışıyo önceki kayıt. Çözmeye çalışıcam...
-
#include<stdio.h>
#include<locale>
FILE *dsy;
char TCNo[11];
char ad[20];
char soyad[20];
char odaNo[10];
char tarih[11];
int giris=0;
int main()
{
//Türkçe karakterler
setlocale(LC_ALL,"TURKISH");
//Menü
while((giris!=5))
{
printf(" MENÜ\n----------------\n[1]Kayıt ekle\n[2]Kayıt düzenle\n[3]Kayıt sil\n[4]Kayıt bul\n[5]Çıkış\n");
scanf("%d",&giris);
if(giris==5)
{ break;
}
else if(giris==1)
{
//Dosya oluşturma & açma
dsy = fopen("hastalistesi.dat","a+");
printf ("T.C. No:\n");
scanf("%s",&TCNo);
fprintf(dsy,"%s ",TCNo);
printf ("Ad:\n");
scanf("%s",&ad);
fprintf(dsy,"%s ",ad);
printf ("Soyad:\n");
scanf("%s",&soyad);
fprintf(dsy,"%s ",soyad);
printf ("Oda No:\n");
scanf("%s",&odaNo);
fprintf(dsy,"%s ",odaNo);
printf ("Tarih:\n");
scanf("%s",&tarih);
fprintf(dsy,"%s\n",tarih);
fclose (dsy);
}
else if(giris==2)
{
//Dosya oluşturma & açma
dsy = fopen("hastalistesi.dat","a+");
fclose (dsy);
}
else if(giris==3)
{
//Dosya oluşturma & açma
dsy = fopen("hastalistesi.dat","a+");
fclose (dsy);
}
else if(giris==4)
{
//Dosya oluşturma & açma
dsy = fopen("hastalistesi.dat","a+");
fclose (dsy);
}
else
printf("Yanlış giriş!!!\n\n");
}
}----------------------
hocam kodlarda oynama yaptım biraz. umarım fputs ve fgets stdin ile yapman gerekmiyordur bunu. fopenları her case in başına koydum çünkü sadece program ilk açıldığında dosyanı çağırırsın. case bittikten sonra kapanır döngünün dışında açıldığı için bir daha işlem yapılamaz.
sanırsam kayıt bulmayı olayında da string.h kütüphanesine ihtiyacın olacak. onu çağırman lazım
-
Benim verdiğim kodu hem mingw hem visual C++ ile derledim, kayıtta herhangi bir sıkıntı yok, scanf den kaynaklanan sorunu ve çözümünü ilk mesajda göstermiştim zaten, scanf \n karakterini girişte bıraktığı için TC no isteyen fgets, \n karakterini girişten alıp direkt sonlanıyor ve sonraki fgets çağırılıyordu, girişi boşaltman için getchar kullanmanı önermiştim, (fflush input streams için güvenli değildir.) benim verdiğim kodu birebir kopyalayıp dener misin?
-
Tugberk bunu yazdı:
-----------------------------
Benim verdiğim kodu hem mingw hem visual C++ ile derledim, kayıtta herhangi bir sıkıntı yok, scanf den kaynaklanan sorunu ve çözümünü ilk mesajda göstermiştim zaten, scanf \n karakterini girişte bıraktığı için TC no isteyen fgets, \n karakterini girişten alıp direkt sonlanıyor ve sonraki fgets çağırılıyordu, girişi boşaltman için getchar kullanmanı önermiştim, (fflush input streams için güvenli değildir.) benim verdiğim kodu birebir kopyalayıp dener misin?
-----------------------------string.h kütüphanesini eklemeden derlenmiyo,onuda ekleyerek derledim sonuç bu. visual studio 2010 ultimate kullanıyorum. devc++ ta da denedim ama strcmp fonksiyonu yüzünden o da hata veriyo.
-
Sen tc kimlik nosunu alırken 11 karakter girmişsin, sorun şu, fgets fonksiyonu, ikinci parametresindeki değer yeterli ise, \n dahil girişteki tüm veriyi okuyup stringe aktarır. Ancak sen girişi 11 karakter ile sınırlamışsın fgets de, bende kaynak koda ekleme yaptım, bu fgets sorununu yukarıdaki önerilerde belirttim ve kendi eklediğim bölümde fgets i doğru kullandım, ancak senin yazdığın bölümü editlemeyi unutmuşum.
Özetle yapman gereken, fgets in ikinci parametresini sizeof(string) olarak değiştirmek . Aksi halde fgets girişten 11 karakter okuyor(aslında 12 var \n ile beraber) ve dönüyor. Bir sonraki fgets yine o karakteri yani \n i okuyarak dönüyor. Ne yazıkki C de string fonksiyonları ya çok güvensizdir, yani string boyutunu aştığınızda güvensiz bellek alanına veri yazar, ya da fgets de olduğu gibi 2. parametrede verilen üst limitten sonrasını okumaz girişte bırakır. İkisi de çok kötü bir yöntem. C de girilen veriye göre genişleyen bir string fonksiyonu henüz yok .
-
Çok sağol,dediğin gibi sizeof(değişkenadı) yapınca tüm sorunlar halloldu :) anlattığın şeyler için çok sağol,derslerde yada her forumda görebileceğimiz türden şeyler değiller.Ayrıca soket programlama dökümanın da çok iyi,ordada yazdığın gibi soket programlamayla ilgili fazla bi bilgi yok olanlarda da pek bişey yok.
-
wasd bunu yazdı:
-----------------------------
Çok sağol :) yani buradan anlayacağımız şey "Yaşasın c#" :D anlattığın şeyler için çok sağol,derslerde yada her forumda görebileceğimiz türden şeyler değiller.Ayrıca soket programlama dökümanın da çok iyi,ordada yazdığın gibi soket programlamayla ilgili fazla bi bilgi yok olanlarda da pek bişey yok.
-----------------------------O döküman yüzünden çok kişi ekliyor ama üzerindeki tarihten daha eski bir döküman ve içinde ufak defek hatalar var. Ayrıca artık blocking socket fonksiyonları profesyonel yazılımlarda kullanılmıyor, tabi başlangıç için ideal. bende I/O completion port gibi yöntemler üzerinde çalışıyorum şu sıralar :)
-
Araştırılması gereken şeyler,ama 3 ayda bir dil değiştirilince dili tamamıyla öğrenmek imkansız oluyo :/ zamanla olucak benden de bişeyler inşallah...şimdi anlattıklarını iyice bi anlayıp sindireyim :)