[Çö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 2 Ziyaretçi konuyu incelemekte.

noktakom

C ile telefon defteri programı yapmak istiyorum, yalnız veritabanını nasıl oluşturulur hiçbir fikrim yok. Gerçi yaptığım aramalarda access filan çıktı ama o da linux için değil galiba. direk gedit filan işimizi görmez mi ? hangi kütüphaneleri ve kodları bilmem gerekiyor ? mümkünse küçük bir örnek gösterebilir misiniz ?

unutmadan program başlangıçta 5 seçenek sunacak 1- kayıt ekleme 2- düzeltme 3- silme 4- kayıtlardan arama 5- tüm kayıtları gösterme gibi... buna göre nasıl bir yol izlemeliyim.

eribol

Normalde bu gibi işleri veritabanı kullanarak yapmak yerine dosyaya yazmak daha mantıklı. Ama illa bir veritabanı olacaksa sqlite güzeldir. Her ne kadar sqlite ve access veritabanı programı olmasada bu gibi konularda sqlite çok iyi iş görür.

http://www.sqlite.org/cintro.html

noktakom

Hocam şimdi benim c bilgim giriş seviyesi ve bu programı da öğrenme amaçlı yapmak istiyorum. Verdiğiniz kaynağa baktım, araştıracam da fakat baştan sona ingilizce olması ve onca yazı arasında nereye bakacağımı bile bilemediğim için beni biraz uğraştıracak gibi görünüyor. bana biraz daha açık olarak birşeyler gösterebilirseniz sevinirim . Mesela bi isim sorup onu kaydeden program örneği gösterebilir misiniz ? vaktiniz varsa tabi. Bir de dosyaya kaydetmek derken o nasıl olacak? ben bi ara denemiştim kendimce, program çalışırken giriyordum fakat kapatınca * her şey siliniyordu doğal olarak :) o işin mantığı nasıl olacak.. Saygılar..

eribol

Dosya Yönetimi için http://www1.gantep.edu.tr/~bingul/c/index.php?ders=16 türkçe kaynağı forumdan buldum. Aynı sitede bir çok belge mevcut. Ancak işin içine sqlite girdiğinde biraz daha fazla bilgi gerekir. En azından sqlite nedir, nasıl çalışır bilmek gerekiyor. Eğer yeni iseniz biraz dosya yönetimi konusuna bakınmak daha iyi olacaktır.

Ayrıca ben örnek yapamam, sadece bilgim giriş seviyesine uygun. Örnek için belge kurcalamak zorundayım. Buna vaktim yok maalesef :)

noktakom

Tamam hocam kaynak süper biraz kurcalarsam yaparım yapamazsam da size sorucam :)ona göre iyi çalışın hazırlıklı olun :)

sem

Kolay gelsin... eribol'un dediği gibi dosya işlemlerine bakmanız gerekli diye düşünüyorum öncelikle.. Yani bu gibi bir program için öğrenmeniz gereken fonksiyonlar;

fopen();
fprinf();
fscanf();
fgets();
fclose();

gibi dosya fonksiyonları.. Dikkatli kullanım ile sadece bu fonksiyonlar bile yetebilir =)

Örnek ve basit (çok üzerinde durulmamış) bir program için;

http://forum.ubuntu-tr.net/index.php/topic,14840.msg243987.html#msg243987

Bunu inceleyebilirsiniz... Tekrar kolay gelisn...
".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 arada ek yapayım Kısayol Oluşturucu programı da (C/C++ bölümünde bulabilirsiniz) verilieri dosyalarda saklıyor... Kodlara bakmak isterseniz başlığı incelemeniz yetecektir fakat içerisinde çok fazla GTK olduğu için biraz sıkıntı yaratabilir...
".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

Arkadaşlar buraya kadar nerede hata var. Sizi yormayayım dedim baya araştırdım ama çözemedim bi türlü... Birde programın arama bölümünü nasıl yapmam gerektiği hakkında fikir verebilir misiniz? Sağolun


#include <stdio.h>
//#include <conio.h>
#include <stdlib.h>

int main()
{
FILE *tel;
char  ad[15];
int secim;
long int no[10];


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");
scanf("%d",&secim);

switch (secim)  {

case 1 : if(tel == NULL) tel=fopen("def.txt", "w") ;else tel=fopen("def.txt", "a");

printf("İsim:"); scanf("%s",ad);
printf("No:"); scanf("%d",&no);

fprintf(tel,"%s %d \n",ad,no);
fclose(tel);
puts("Kaydedildi.\a");break;

}
}


sem

Merhabalar öncelikle programın çok fazla hata vermesinin nedeni birinci satırdaki "#include" yerine include yazılmış olması... Bunu sanıyorum siteye kodları aktarırken yanlış aktardınız...


if(tel == NULL)
   tel=fopen("def.txt", "w") ;
else
   tel=fopen("def.txt", "a");


Buradaki kodda anladığım kadarı ile tel dosyasınn var olup olmadığı kontrol ediliyor... Fakat bu şekilde dosya varlığı kontrolünü yapamazsınız. Burada hata var. Bir dosyanın var olup olmadığını kontrol etmek için access() fonksiyonunu kullanmalısınız....

   if(access("deneme", 0))
      fprintf(stdout,"Dosya yok\n");
   else
     fprintf(stdout,"Dosya var\n");


Dosyalarınızın açılıp açılmadığına dair de kontrol yapmalısınız... fopen() fonksiyonu başarısızlık durumunda NULL döndürür...

tel =fopen("def.txt", "w");

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


ya da kısa yoldan

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


case'lerden sonra break kullanmayı da unutmayın.. Kolay gelsin...

EK: Yuarıda deneme  isminde dosyanın olup olmadığı kontrol edilmiştir...
".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

Teşekkürler ama iki problem daha var
1- numaraları deftere doğru geçmiyor.
2- isim soyisim arasında boşluk bırakınca da numarayı almadan dosyayı kapatıyor.

hakan -1076126516
fgy -1080844468
errfddddddd -1077111988
ppppppppppppppp -1081871572


sem

Kodların son halini paylaşabilir misiniz?

Soyadını okumama sorunu büyük ihtimalle dosyadan fscaf() fonskiyonu ile okumanızdan kaynaklanıyordur... Onu fgets() ile rahatça aşabilirsiniz...  fscanf() fonskiyonu bir boşluk karakteri (space ya da tab), satır sonu (enter yani \n) ya da dosya sonunu (EOF -> End Of File) görene kadar okuma yapabilir...

Kodlarını son halini görebilirsem daha rahat yardım edebilrim...
".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

Kodlarda daha bir değişiklik yapmadım, o çıktıyı da programdan almadım zaten masaüstünde oluşan def.txt dosyasına elle girerek aldım.

sem

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

#define YOL "def.txt"

int main()
{
   FILE *tel;
   char  ad[15];
   int secim;
   long int no;


   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();

   switch (secim)
   {
      case 1:

         if(access(YOL, 0))
         {
             if((tel = fopen(YOL, "w")) == NULL)
             {
                fprintf(stdout,"%s dosyası oluşturulamadı. Program kapatılacak\n", YOL);
                exit(EXIT_FAILURE);
             }
             else
                fprintf(stdout,"%s dosyası oluşturuldu\n", YOL);
         }
         else
         {
             if((tel = fopen(YOL, "a")) == NULL)
             {
                fprintf(stdout,"%s dosyası açılamadı. Program kapatılacak\n", YOL);
                exit(EXIT_FAILURE);
             }
             else
                fprintf(stdout,"%s dosyası açıldı\n", YOL);

         }

         printf("İsim:");
         fgets(ad, 15, stdin);

         printf("No:");
         scanf("%ld",&no);

         fprintf(tel,"%s %d \n",ad,no);
         fclose(tel);
         puts("Kaydedildi.\a");break;
         break;

   }

   return 0;
}



Şöyle bir şey olacak yaklaşık olarak... Neden hata aldığınızı söyleyeyim;

* Soy adını okumaması fscanf'den kaynaklanıyor dedim gibi... O nedenle oraya fgets() koydum...
* Numarayı kaydedeceğiniz değişkeni long int dizisi olarak tanımlaışsınız. Bu demek oluyor ki bu dizi 10 tane telefon numarasını tutabilir... Onu dizi değil long int olarak tanımladım...

NOT: fprintf(stdout)  ile printf() aynı işlemi yapar... frpintf dosyaya yazar, stdout ise ekranı temsil eder... Aynı şekilde fgets kullanımında da fgets dosyadan okur ve yukarıdaki örnekte stdin 'den okuyor.. Bu da klavyemizi temsil eden dosyadır...

#define YOL "isim"

Bu şekilde tanımlammın sebei dosya ismi ya da (adında) yolunda  değişiklik yaparsanız sadece burada yapacağnız değişiklik bütün koda yansıyacaktır... Yoksa teker teker el ile bulmak gerekebilir... Kolay gelsin...


EK: Değişik karakterler görmenizin sebebi de "no" bir adres bilgisi tutuyor ve siz de bu adresi yazdırıyorsunuz... Dizi ile işlem yapsanız bile işinize yarayacak olan (yazdırmak için) adresi değil, adresin tuttuğu bilgiler olacaktır...
".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

Evet haklısınız şimdi yaptığım yalnışları daha iyi görebiliyorum. İnsan ara verince böyle hatalar yapabiliyor.

Programı komple değiştirerek baya zaman harcamışsınız, mahçup oldum. Böyle yaparsanız birdaha soru soramam :)

sem

Rica ederim lafı mı olur... =)

Programı fikir vermesi açısından biraz değiştirdim o kadar fazla oynama yapmadım...

Sorularınızı rahatlıkla sorabilirsiniz, ben ya da başka bir arkadaş zamanı oldukça yardımcı olmaya çalışacaktır... Hem bu sorulardan kaç kişinin faydalandığnı da hesaba katın, daha rahat sorarsınız..

Kolay gelsin görüşmek üzere...
".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

Peki madem öyle diyorsunuz, siz kaşındınız :)  Bir sorum daha olacak

Siz kodları hangi programda yazıyorsunuz, ben geditte yazıyorum. Eğer kod tamamlayan veya ipucu gösteren vs. birşeyler varsa benim için ekstra kolaylık olurdu.

sem

Ben bu size gönderdiklerimi nano ile yazdım... Yani uçbirimden... Bende alışkanlık olmuştu bir ara sadece uçbirimden hallediyordum C işlerimi, yani nano ile hallediyordum...

10.04 ile sanıyorum C kodlarını tanıma yani renkler ile vurgulama da geldi nano'ya... O nedenle çoğu durumda Gedit'ten pek bir farkı olmuyordu (fare kullanılmayan duurumlarda hiç bir farkı olmuyor)

Ama son zamanlar Eclipse kullanmaya başladım... Tavsiye edebileceğim kadar hoşuma gitti... Kullanımı ile ilgili SUDO 26. Sayıda anlatım bulabilirsiniz...
".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

Hocam kitapta göstericiler bölümünü inceliyorum şu an, o yüzden bu programa biraz ara verdim. Yine de öğrendiklerimden yola çıka çıkarak kayıt arama bölümünü şu şekilde yapmaya çalıştım. Bilmiyorum ne kadar doğru yaptım ama bi kontrol edebilirseniz sevinirim...



int main()
{
FILE *tel;
char  ad[15];
int secim,i;
unsigned int no;
char *x;


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 4 : {
x=malloc(15);
if(access("tel", 0)) fprintf(stdout,"Dosya yok\n"); else tel=fopen("def.txt", "r");
printf("İsim:");scanf("%s",ad);
x=strchr(*tel,ad); if(x!=0) printf("Kayıt Bulundu\n%s",x);else printf("Kayıt Bulunamadı"); }

}
}

sem

Göstericiler C'nin en zor anlaşılan konusuymuş, öyle diyorlar... Ben de daha tam olarak hakim oldum diyemeyeceğim... Gördüğüm hataları söyleyeyim;

tel FILE türünden bir gösterici. FILE da hatta "int" türünden bir tanımlama olması gerekiyor yanlış hatırlamıyorsam ve büyük ihtimalle yanlış hatırlamıyorum...  typedef ya da define kullanılarak üretildiğini hatırlıyorum...

Yani FILE'ı bir tam sayı olarak görebilirsiniz. Çok önemli değil bahsedeceğim konu ufak bir bilgilendirme geçtim...

access -> Bu fonksiyon bir dosyanın diskte olup olmadığını kontrol ediyoruz.. Yalnız parametre olarak dosyanin yolunu gönderiyoruz.. "/home/sem0900/dosya" gibi... Yani parametre türü "char *".. Siz parametre olarak FILE * türünden bir değişken göndermişsiniz. Hatalı çalışacaktır ya da çalışmayacaktır... Aslında derleme sırasında hata almanız gerekiyor ? Almadınız mı?

strchr de aynı şekilde char * türleri üzerinde çalışıyor... Yani bir metin dosyasında bir metin arayacaksaınız önce bir char * türünden bir değişkene metin dosyasının içerisindeki bütün yazıları aktarıp daha sonra bu değişken içerisinde aramalısınız...  Ya da bir döngü ile içerisinde de yapabilirsiniz metin dosyası çok uzunsa... İlk 100 karakteri al -> içerisinde ara, ikinci 100 karakteri al, içerisinde ara.. gibi...
".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

Doğru anladıysam access fonksyonuna tel'i değil def.txt'yi adresi ile birlikte göstermem gerek. Aynı klasörde olursa da adres belirtmek gerekiyor mu ?

File *tel dosyasını bir değişkene geçirmek için ne kullanmam gerekiyor ? içerik kopyalamak için strcpy gibi bir fonksyon vardı yalnış hatırlamıyorsam.... onu mu araştırayım ?

sem

Evet dosya yolunuz "def.txt" ti.. O nedenle access fonksiyonuna bu yolu göndermeniz gerekir...

NOT: "def.txt" olarak gönderirseniz programın çalıştığı dizin içerisinde def.txt adında bir dosyanın varlığı araştırılır... Tam olarak yol da belirtebilirsiniz "/home/hkndvc/Desktop/def.txt" gibi...

FILE *tel dosyasını bir değişkene geçirmek ile kastınız; bu metin dosyasındaki bütün yazıları bir değişkene kayıt edip, daha sonra bu değişkeni strchr, strcpy gibi string fonksiyonları ile kullanabilmek ise;

char *tmp; gibi bir değişken tanımlayayın... Bu değişkene yer ayırın (malloc, calloc gibi fonksiyonlarla)

for(i = 0;!feof(tel); ++i){
fscanf(tel, "%c", &ch);
tmp[i] = ch;
}


Bu şekilde şunu söylemiş oluyoruz;

* i başnagıç değeri 0 olsun... Her bir iterasyonda i'nin değerini bir arttır...
* Döngü dosya sonuna kadar devam etsin... (bunu feof() fonksiyonu ile anlıyoruz...)
* dosyadan karakteri oku, tmp değişkenine yerleştir...


Burada dikkat etmeniz gereken char * türünden değişkenleri karakter dizisi kullanabiliyoruz...

char *tmp;

tmp[0], tmp[1].... Bu şekilde bir sonraki adreslere erişebiliyoruz...

Artık bütün metin dosyası tmp değişkeni içerisinde... Artık bu değişkeni strchr, strcpy gibi bütün işlemlerde kullanabiliriz...

NOT: Kodu denemedim... Daha çok fikir vermesi açısından yazdım...
".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

Hocam affedin :) son * bir şey daha soracam.

ch değişkeninin varlık amacını çözemedim. fscanf hakkında bilgin olmadığı içindir belki ( daha o konuya gelmedik te :) ) ...dosyadan okuduğumuz karakteri onun( &ch) yerine direk tmp [ i ]'ye atayamıyor muyuz

bir de şöyle olmayacak mı ? *tmp [ i ] = ch;  çünkü bildiğim kadarıyla tmp [ i ]  =  ( tmp+i ) yani adres.... ch ise nesne....

sem

Evet ben yanlış yazmışım zaten... =)

fscaf yerine ch'ye fgetc ile okuma yapın...

fscanf daha önce belirttiğim gibi belirli şeyleri okuyabiliyor, fgets ise satır sonuna kadar okuyor.. fgetc ise doğrudan bir karakteri okuyor... Doğrudan tmp'ye aktaracak olursak belki fread yardımcı olur... Fakat önceden dosya boyutunu hesaplamak gerekecektir büyük ihtimalle...

O nedenle dosyayı karakter karakter okuyarak(fgetc ile ch'ye alıp) daha sonra bu karakterleri tmp'ye göndermek en kolay çözüm olacaktır...

fgetc ise o andaki karakteri doğrudan okur...


EK: Neden fgetc ile bir değişkene atayıp sonra tmp'ye atıyoruz dersen;


fscanf ile tmp'ye yazacak olursak;

Semetey Coşkun
093853

fscanf boşluk karakterini okumuyor... Döngü içerisinde okusak dahi dosyanın aynısını tmp'ye yerleştiremeyiz...
fgets ile de yapabilirsiniz... Fakat o zaman da her okuduğunuz karakter dizinin boyutunu hesaplayıp tmp'nin gösterdiği adresi o kadar ileri almanız gerekir.. Ya da karakter sonuna ekleme yapan ayrıca bir fonksiyon eklemeniz gerekir...


fgetc ile oku, bir arttır yaz, oku bir arttır yaz... Dediğim gibi en kolayı olacaktır diye düşünüyorum... Alternatifleriniz var tabii gördüğünüz gibi ben kolay gördüğümü ekledim...
".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

Tamam hocam teşekkürler dediğiniz gibi yapıcam.

Dosya işlemleri bölümü en sonlarda . O yüzden hayırlısıyla şu kitabı bitirebilirsem, daha emin bir şekilde devam edebileceğim. Böyle çok fazla hata yapıyorum... sizi de boşuna yoruyorum...

sem

Alıntı yapılan: hkndvc - 17 Ocak 2011 - 22:49:12
Hocam affedin :) son * bir şey daha soracam.
....
bir de şöyle olmayacak mı ? *tmp [ i ] = ch;  çünkü bildiğim kadarıyla tmp [ i ]  =  ( tmp+i ) yani adres.... ch ise nesne....

Affetmek ne demek canım öyle laf olur mu...

Burada şunu söyleyeyim; tmp+i dediğiniz gibi bir adres gösterir o nedenle *(tmp+i) ile * operatörü ile kullanılır... Fakat tmp[.i] (arada nokta yok... Noktalı yazdım yoksa italik yazı oluyor =)) şeklinde blirttiğimizde zaten indeks operatörü ile ulaşıyoruz... Bu şekilde otomatik olarak tmp+i adresinin tuttuğu veriye ulaşmış oluyoruz... Dizilerdeki gibi düşünün...

char dizi[10];

Burada "dizi"    dizi[0] elemanın adres bilgisini tutuyor zaten.. dizi[5] ise *(dizi+5) olarak düşünülebilir...  Yani dediğiniz işlemi [] -> Bu indeks operatörleri otomatik olarak yapıyor...
".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?