[Çözüldü]Telefon defteri yapmak istiyorum, veritabanını nasıl oluşturabilirim ?

Başlatan noktakom, 08 Ocak 2011 - 16:30:44

« önceki - sonraki »

0 Üyeler ve 3 Ziyaretçi konuyu incelemekte.

noktakom

Haklısın canım :) hocam, zaten adı üzerinde index operatörü diye...

sem

Sıfat olarak "arkadaşım" diyelim orta olsun =)=) ya da Sem de diyebilirsin, Semetey de diyebilirsin, sem0900 de diyebilirsin... Hocam deyince biraz garip hissediyorum kendimi... =)
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

sem

DÜZELTME

İlk akla gelen doğrudur =)

@hkndvc; fscanf fonksiyonunun davranışı da tırnak içerisindeki parametresine göre değişiklik gösteriyor.

Eğer %c ise boşluk okuyabiliyor.
%d gibi sayı alınıyorsa boşluk ve satır sonları atlanıyor...
%s de ise ilk boşluk ya da satır sonu karakterine kadar okuyor.

fgets ise boşlukları okuyor, satır sonu karakterini de okuyor. Ama satır sonu karakterinden sonra okumayı bitiriyor...
fgetc de fscanf ile %c okur gibi okuma yapıyor...

Yine denemek de fayda var, hepsinden emin olamadım... Ben daha çok fgets ve fscanf %s olarak okuma yapıyorum...

Hangisi kolayınıza giderse onu kullanabilirsiniz... Tek yapmanız gereken hangisi sizin işinize daha çok yarayacak onu belirlemek... Hepsini programınıza uyarlayabilirsiniz tabii, hagisi rahatınıza gelirse diyelim...
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

noktakom

Programın son halini kopyalıyorum. Şu an, 1,4 ve 5 seçenekleri çalışıyor yalnız küçük düzeltmeler gerekiyor. Mümkünse programı derlemenizi, birkaç kayıt ekleyip çalışmasını test etmenizi ve önerilerinizi belirtmenizi bekliyorum.

ayrıntı vermiyorum zaten çalıştırınca eksikleri fark edeceksiniz.

Özellikle sormak istediğim iki şey var scanf'i gets komutu ile değiştirdiğimde nedense çalışmıyor ?bu yüzden boşluk yerine "_" karakterini kullanın.

Diğeri de kayıt silme ve düzeltme bölümlerini arama kısmını kullanarak yapmayı düşünüyorum yalnız bellekte bir bölgeyi silmek, tam olarak ne demek? onu öğrenmem gerekiyor...


KODLARI YENİLEDİM. GÜNCEL KODLAR SONRAKİ İLETİMDE..

sem

Önümüzdeki bir kaç gün programı denemem zor...  İlk fırsatta deneyip geri dönüş yaparım...

gets ile program çalışmıyor ile kastınız? Aranılan kelimeler mi bulunmuyor ? Olası hata nedenini söyleyeyim aklımdaki;

Önceki iletimlerde dediğim gets ve fgets fonksiyonları boşluk okur... Satır sonu karakterini görünce son olarak onu da okur, en son satır sonu karakteri yerleştirilir ve fgets sonlanır. Yani bir dosya da şöyle bir şey olsun;

Alıntı YapSemetey Coşkun
09004444444

Dosyada adım soyadım ve telefon numaram yazıyor. Şimdi fgets ile dosyayı aşağıdaki gibi okuyorum;

char isim[50];
fgets(isim, 50, dosya);


Yukarıda dediğime göre okuma şu şekilde olacak; isim değişkenine satır sonu dahil okuma yapılacak... Yani isim dizisi şu halini alacak;

isim[0] = 'S';
isim[1] = 'e';
isim[2] = 'm';
isim[3] = 'e';
isim[4] = 't';
isim[5] = 'e';
isim[6] = "y';
isim[7] = ' ';  /*Boşluk da okundu*/
isim[8] = 'C';
isim[9] = 'o';
isim[10] = 'ş';
isim[11] = 'k';
isim[12] ='"u';
isim[13] = 'n';
isim[14] = '\n'; /*Satır sonu karakteri de okundu*/
isim[15] = '\0';

gets fonksiyonu da aynı şekilde... Yani klavyeden gets fonksiyonuna giriş olarak "Semetey Coşkun" yazsaydık okuma bu şekilde olacaktı... Dolayısı ile sizin isediğin dizi aslında ufak bir farkla değiştiği için bulunamayacak...

Bu gibi bir hata olacğanı tahmin ediyorum... Çözüm olarak yazdığım fonksiyon;

void remove_lastchar(char *adress)
{
int k = strlen(adress);
adress[k - 1] = '\0';
}


Parametre olarak fgets, gets ile okuduğunuz diziyi işleme sokmadan önce diziye gönderin... Tabii sorun bu mu değil mi emin de değilim =) Bu ise diye yazdım...

İkinciyi soruyu anlamadım =) Biraz daha açarsanız daha iyi kavrarım sanırım...

NOT: Fonksiyon adı remove_lastchar =) silinen son karakter değil, daha iyi bir siim bulmak lazım =) edit_lastchar olabilir =)
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

noktakom

Keşke programa gözattıktan sonra yazsaydınız, boşuna yorulmuş oldunuz.

gets çalışmıyor derken ,

printf("İsim_Soyisim_Numara:");
scanf("%s",ad);
// gets(ad);


bölümünde "/" leri kaldırıp gets i aktif edip çalıştırdığımda gets komutu sanki yokmuş gibi es geçiliyor.... halbuki gets'i kitaptaki örnekleri yaparken aynı şekilde birsürü programda kullandım ve hiçbirinde böyle bir sorun yaşamadım. Çok ilginç yani, aklım almıyor ....=)

ikinci soruya gelince şu yüzden  soruyorum. Bildiğiniz gibi diskten birşey silmek istediğimizde aslında o tamamen ortadan kalkmıyor sadece üzerine başka şeyler yazılıyor. Bu bağlamda düşündüğümüzde, def.txt dosyasından bir kayıt silebilmem için; o kaydın bulunduğu bellek bölgesine, başka birşey yazdıracak şekilde bir yöntem mi izlemem gerekiyor? diye kafama takıldı...

sem

Yok boşa gitmez... Mutlaka birisinin işine yarar =)

Bahsettiğin durumdan şurada bahsetmiştik;

http://forum.ubuntu-tr.net/index.php/topic,17803.msg215132.html#msg215132


İlk 4 - 5 ileti senin ilk sorunun cevabı... Aslında o da yine yukarıda bahsettiğimiz durumlar ile alakalı...


scanf ve fscanf satır sonunu okumaz demiştik... O zaman;

int sayi;
fscanf(stdin, "%d", &sayi);


Bu şekilde bir sayı girdik diyelim klavyeden...

10

Dedik ve entera bastık... Yani hangi tuşları stdin içerisine girmiş olduk; 1, 0 ve \n ... Satır sonu karakterini basmak zorundayız ki okuma başlasın... Ama fscanf ve scanf '\n' bu karakteri okumuyordu!

Yani klavyeden girdiklerimiz arasından; 10 sayısı;  *sayi olarak atandı (scanf, fscanf adres ile çalışıyor, & operatörüne dikkat.)... O zaman girmiş olduğumuz '\n' karakteri hala stdin içerisinde duruyor demek oluyor...

stdin'i bir tampon olarak düşününün... Programda klavyeden girdiğimiz * her şey bu tamponda tutuluyor... Yani "10\n" olarak girdik, 10 okudundu (scanf tarafından) ama '\n' stdin tamponunda kaldı!

gets fonskiyonu da '\n' gördüğü zaman okuyup sonlanır demiştik... =)

Hali ile bu şekilde gets ya da fgets fonksiyonu çağırdınız zaman stdin içerisine bakacak; okunacak bir karakter var mı? Bakacak, dişine göre '\n' karakterini görecek ve okuma sonlanacak... O nedenle okumayı yapıp geçecek...

Yani siz oradan // bu işaretleri kaldırdığınızda "ad" değişkeni şu halini alacak;

ad[0] = '\n';
ad[1] = '\0'; //NULL karakterini de koyuldu...

Bu nedenle program istemediğiniz şekilde çalışacak. Önlem olarak ne yapmak lazım?

Verdiğim bağlantıdaki fflush() fonksiyonunu inceleyebilirsiniz...  C99 standartlarına göre stdin'e  fflush() çekilemiyor... Daha sonra bir değişiklik oldu ise bilemiyorum. Çekilemiyordan kastım böyle bir standart yok... Biz o başlıkta gördüğünüz gibi denedik işe yarıyor... Ama daha taşınabilir kod yazmak için;

while (getchar() != '\n');//stdin tamponu bosaltiliyor...

Bu kod verdiğim bağlantıdaki örnek içerisinde mevcut.

BAşka bir alternatif ise scanf, fscanf gibi fonksiyonların hepsinden sonra temizlik yapmak.... Yukarıda verdiğim örnek için;

int sayi;
fscanf(stdin, "%d", &sayi);
getchar();



Aynı şekilde sayi = 10 oldu... '\n' stdin içerisinde bırakıldı (fscanf tarafından)... getchar()'da stdin tamponundan yani klavyeden okuma yapan bir fonksiyon... Bir karakter okuyor... getchar() bakacak; eğer stdin içerisinde okunacak bir karakter varsa, okumasını yapacak (bir karakter) eğer yoksa kullanıcının bir karakter girmesini bekleyecek... fscanf '\n' bırakmıştı, bu durumda getchar bunu görecek ve okuyacak... Hali ile akış gets fonksiyonuna geldiğinde stdin tamponumuz boş olacak...


Dediğim gibi stdin'i klavyeden aldıklarımızı saklayan bir tampon olarak düşünün... stdout ise aynı şekilde ekrana yazdıklarımızı saklayan bir tampondur.. Fonksiyonlar bu tamponlar üzerinde çalışır... O nedenle dosya işlemlerinde ben stdin ve stdout kullanıyorum, size verdiğim kodlarda örneklerini görebilirsiniz...

fprintf(stdout, "...");  // stdout -> ekrana yaz
fscanf(stdin, "...");   // stdin,   -> klavyeden oku

Aslında bunlar da standart değildir... Yani stdin dosyası/tamponu standart olarak klavyeye yönlendirilmek zorunda değildir... Ama eminim ki bütün heryerde bu böyle =)=) Şakası tabii...

Umarım anlatabilmişimdir demek istediğimi...

Bellekten bir şey silme konusunda ise; tekrar üzerine yazmanız yeterli... Dizi için konuşuyorum... Bir diziniz var ve tuttuğu sayılar/karakterler belli diyelim... Tekrar üzerine yazmanız yeterli (bir değişkenin üzerine yazabilmeniz için tek dikkat etmeniz gereken const olarak tanımlamamanız gerektiği... Aksi halde günlük terim ile "Read Only" bir değişkeniniz olur)...

Yani bellekteki bir değişkeninin değeri ile istediğini gibi oynayabilirsiniz... AMA;

Bu belekteki değişikliklerin hiç birisi dosyanıza yansımaz... Siz bir değişken tanımayıp, dosyadan veri okuyorsunuz... Sadece dosyadaki veri ile bellekteki birbirine eşit oluyor... Fakat bu ikisi birbirinden bağımsız. Yani değişlikleri kaydetmek için dosyaya yeniden yazmanız gerekiyor...

sem
cem
kem
ben
sen
o
SUDO
C
C++


Bir dosyamız yukarıdaki gibi.. Bu dosyayı okuduk bir değişken içerisine... Daha sonra SUDO'yu "Uygulama Geliştirme Ekibi" olarak değiştireceğiz diyelim... Bellekte tekrardan üzerine yazdık değiştirdik...

Belleğimizde şu şekilde karakterleri tutan bir değişkenimiz oldu;
sem
cem
kem
ben
sen
o
Uygulama Geliştirme Ekibi
C
C++



Şimdi dosya içerisindeki SUDO'yu nasıl sileceğiz? Önemli olan bu =) Dosya içerisindeki SUDO'yu silmek için çok şey denedim hiç birisi sonuç vermedi... O nedenle kullandığım yöntemi söyleyeyim;

Dosyayı w+ ile açarak yani dosyayı sıfırlayarak tekrardan yazdırmak... Aksi şekilde sadece SUDO'yu silmek için ne yapılır bilmiyorum... Hatta böyle bir şey yok diyeceğim ama diyemiyorum, emin değilim çünkü, fakat çok çok aradık bulamadık biz... O nedenle dediğim gbi değişiklikleri kaydetmek için yeni bir dosya işinizi görecektir...

Ya dosyayı +w ile sırıflayıp tekrar açabilirsiniz. Ya da bütün her şeyi bir kerede halletmeyeceksiniz geçiçi bir dosya oluşturursunuz (def.txt.tmp gibi)  daha sonra def.txt'i silip, rename(def.txt, def.txt.tmp) şeklinde işinizii halledebilirsiniz...

Benim bu konuda önerilerim bunlar... Eğer metin dosyası içerisinden SUDO yazısını silmeyi bulursanız ve paylaşırsanız ya da bilen bir arkadaş varsa ve açıklarsa ben de çok sevinirim... Kolay gelsin...

NOT: Zaman kıtlığı nedeni ile yazımı tekrar okuma fırsatım yok, o nedenle gönderiyorum şimdi, imla hataları ya da düşük cümleler var ise kusura bakmayın... İyi çalışmalar...


EK: Yine kodları deneme şansım olmadı =) Fakat %99 sorun budur sanıyorum...
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

noktakom

Dediğiniz gibi %99 teşhis doğru fakat ben %1 lik kısımda olduğumu düşünüyorum :) Çünkü, benim durumumda ardışık string alma diye birşey, şu an için söz konusu değil. gets'i aktif ettiğimde scanf'i zaten pasifize ediyorum...! Özetle, scanf'i gets ile değiştirmek istememin sebebi; sizin bana öğrettiğiniz üzere, gets'in boşluk okuyabiliyor olması... Ayrıca ben fgets kullanmadım, bahsettiğiniz stdin tamponu gets için de geçerli mi ?

Diğer silme konusu vs. araştırıyorum. Birşey bulursam, paylaşırım.

Bu yoğunlukta ilgilendiğiniz için tekrar teşekkürler. Siz olmasanız kimsenin iki kelime karalayacağı yok...

net-stat

Linux'te alternatifi varsa Office Access'in en kolay bir şekilde yapabilirsin.

noktakom

@net-stat, sqlite var demişlerdi ama; şu an dosya üzerine yoğunlaştık, öyle yapmaya çalışıyoruz.

sem

Alıntı yapılan: hkndvc - 21 Ocak 2011 - 13:20:34
Ayrıca ben fgets kullanmadım, bahsettiğiniz stdin tamponu gets için de geçerli mi ?

Evet, klavyeden giriş alan bütün fonksiyonlar için stdin, ekrana yazan bütün fonksiyonlar için stdout geçerlidir...

Bir de ardışık string almanıza gerek yok... stdin'de kalan herhangi bir karakter gets ya da fgets fonksiyonunun istenmeyen şekilde çalışmasına neden olacaktır. Örneğin program açılışındaki scanf'den kalan satır sonunu karakterini de hesaba katmalısınız...
Alıntı Yap
printf("1-Kayıt Ekle\n2-Kayıt Düzelt\n3-Kayıt Sil\n4-Kayıt Ara\n5-Tüm Kayıtları Göster\n");
scanf("%d",&secim);

İkinci seçeneği alalım;

secim = 2; olarak kabul edildi...
stdin içerisinde iki sayısını kabul ettirmek için bastığımız enter duruyor =) Çünkü scanf bu karakteri okumadı... Basit bir önlem;

printf("1-Kayıt Ekle\n2-Kayıt Düzelt\n3-Kayıt Sil\n4-Kayıt Ara\n5-Tüm Kayıtları Göster\n");
scanf("%d",&secim);
getchar();


Alıntı yapılan: hkndvc - 21 Ocak 2011 - 13:20:34
Bu yoğunlukta ilgilendiğiniz için tekrar teşekkürler. Siz olmasanız kimsenin iki kelime karalayacağı yok...

Rica ederim... Bilgisi olan arkadaşlar da zaman buldukça ellerinden gelen yardımı yapıp fikirlerini paylaşacaklardır... Linux kullanıcıları olarak ortak paydamız sabır, merak ve araştırma olsun =)


Veri tabanı olarak da dosyalamaya devam etmenizi tavsiye ederim... Çünkü dosya fonksiyonlarını ve okuma/yazma fonksiyonlarını en iyi bu şekilde; pratiklerle öğrenirsiniz... (bence)

İyi çalışmalar...
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

noktakom

"Bir de ardışık string almanıza gerek yok... stdin'de kalan herhangi bir karakter gets ya da fgets fonksiyonunun istenmeyen şekilde çalışmasına neden olacaktır"

Verdiğiniz linkte bir stringten sonra tamsayı alınıyorsa bu tarz bir problemin olmayacağını yazmışsınız ama... oradaki yazınıza göre seçim bölümünde de 1,2 gibi bir sayı alındığı için problem olmaması lazım...

Neyse verğiniz kodu programın başka bir yerine iliştirdim, çalışmasını test ettim.. Bundan sonra dediğiniz gibi yaparım..

sem

Dediğim doğrudur =)

Bir karakter dizisinden sonra tam sayı alırsanız sorun olmaz...  Yani önce stringi aldınız... Sonra tam sayıyı okursanız; stringi scanf ile de alsanız gets ile de alsanız tamsayınızı da scanf ile okuyacağınız için sorun olmaz...

gets ile aldınız diyelim; zaten stdin içerisindeki '\n' karakteri de okunacak... Sorun yok... scanf ile stringi aldınız diyelim; en sondaki '\n' karakterini bırakacak... Tam sayı okurken yine scanf aldınız; scanf '\n' okumadığı için doğrudan girdiğiniz tam sayıyı okuyacak...

EK: teyit:
#include <stdio.h>

int main()
{
   char s[10];
   int a;

   gets(s);
   puts(s);
   scanf("%d", &a);
   printf("%d\n", a);

}


   
#include <stdio.h>

int main()
{
   char s[10];
   int a;
    scanf("%d", &a);
   printf("%d\n", a);

  gets(s);
   puts(s);
}



Farka bakın demek istediğimi anlacayacaksınız...


EK2: Sizde durum tam tersi.. Önce tam sayı sonra karakter dizisi alıyorsunuz...
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

noktakom


sem

Olsun olsun... Olacak o kadar... Zaten bu detay kısımları canı sıkan... Bunları atlattıktan sonra daha zevkli oluyor =) Kolay gelsin tekrardan...
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

noktakom

Hataları düzelttim, kodları yeniliyorum... ( 2 ve 3 seçenekleri daha eklenmedi... )
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *find(char *x,char *y)   {
static char *g;
static char z[]="Kayıt Bulunamadı";
int i=1;

while (x!= NULL || y!= NULL)
{
y0:g=strchr(x,y[0]);
if(g==0) return z;
for(i=1;y[i]!='\0';i++)
if(g[i]==y[i])
{
if(i!=strlen(y)) return g;
else {
x=g; goto y0;
}
}

}return z;
}


int main()
{
FILE *tel;
char  ad[25];
int secim,j;


printf("1-Kayıt Ekle\n2-Kayıt Düzelt\n3-Kayıt Sil\n4-Kayıt Ara\n5-Tüm Kayıtları Göster\n");
scanf("%d",&secim);


switch (secim)  {

case 1 :{ if(access("def.txt", 0)) {
    fprintf(stdout,"Dosya yok\n"); tel=fopen("def.txt", "w");
      }
          else
          fprintf(stdout,"Dosya var\n"); tel=fopen("def.txt", "a");

if(tel == NULL)
{
fprintf(stdout,"Dosya açılamadı program kapatılacak\n");
        exit(EXIT_FAILURE);
}

printf("İsim Soyisim Numara(max 24 karakter giriniz):");
while (getchar() != '\n');//stdin tamponu bosaltiliyor...
gets(ad);

fprintf(tel,"%s\n",ad);
fclose(tel);
puts("Kaydedildi.\a");break;
}
/*case 2 :
case 3 :  */

case 4 : {
if(access("def.txt", 0)) fprintf(stdout,"Dosya yok\n");
else tel=fopen("def.txt", "r");

int oku,i=0;
char *tmp,*kontrol;
tmp=malloc(1024*100);

oku=fgetc(tel);
while (oku!=EOF)  {
tmp[i]=oku;
oku=fgetc(tel);
i++;
}

y:printf("İsim:");
scanf("%s",ad);
if(strlen(ad)==1) {
printf("Lütfen en az iki karakter girin!\n");
goto y;
}
kontrol=find(tmp,ad);
x:j=0;
while(kontrol[j]!='\n')
{
printf("%c",kontrol[j]);
j++;
}
printf("\nAradığınız aynı isimde başka biri mi? [e/h]");
while (getchar() != '\n');//stdin tamponu bosaltiliyor...
char eh;
eh=getchar();

if(eh=='e') {
kontrol=find((kontrol+j+1),ad);
goto x;
}
fclose(tel);break;
}

case 5 : {
if(access("def.txt", 0)) fprintf(stdout,"Dosya yok veya henüz hiç kayıt girilmemiş!\n");
else tel=fopen("def.txt", "r");

int oku;
oku=fgetc(tel);
while (oku!=EOF)  {
putchar(oku);
oku=fgetc(tel);
}
fclose(tel);break;
}
}//switch

return 0;
}//main


sem

Bütün kodları inceleme imkanım olmadı...

İnceleyebildiğim kadarından önerilerimi sunayım;

* access fonksiyonunun prototipi unistd.h içerisinde. Eğer bu başlığı da dahil  ederseniz hiç uyarı almazsınız. Zaten almıyorsanız -Wall paramtresini kullanın. Bu parametre güzel bilgiler veriyor.

Örneğin kullanılmayan verilere kadar gösteriyor.

gcc porgram.c -o program -Wall

* Program her bir adımdan sonra sonlanıyor. Programı sonsuz döngü içerisine kurarsanız daha hoş durur.

while(1){
    fprintf(....) //Menü...
    ///işlemler
}


Menü seçimlerine bir de "6 -Çıkış" eklerseniz, programdan çıkış da kullancı kontrolüne bırakılmış olur.

* case 4: etiketine bakarsanız

case 4 : {
if(access("def.txt", 0)) fprintf(stdout,"Dosya yok\n");
else tel=fopen("def.txt", "r");


gibi bir ifade var... Burada dosya bulunamazsa kişiye "Dosya yok" bilgisi veriliyor. Ama dosya açılmaya çalışılmıyor. Tabii dosya açılmaya çalışılsa da açılmayacak fakat bu uyarıdan sonra program dosya açılmış gibi devam ediyor. Hali ile hataya sebep oluyor. Burada  da "Dosya yok. Kayıt Bulunamadı" şeklinde bir uyarı ile akışın yönü değiştirilse sorun kalmayacaktır...

Bakabildiğim kısım bu kadar... Kolay gelsin...
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

sem

Bu proje bitti mi acaba.. Akibetini merak ettim de =) Bitti ise son halini görmek isterdim...
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

noktakom

Yok malesef kaç haftadır elimi bile süremedim. Bu akşam bitireyim dedim de uygulama sırasında silme fonkyonunun düzgün çalışmasını sağlayamadım. Bi bakarsanız sevinirim.

Kısaca şöyle düşündüm.

xx yy 0535(\n)
cc vv 0536(\n)
bb öö 0537(\n)

şeklinde kayıtlar olsun ve "cc" adlı kişiyi silmek isteyeyim..

del fonksyonuna tüm kayıtların bulunduğu göstericinin adresini ve silmek istediğim kaydın adresini yolluyorum.

silmek istediğim kaydın adresi ile tüm kayıtların bulunduğu göstericinin adresi eşit oluncaya kadar karakterleri tek tek dosyaya yazdırıyorum. bu iki adres eşitlenince de silinecek kayıt kaç karakterse  tüm kayıtların bulunduğu göstericinin adresini o kadar arttırıp dosyaya yazırma işlemine o kaydı atlayarak devam ediyorum.

bu mantıkla kodladım fakat dosyaya farklı karakterler yazılıyor.

Neyse işte kodlar, umarım vaktiniz vardır :)

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

char *find(char *x,char *y)   {
   static char *g;
   static char z[]="Kayıt Bulunamadı";
   int i=1;

   while (x!= NULL || y!= NULL)
   {
   y0:g=strchr(x,y[0]);
   if(g==0) return z;
   for(i=1;y[i]!='\0';i++)
      if(g[i]==y[i])
      {
      if(i!=strlen(y)) return g;
         else {
            x=g; goto y0;
         }
      }

   }return z;
}

void del(char *x,char *y)   {
FILE *tel2;
int j;
for(j=0;y[j]!='\n';j++);
tel2=fopen("def.txt", "w");
for(;*x!=EOF;) {
if(x==y) { x+=j; continue; }
for(;fputc(x,tel2),*x!='\n';x++);
x++;
}
fclose(tel2);
puts("Kayıt Silindi");
}

int main()
{
while(1){
FILE *tel;
char  ad[25];
int secim,j;


printf("1-Kayıt Ekle\n2-Kayıt Düzelt\n3-Kayıt Sil\n4-Kayıt Ara\n5-Tüm Kayıtları Göster\n");
scanf("%d",&secim);


switch (secim)  {

case 1 :{ if(access("def.txt", 0)) {
             fprintf(stdout,"Dosya yok\n"); tel=fopen("def.txt", "w");
         }
          else
               fprintf(stdout,"Dosya var\n"); tel=fopen("def.txt", "a");

   if(tel == NULL)
   {
      fprintf(stdout,"Dosya açılamadı program kapatılacak\n");
        exit(EXIT_FAILURE);
   }

   printf("İsim Soyisim Numara(max 24 karakter giriniz):");
   while (getchar() != '\n');//stdin tamponu bosaltiliyor...
   gets(ad);

   fprintf(tel,"%s\n",ad);
   fclose(tel);
   puts("Kaydedildi.\a");break;
}
/*case 2 : */

case 3 :{
   if(access("def.txt", 0)) {fprintf(stdout,"Dosya yok\n");break;}
   else tel=fopen("def.txt", "r");

   int oku,i=0;
   char *tmp,*kontrol,*tmp2;
   tmp=malloc(1024*100);
   tmp2=malloc(1024*100);
   if(tmp==NULL || tmp2==NULL) exit(1);

   oku=fgetc(tel);
   while (oku!=EOF)  {
      tmp[i]=oku;
      oku=fgetc(tel);
      i++;
   }

   strcpy(tmp2,tmp);

   y:printf("İsim:");
   scanf("%s",ad);
   if(strlen(ad)==1) {
      printf("Lütfen en az iki karakter girin!\n");
      goto y;
   }
   kontrol=find(tmp,ad);
   x:j=0;
   while(kontrol[j]!='\n')
   {
      printf("%c",kontrol[j]);
      j++;
   }
   printf("\nSilmek istediğiniz kişi aynı isimde başka biri mi? [e/h]");
   while (getchar() != '\n');//stdin tamponu bosaltiliyor...
   char eh;
   eh=getchar();

   if(eh=='e') {
      kontrol=find((kontrol+j+1),ad);
      goto x;
   }
   else {
   fclose(tel);
   del(tmp2,kontrol);
   }
fclose(tel);break;
}


case 4 : {
   if(access("def.txt", 0)) { fprintf(stdout,"Dosya yok\n");break;}
   else tel=fopen("def.txt", "r");

   int oku,i=0;
   char *tmp,*kontrol;
   tmp=malloc(1024*100);

   oku=fgetc(tel);
   while (oku!=EOF)  {
      tmp[i]=oku;
      oku=fgetc(tel);
      i++;
   }

   y1:printf("İsim:");
   scanf("%s",ad);
   if(strlen(ad)==1) {
      printf("Lütfen en az iki karakter girin!\n");
      goto y1;
   }
   kontrol=find(tmp,ad);
   x1:j=0;
   while(kontrol[j]!='\n')
   {
      printf("%c",kontrol[j]);
      j++;
   }
   printf("\nAradığınız aynı isimde başka biri mi? [e/h]");
   while (getchar() != '\n');//stdin tamponu bosaltiliyor...
   char eh;
   eh=getchar();

   if(eh=='e') {
      kontrol=find((kontrol+j+1),ad);
      goto x1;
   }
fclose(tel);break;
}

case 5 : {
   if(access("def.txt", 0)) {fprintf(stdout,"Dosya yok veya henüz hiç kayıt girilmemiş!\n");break;}
   else tel=fopen("def.txt", "r");

   int oku;
   oku=fgetc(tel);
   while (oku!=EOF)  {
      putchar(oku);
      oku=fgetc(tel);
   }
   fclose(tel);break;
}
}//switch
}
return 0;
}//main


sem

@hkndvc, biraz inceleme fırsatım oldu fakat kodlar bayağı karışık geldi aslında bana =) Size öneri olarak bir del fonksiyonu algoritması verebilirim... Ve okunabilirlik açısından da size kazanç sağlayacaktır... Ve iki tane 1024 byte lık tampon ile çalışmanıza gerek kalmayacak sanıyorum... Ayrıca veri tabanı bir satırdan oluştuğu için sıkıntı da yaratmayacaktır... Burada program için bir satır belirlediğimizi düşünüyorum... Önreğin bir satır en fazla 100 satır olabilir demiş olalım



...
#define MAX_LINE 100
..
..
case 3:
   char *remove_line;
   remove_line = (char*)calloc(MAX_LINE, sizeof(char));
   fprintf(stdoıt, "Silenecek satır için bir arama anahtarı girin:");
   fgets(remove_line, 100, stdin);
   edit_last_char(remove_line); //bu fonskiyon satır sonunu karakterini silmek için, önceden vermiş olduğum remove_last_char fonksiyonu
   del(remove_line);
    free(remove_line);
   break;


Yani kişiden sadece silmek istediği satıra ilişkin bir anahtar almış oldum... 100 harf ile bir harf arasında değişebilir bu anahtar.. Sizin 2 harflik sınırlamanız kullanılabilirlik açısından daha iyi olmuş tabii...

Silme fonksiyonu için; tek ihtiyacımız olan silinecek anahtları bilmek... Şu algoritma ile giderseniz sadece bu bilgi ile işlem yapabilirsiniz;

* kaynak dosya (def.txt) ve geçici bir dosya oluştur (örneğin temp_def.txt)
* kaynak dosyadan oku (fgets ile komple satırı al)
   - Dosyadan okunan satır ile del fonksiyonun parametresi olan remove_line parametrelerini karşılaştır (strstr fonksiyınu ile)
      - Eğer okunan satır, aranılan karakterleri barındırıyorsa kişiye silmek isteyip istemediğini sor
          - Kişi silmek isterse okunan satırı atla
          - Kişi silmek istemezse okunan satırı atlamadan, olduğu gibi geçici dosyaya yaz.


* Bütün yazdırma işlemleri bitmiş oldu... Aldığımız satırı kişinin isteğine göre temp_def.txt içerisine yazdırdık... Yani bu dosya kişinin istedği bilgileri barındırıyor oldu.
* def.text dosyasını sil(remove, fonksiyonu)
* temp_def.txt dosyasının adını def.txt olarak değiştir... (rename fonksiyonu)


Bu şekilde yaparsanız karışıklığı en aza indirmiş olursunuz... goto ibaresi çok kullanşlı olabiliyor gerçekten fakat bir başkası için ya da kendiniz için de 2 hafta sonra kodları incelediğinizde, kodu takip etmeyi zorlaştırıyor...

Kolay gelsin...
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

noktakom

goto deyiminden şikayet ettiğinize göre sanırım hatanın case 3 bloğu içerisinde olduğu düşünüyorsunuz. Çünkü tavsiyeleriniz hep o yönde ve del fonkyonunu da aynen kullanmışsınız. Yalnız ben  burada hata olduğunu pek zannetmiyorum çünkü o blok arama bölümü yani case 4 ile %90 aynı, sadece 1-2 küçük ekleme yapıldı... özetle del fonksyonuna bakma imkanınız varsa o konuda da yorumunuzu almak isterim...

sem

Deneme mi aktarıp üzerinden hata bildirimi yapayım;

Alıntı Yapsem0900@debian:~/Desktop/hakan$ ./deneme
1-Kayıt Ekle
2-Kayıt Düzelt
3-Kayıt Sil
4-Kayıt Ara
5-Tüm Kayıtları Göster
3
İsim:sago
sagopa kajmer 0358
Silmek istediğiniz kişi aynı isimde başka biri mi? [e/h]e
^C
sem0900@debian:~/Desktop/hakan$ ./deneme
1-Kayıt Ekle
2-Kayıt Düzelt
3-Kayıt Sil
4-Kayıt Ara
5-Tüm Kayıtları Göster
3
İsim:sago
sagopa kajmer 0358
Silmek istediğiniz kişi aynı isimde başka biri mi? [e/h]h
.
.
.
.
Segmentation fault
sem0900@debian:~/Desktop/hakan$ ./deneme

İlk ednememde sago'yu arıyorum.. Doğru kaydı buluyor, fakat sonsuz döngü içerisine giriyor... Kendim ctrl +c ile sonlandırmak zorunda kalıyorum...  İkinci denememde ise doğru kişiyi bulmasına rağmen hayır diyorum... Fakat hayır dememe rağmen del fonksiyonu çağrılıyor...

İlk fonksiyonda evet desem de del fonksiyonu çağırılmıyor fakat hayır dediğim zaman fonksiyon çağırılıyor... Programın yapısı ters işliyor sanırım, ya da fonksiyonlar bu duruma göre çalışıyor...

Oradaki noktalar şunu gösteriyor; del fonksiyonu içerisine puts(".") koydum ki, eğer sonsuz döngüye burada giriliyorsa haberim olsun diye... Fakat sonsuz döngüde iken gördüğünüz gibi del fonskiynu çağrılmıyor, hiç nokta yok... Sanıyorum program goto lar arasında kalıyor... Emin değilim tabii... Hayır dediğimde ise del fonksiyonunun çağrıldığını yine aynı noktalar sayesinde anlıyorum...
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

noktakom

Hayır deyince del fonksyonunu çağırması normal en azından ben öyle yazmıştım :) o önemli değil şimdilik... Bu durum gösteriyor ki silme işlemi için del fonksyonuna giriyor fakat bahsettiğim gibi fonksyon doğru çalışmıyor.. eğer bahsettiğiniz kısır döngüden sonra "cat" ile def.txt dosyasını açmayı denerseniz içerisine benim yazıdrmak isteediğim karakterler değil de farklı şeyler yazıldığını göreceksiniz.... Anlatmaya çalıştığım şey de bu aslında... case 3 bloğu içerisi bir miktar düzeltme gerektirse de ölümcül hata del fonksyonu içerisinde ve ben  del fonksyonundaki bu hatayı bulamadım...

sem

@hkndvc, biraz bakınma fırsatım oldu programa, hatayı bulamadım.. Açıkca söylemem gerekirse kodlar benim için çok karışık... Büyük ihtimalle hataları karışıklık yüzünden seçemiyoruz...

Alışkanlık meselesi tabi;

Bana göre neden karışık; parantezlerin nerede başlayıp nerede bittiğini göremesem bile bir kodu anlamamam için başlı başına bir nedendir benim için =) Size tavsiyem kendinize göre bir tarzda yazmanız... Kendinize en uygun tarzlara bakıp oradan devam edin derim. Çünkü anladığım kadarı ile parantezler sizde de sıkıntıya neden olmuş;

Örneğin;

case 1 :{ if(access("def.txt", 0)) {
             fprintf(stdout,"Dosya yok\n"); tel=fopen("def.txt", "w");
         }
          else
               fprintf(stdout,"Dosya var\n"); tel=fopen("def.txt", "a");


Burada else için parantez açmadığınız için şu durum olmuş;

* Eğer dosya varsa; "Dosya var" yaz ve dosyayı a modunda aç
* Eğer dosya yoksa: "Dosya yok" yaz ve dosyayı w modunda aç sonra dosyayı a modunda tekrar aç...

Uykusuzluktan gözerim beni yanıltmıyorsa bu şekilde olması lazım..

Ne kadar basite indirgerseniz programı hataları o kadar kolay bulursunuz... Bir de siz C'yi yeni başlarken yapmak için çok zor bir örnek uygulama seçtiniz kendiniz için.. Hatayı bulmak çok zamanımı alır ve çok zorlar beni, fakat sizin programınızın tabanına oturtulmuş ufak bir uygulama örneği paylaşabilirim isterseniz... Fikir vermesi açısından...
".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

noktakom

Semetey, hayırlı olsun diyelim mi artık ? :) Program bitti, şu an bildiğim bir problemi yok tabi biraz görünümünü güzelleştirmek gerekebilir... Neyse yorumlarınızı ve tavsiyelerinizi bekliyorum..

Not: Kodlar biraz karışıktır :) idare edin :)

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

FILE *tel;

char *find(char *x,char *y)   {
   static char *g;
   static char z[]="Kayıt Bulunamadı";
   int i=1;

   while (x!= NULL || y!= NULL)
   {
   y0:g=strchr(x,y[0]);
   if(g==0) return z;
   for(i=1;y[i]!='\0';i++)
      if(g[i]==y[i])
      {
      if(i!=strlen(y)) return g;
         else {
            x=g; goto y0;
         }
      }

   }return z;
}
void del(char *x,char *y)   {
FILE *tel2;
int j,i,k=0,oku;

if(access("def.txt", 0)) {fprintf(stdout,"Dosya yok\n");exit(1);}
else tel=fopen("def.txt", "r");

oku=fgetc(tel);
while (oku!=EOF)  {
x[k]=oku;
oku=fgetc(tel);
k++;
}
fclose(tel);

tel2=fopen("def.txt", "w");
for(i=0;y[i]!='\n';i++);
for(j=0;*y='.',i!=j;j++,y++);

do{
if(*x=='.') {x++;continue; }
fputc(*x,tel2);x++;
}while(*x!=NULL);

fclose(tel2);
puts("Kayıt Silindi.\a");
}

void edit(char *x,char *y,char *z)   {
FILE *tel2;
int j,i,k=0,oku;

if(access("def.txt", 0)) {fprintf(stdout,"Dosya yok\n");exit(1);}
else tel=fopen("def.txt", "r");

oku=fgetc(tel);
while (oku!=EOF)  {
x[k]=oku;
oku=fgetc(tel);
k++;
}
fclose(tel);

tel2=fopen("def.txt", "w");
for(i=0;y[i]!='\n';i++);
for(j=0;*y='.',i!=j;j++,y++);

y-=j;
for(i=0;z[i]!=NULL;i++) y[i]=z[i];
y[i]='\n';

do{
if(*x=='.') {x++;continue;}
fputc(*x,tel2);x++;
}while(*x!=NULL);

fclose(tel2);
puts("Kayıt düzeltildi.\a");
}

int main()
{
while(1){
char  ad[25];
int secim,j;


printf("1-Kayıt Ekle\n2-Kayıt Düzelt\n3-Kayıt Sil\n4-Kayıt Ara\n5-Tüm Kayıtları Göster\n");
scanf("%d",&secim);


switch (secim)  {

case 1 :{ if(access("def.txt", 0)) {
             fprintf(stdout,"Dosya yok\n"); tel=fopen("def.txt", "w");
          }
          else {
               fprintf(stdout,"Dosya var\n"); tel=fopen("def.txt", "a");
          }

   if(tel == NULL)
   {
      fprintf(stdout,"Dosya açılamadı program kapatılacak\n");
        exit(EXIT_FAILURE);
   }

   printf("İsim Soyisim Numara(max 24 karakter giriniz):");
   while (getchar() != '\n');//stdin tamponu bosaltiliyor...
   gets(ad);

   fprintf(tel,"%s\n",ad);
   fclose(tel);
   puts("Kaydedildi.\a");sleep(2);break;
}
case 2 :{
   if(access("def.txt", 0)) {fprintf(stdout,"Dosya yok\n");break;}
   else tel=fopen("def.txt", "r");

   int oku,i=0;
   char *tmp,*kontrol;
   tmp=malloc(1024*100);
   if(tmp==NULL) exit(1);

   oku=fgetc(tel);
   while (oku!=EOF)  {
      tmp[i]=oku;
      oku=fgetc(tel);
      i++;
   }

   y2:printf("İsim:");
   scanf("%s",ad);
   if(strlen(ad)<2) {
      printf("Lütfen en az iki karakter girin!\n");
      goto y2;
   }
   kontrol=find(tmp,ad);
   x2:j=0;
   while(kontrol[j]!='\n')
   {
      printf("%c",kontrol[j]);
      j++;
   }
   printf("\nDüzeltmek istediğiniz kişi aynı isimde başka biri mi? [e/h]");
   while (getchar() != '\n');//stdin tamponu bosaltiliyor...
   char eh;
   eh=getchar();

   if(eh=='e') {
      kontrol=find((kontrol+j+1),ad);
      goto x2;
   }

   else {
   printf("kaydı düzeltmek istediğinize emin misiniz? [e/h]");
   while (getchar() != '\n');//stdin tamponu bosaltiliyor...
   char eh;
   eh=getchar();

   if(eh=='e') {
   printf("Kaydı değiştirmek istediğiniz haliyle giriniz...\nİsim Soyisim Numara(max 24 karakter):");
   char new[25];
   while (getchar() != '\n');//stdin tamponu bosaltiliyor...
   gets(new);

   fclose(tel);
   edit(tmp,kontrol,new);
   free(tmp);
   goto z2;
   }
   }


fclose(tel);
z2:sleep(2);break;
}

case 3 :{
   if(access("def.txt", 0)) {fprintf(stdout,"Dosya yok\n");break;}
   else tel=fopen("def.txt", "r");

   int oku,i=0;
   char *tmp,*kontrol;
   tmp=malloc(1024*100);
   if(tmp==NULL) exit(1);

   oku=fgetc(tel);
   while (oku!=EOF)  {
      tmp[i]=oku;
      oku=fgetc(tel);
      i++;
   }

   y:printf("İsim:");
   scanf("%s",ad);
   if(strlen(ad)<2) {
      printf("Lütfen en az iki karakter girin!\n");
      goto y;
   }
   kontrol=find(tmp,ad);
   x:j=0;
   while(kontrol[j]!='\n')
   {
      printf("%c",kontrol[j]);
      j++;
   }
   printf("\nSilmek istediğiniz kişi aynı isimde başka biri mi? [e/h]");
   while (getchar() != '\n');//stdin tamponu bosaltiliyor...
   char eh;
   eh=getchar();

   if(eh=='e') {
      kontrol=find((kontrol+j+1),ad);
      goto x;
   }

   else {
   printf("%s kaydını silmek istediğinize emin misiniz? [e/h]",kontrol);
   while (getchar() != '\n');//stdin tamponu bosaltiliyor...
   char eh;
   eh=getchar();

   if(eh=='e') {
   fclose(tel);
   del(tmp,kontrol);
   free(tmp);
   goto z;
   }
   }


fclose(tel);
z:sleep(2);break;
}


case 4 : {
   if(access("def.txt", 0)) { fprintf(stdout,"Dosya yok\n");break;}
   else tel=fopen("def.txt", "r");

   int oku,i=0;
   char *tmp,*kontrol;

   tmp=malloc(1024*100);
   if(tmp==NULL) exit(1);

   oku=fgetc(tel);
   while (oku!=EOF)  {
      tmp[i]=oku;
      oku=fgetc(tel);
      i++;
   }

   y1:printf("İsim:");
   scanf("%s",ad);
   if(strlen(ad)==1) {
      printf("Lütfen en az iki karakter girin!\n");
      goto y1;
   }
   kontrol=find(tmp,ad);
   x1:j=0;
   while(kontrol[j]!='\n')
   {
      printf("%c",kontrol[j]);
      j++;
   }
   printf("\nAradığınız aynı isimde başka biri mi? [e/h]");
   while (getchar() != '\n');//stdin tamponu bosaltiliyor...
   char eh;
   eh=getchar();

   if(eh=='e') {
      kontrol=find((kontrol+j+1),ad);
      goto x1;
   }
   free(tmp);
   fclose(tel);
   sleep(2);break;
}

case 5 : {
   if(access("def.txt", 0)) {fprintf(stdout,"Dosya yok veya henüz hiç kayıt girilmemiş!\n");break;}
   else tel=fopen("def.txt", "r");

   int oku;
   oku=fgetc(tel);
   while (oku!=EOF)  {
      putchar(oku);
      oku=fgetc(tel);
   }
   fclose(tel);sleep(2);break;
}
}//switch
}
return 0;
}//main