sanırım bug buldum :D

Başlatan hedzuben, 02 Nisan 2010 - 21:37:16

« önceki - sonraki »

0 Üyeler ve 1 Ziyaretçi konuyu incelemekte.

hedzuben

Kullanıcıdan sırasıyla parça başlığı, sanatçı, albüm adı gibi bilgiler istiyorum. Başlık kısmına "Burak" değerini girersem sorun yok ama "Burak KUT" değerini girersem sanatçı kısmını atlayıp albüm bilgisini istiyor. Arada boşluk olunca öyle oluyor. "BurakKUT" yazınca sorun yok.

Turbo C++ 3.0 da yazılmış program aşağıdaki gibidir.


//MuzikKutusu.CPP
#include <stdio.h>
#include <iostream.h>
#include <ctype.h>
#include <conio.h>
#include <stdlib.h>

void dosac ();
void ekle ();
void listele ();

struct muzik
{
char baslik[50],sanatci[50],album[50],tarz[20];
}sarki;

FILE *fp;

void dosac ()
{
if ((fp=fopen("mk.dat","r+"))==NULL)
{
  fp=fopen("mk.dat","w");
  fclose(fp);
  fp=fopen("mk.dat","r+");
}
}

void ekle ()
{
int i;
dosac();
fseek(fp,0L,SEEK_END);
do
{
  printf("Parca Basligi :");
  scanf("%s",sarki.baslik);
  printf("Sanatci : ");
  scanf("%s",sarki.sanatci);
  printf("Album : ");
  scanf("%s",sarki.album);
  printf("Tarz : ");
  scanf(" %s",sarki.tarz);
  fwrite(&sarki,sizeof(struct muzik),1,fp);
  printf("Devam edilsin mi? [E/H]\n");
} while (toupper(getch())=='E');
fclose(fp);
}

void listele ()
{
int i;
dosac();
fseek(fp,0L,SEEK_SET);
fread(&sarki,sizeof(struct muzik),1,fp);
while (!feof(fp))
{
  printf("%s %s %s %s\n",sarki.baslik,sarki.sanatci,sarki.album,sarki.tarz);
  fread(&sarki,sizeof(struct muzik),1,fp);
}
fclose(fp);
getch();
}

void main ()
{
char c;
while(1)
{
  clrscr();
  printf("1-PARCA EKLE\n");
  printf("2-LISTELE\n");
  printf("3-CIKIS\n");
  c=getch();
  switch(c)
  {
   case '1': ekle(); break;
   case '2': listele(); break;
   case '3': { remove("mk.dat"); exit(0); }
  }
}
}

sem

Merhabalar... C++ bilmiyorum fakat stdin tamponunu boşaltarak denerseniz belki sorun çözülebilir diye düşünüyorum... C den yola çıkarak... iki tane arka arkaya string alırsanız stdin'den birincisi için basılan \n (enter ) karakteri stdin'de kalıyor ve bir sonraki dizi için \n karakteri okunuyor... O nedenle tamponu boşaltarak denemenizi öneririm...
İyi geceler...
".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?

hedzuben

#2
fflush(stdin); komutu ile boşalttım ama her scanf ten sonra yazmam gerekiyor. Ne anlamsız bir durum :s

sem

#3
Tekrar belirteyim C++ bilmiyorum fakat bu konuda bir farklılık olacağını düşünmüyorum ama gene de kesin * bir şey demeyip kod örneği göndereyim siz ordan yola çıkarak kodu C++ için uyarlarsınız... Gönderdiklerim standart C kodlarıdır....

stdin dosyasi boşaltılmadan önceki program

#include <stdio.h>

int main()
{

char *birinci,*ikinci;

fprintf(stdout,"birinci diziyi gir:");
fscanf(stdin,"%s",birinci);
fprintf(stdout,"ikinci diziyi gir:");
fscanf(stdin,"%s",ikinci);//stdin tamponu bosaltilmadigi icin, birinciyi girmek icin basilan enter'ı ikinciye atiyor

return 0;
}


buda tampon boşaltıldıktan sonraki hali

#include <stdio.h>

int main()
{

char *birinci,*ikinci;

fprintf(stdout,"birinci diziyi gir:");
fscanf(stdin,"%s",birinci);

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

fprintf(stdout,"ikinci diziyi gir:");
fscanf(stdin,"%s",ikinci);//stdin tamponu bosaltilmadigi icin, birinciyi girmek icin basilan enter'ı ikinciye atiyor

return 0;
}



Kodları çalıştırarak daha iyi görürsünüz diye iki durumu da gönderdim...



Mesaj tekrarı yüzünden mesajınız birleştirildi. Bu mesajın gönderim tarihi : 02 Nisan 2010 - 22:07:35

Evet sizin yazdığınız gibi de kabul ediliyor bazı derleyicilerde ama aslında C standartlarında geçerli bir durum değil bu stdin tamponuna fflush çekilmesi. C++ için durum nedir bilmiyorum fakat dediğiniz gibi kod sağlığı açısından her scanf'den sonra yapmanız gerekir sanırım... Bir araştırayım da sanırım güvenli okuma fonksiyonları da vardı... Böyle bir fonksiyon varsa(tampon boşaltmaya gerek duymayan)
tekrar bildiririm size...

EK: Bu arada ardışık olarak string alırsanız tamponu boşaltmanız gerekiyor,  örneğin bir karakter dizisinden sonra tam sayi okumak isterseniz tapmon boşaltma işlemine gerek kalmayacaktı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?

mce

scanf yerine getline kullanırsanız düzelir sanıyorum.

getline(sarki.baslik, 50);

hedzuben

Aşağıda sil fonksiyonunun tamamlanmamış hali var. Kod şu anda anlamlı değil. Sadece bilmeniz gereken yerleri yazdım (dosac, struct ). Dosyadan satır silmek zaten ayrı bir mesele ama ben daha başlığa göre sil, sanatçıya göre sil kısmını nasıl halledeceğim onu kuramadım kafamda.



struct muzik
{
char baslik[50],sanatci[50],album[50],tarz[20];
int no;
} sarki;

FILE *fp;

void dosac ()
{
if ((fp=fopen("mk.dat","r+"))==NULL)
{
  fp=fopen("mk.dat","w");
  fclose(fp);
  fp=fopen("mk.dat","r+");
}
}

void sil()
{
dosac();
system("cls");
cout<<"      SIL MENUSU\n";
cout<<"1- Parca Basligina Gore\n";
cout<<"2- Sanatci Ismine Gore\n";
cout<<"3- Albume Gore\n";
cout<<"4- Tarza Gore\n";
cout<<"4- Numaraya Gore\n";
system("pause");
switch (getch())
{
case '1':
case '2':
case '3':
case '4':
case '5':
}
cin>>girdi;
fseek(fp,0L,SEEK_SET);
while (!feof(fp))
{
fread(&sarki,sizeof(struct muzik),1,fp);
if ()
}
fclose(fp);
}


sem

Merhabalar. mk.dat dosyasının içeriğini nasıl düşünüyorsunuz? parça başlığı, sanatçı ismi, numara, tarz hepsi bu dosyada olacak galiba... dosya nasıl bir şekilde olacak onu tasarlayamadım ben kafamda... Bir de dosac()  diye ayrı fonksiyon yerine;
fp=fopen("mk.dat","w+");  olarak belirtince direk olarak dosyası açamıyor musunuz?
(C++ bilmediğim için merakımdan sordum)
".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?

hedzuben

Programım birçok fonksiyon içeriyor; ekle, sil, listele, ara gibi. Bunların hepsinde de dosya açmak ve dosyanın var olup olmadığını kontrol etmek gerekiyor. Var değilse oluşturmak gerekiyor. Bu yüzden ayrı bir fonksiyon içinde tanımlandı.
Ayrıca dediğiniz gibi tüm bilgiler mk adlı dosyanın içinde. Her kaydı bir txt dosyasına alt alta yazılmış satırlar gibi düşünebiliriz sanırım.

sem

Anladım. C  ile C++ arasındaki farklardan biri de bu demek. Teşekkürler. C'de açılış modu "w+" olarak bildirilince dosya da hem okuma hem yazma işlemleri yapılabilyor. Dosya yoksa da yaratılıyor. C++'ta da öyle ise size kolaylık olsun diye söylemiştim.  Demek sizde farklı oluyor.
".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?

eribol

Konu dışı: @sem0900 C ile C++ arasında öyle tahmin ettiğiniz gibi farklar yok. Zaten ilk aşamada bunları farketmekte şanstır. Yani demem o ki C'yi iyi biliyorsunuz. Vurgu yapmadan öneri sunun, o kapasiteye sahipsiniz.

sem

Alıntı yapılan: eribol - 07 Nisan 2010 - 15:12:49
Konu dışı: @sem0900 C ile C++ arasında öyle tahmin ettiğiniz gibi farklar yok. Zaten ilk aşamada bunları farketmekte şanstır. Yani demem o ki C'yi iyi biliyorsunuz. Vurgu yapmadan öneri sunun, o kapasiteye sahipsiniz.
Teşekkür ederim @eribol. Uyarınızı dikkate alacağı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?

eribol

Uyarı değildi bu. Sadece bir tavsiye idi.

sem

Çok ikili diyalog olacak diye yazayım mı yazmayayım mı diye ikilemde de kalıyorum ama cevap vermemek gibi olsun da istemiyorum... O nedenle tekrar teşekkürler... Tavsiyenizi dikkate alacağım o zaman=).
".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?

hedzuben

Alıntı yapılan: sem0900 - 07 Nisan 2010 - 15:05:08
Anladım. C  ile C++ arasındaki farklardan biri de bu demek. Teşekkürler. C'de açılış modu "w+" olarak bildirilince dosya da hem okuma hem yazma işlemleri yapılabilyor. Dosya yoksa da yaratılıyor. C++'ta da öyle ise size kolaylık olsun diye söylemiştim.  Demek sizde farklı oluyor.

w+ ile açınca; eğer dosya mevcutsa siliyor, yeni dosya oluşturuyor bu durumda eski kayıtları kaybederiz. Ama sizin sorunuzu dikkate alarak dosyalama fonksiyonlarını inceledim ve a+ ile açınca - okuma, yazma, eski dosyayı silmeden sonuna kayıt ekleme -  gibi işlemlerin yapılabileceğini öğrenmiş oldum. Dediğiniz gibi dosac fonksiyonu gereksizmiş. Ama bizim asıl konumuz sil fonksiyonu idi  ;)

sem

#14
Anladım. Az önce de belirttiğim gibi mk.dat dosyası ile ilgili bir prototip oluşturamadım ben kafamda. Siz nasıl bir dosya oluşturmak istiyorsunuz örnek olarak  bir şey yazarsanız daha rahat yardım alabilirsiniz diye düşünüyorum...

--->>>Yani oluşturmak istediğiniz dosyanın bir benzeri gibi birşeyler yazarsanız demek istedim
".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?

hedzuben

#15
temsili mk.dat içeriği;

dön bebeğim
tarkan
a acayipsin
pop
--------------------
Creeping Death
metallica
Ride The Lightning
rock


başlık=parça başlığı
sanatçı=parçayı seslendiren sanatçı
albüm=albüm adı
tarz=şarkının tarzı' na karşılık gelir. Şu durumda dosyada iki kayıt var.





Mesaj tekrarı yüzünden mesajınız birleştirildi. Bu mesajın gönderim tarihi : 07 Nisan 2010 - 17:03:00

Sil fonksiyonunu yazmaya başladığımda asıl sorunum alana göre (baslik, sanatci,) silmeyi nasıl yapacağımdı. Bu tek bir alana göre silmek kadar kolay değil. Alana göre seçim yapmayı başardım. Şimdi asıl mesele; belirtilen kaydı silme işlemini gerçekleştirmek. fread, fwrite gibi fonksiyonlar var ama fdelete diye satır silen bir komut yok. remove() var ama o da dosyayı tümden siliyor. Satır(kayıt) silme işlemini nasıl yaparım.


void sil()
{
char girdi[50];
fp=fopen("mk.dat","a+");
system("cls");
cout<<"      SIL MENUSU\n";
cout<<"1- Parca Basligina Gore\n";
cout<<"2- Sanatci Ismine Gore\n";
cout<<"3- Albume Gore\n";
cout<<"4- Tarza Gore\n";
cout<<"4- Numaraya Gore\n";
switch (getch())
{
case '1':
#define alan sarki.baslik
break;
case '2':
#define alan sarki.sanatci
break;
case '3':
#define alan sarki.album
break;
case '4':
#define alan sarki.tarz
break;
/*case '5':
#define alan sarki.no*/
}
system("cls");
cin>>girdi;
fseek(fp,0L,SEEK_SET);
while (!feof(fp))
{
fread(&sarki,sizeof(struct muzik),1,fp);
if (!strcmp(alan,girdi))
cout<<"Bulundu : "<<alan<<"\n";
}
fclose(fp);
system("pause");
}


Yukarıdaki kodda kaydı sadece buluyorum. Silme işlemi için tavsiyeleriniz gerekli.
Ben tampon bir dosya kullanıp belirtilen kayıt hariç tüm kayıtları o dosyaya atmak sonra da tampondan geri mk.dat a yüklemek gibi bir yol düşündüm. Öyle yaparsam kayıt gerçekten silinir. Ama biraz uzun bir iş belki kolayı vardır.
not : no ya göre silme işlemini sonra yazacağım onu şimdilik dikkate almayın.

sem

#16
Arka sayfadaki kodlarda "numara göre"  ve "tarza göre" numaralarına dikkat edin aynı olmuş. Onu düzeltirsiniz pek sorun olmaz sanırım. Fakat numaraya göre silme işlemi hangi numaraya göre olacak mk.dat dosyasında bir numara belirtmemişsiniz? Bir de sanatçıya göre sildiğimiz zaman; sanatçının bütün şarkılarını bulup mu silecek, ya da "rock" girersek türe rock tarzındaki bütün şarkılar mı silinecek?
   Satır silme işlemi için önerebileceğim bir komut yok ama "dön bebeğim" anahtarı ile oluşturduğunuz başlık dosyasından  ilgili başlık, sanatçı, albüm, tarz bilgilerini ayıklayabiliyorsanız geçici dosya oluşturup istediğiniz bilgileri ayıkladıktan sonra, geçici dosyası mk.dat olarak kopyalayıp geçici dosyayı silerseniz, komutu bulana kadar, bekleme yapmadan projenize devam edebilirsiniz. Komutu bulunca ilgili yere koyarsınız. O sırada bilen birileri komut hakkında bilgilendirecektir sizi diye düşünüyorum...

NOT: Benim yazdıklarımı zaten yazmışsınız sonradan onları görmeden cevap vermiş bulundum... Yani en son gönderdiğimi dikkate almasanız  da olur...
".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?

hedzuben

Alıntı yapılan: sem0900 - 07 Nisan 2010 - 17:16:44
Fakat numaraya göre silme işlemi hangi numaraya göre olacak mk.dat dosyasında bir numara belirtmemişsiniz?
Numarayı dikkate almayın onu değiştireceğim. Belki de kaldırırım.
Alıntı yapılan: sem0900 - 07 Nisan 2010 - 17:16:44
Bir de sanatçıya göre sildiğimiz zaman; sanatçının bütün şarkılarını bulup mu silecek, ya da "rock" girersek türe rock tarzındaki bütün şarkılar mı silinecek?
Evet
Alıntı yapılan: sem0900 - 07 Nisan 2010 - 17:16:44
   Satır silme işlemi için önerebileceğim bir komut yok ama "dön bebeğim" anahtarı ile oluşturduğunuz başlık dosyasından  ilgili başlık, sanatçı, albüm, tarz bilgilerini ayıklayabiliyorsanız geçici dosya oluşturup istediğiniz bilgileri ayıkladıktan sonra, geçici dosyası mk.dat olarak kopyalayıp geçici dosyayı silerseniz, komutu bulana kadar, bekleme yapmadan projenize devam edebilirsiniz. Komutu bulunca ilgili yere koyarsınız. O sırada bilen birileri komut hakkında bilgilendirecektir sizi diye düşünüyorum...
Proje acele değil. Amaç öğrenmek. Çünkü o yöntemi bir hashing programında uygulamıştım uğraştırıyor. Belki kısa bir yolu vardır. Zaten şimdilik diğer fonksiyonları yazıyorum.

sem

Aslında C için satır silme işlemi benim de kafamı kurcalamakta. Ben printf() fonksiyonunun "\r"  ya da "\b" parametreleri daha doğrusu özel karakterleri ile denediğim zaman, bir dosyada kullanırsam örneğin; dosyayı "cat" ile ekrana yazdırırsam yapmaya çalıştığım sonucu alıyorum. Fakat aynı dosyaya "pico" ile girip baktığımda anlamsız karakterler çıkıyor... İsterseniz sizde "\r" ve "\b" ile bir deneyin...
system("cls"); --->>> burdan anladığım kadarı ile siz windows üzerinde çalışıyorsunuz ama cat ve pico'yu anlamışsınızdır diye düşünü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?

hedzuben


sem

'\r' veya '\b' karakterlerini kullandım mesela sem0900.txt dosyasında bir yazı işlemi yaparken.
"cat sem0900.txt" komutu ile "dosyayi ekrana yazdırırsam"  dosya içindeki değişiklikler, yapmaya çalıştığım şekilde ekrana basılıyor. Fakat "pico sem0900.txt" komutu ile "pico editörü ile txt dosyasının içine girdiğim" zaman anlamsız karakterler çıkıyor.
(pico metin editörü/cat bir dosyayı ekrana yazdırmak için kullandığım komut.)
   Sen de bahsettiğim özel karakterler ile deneyerek belki satır silme işlemini gerçekleştirebilirsin... Onlar ile de bir dene derim...
".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?

hedzuben

#21
Her kayda bir numara vereceğim. Çünkü her kaydın unique bir değeri olmalı. Otomatik sayı gibi yapmaya çalışıyorum. Ama sonsuz döngüye giriyor nedense. Kod şöyle;


fseek(fp,0L,SEEK_SET);
while(!feof(fp))
{
fseek(fp,sizeof(struct muzik),SEEK_CUR);
sayac++; //kaç kayıt var.
}

sem

#22
     Merhabalar, kolay gelsin. hedzuben, dosya göstericisi, dosya sonundan (EOF)  daha ileri yerlere konumlandırılabilir. Bu şekilde hatta "dosya delikleri" oluşturmak için senin yaptığın gibi daha ileri konumlandırıp, sonra yazma işlemleri yapılıyordu sanırım. Ne işe yarar dosya delikleri nerde kullanılır bir bilgim yok. Fakat dosya sonuna geldiğini;
for(;!feof(kaynak); )
{
   fprintf(kaynak,"Selamar\n");
}

     şeklinde ya da senin yaptığın gibi kontrol edemiyoruz. İstersen while döngüsüne içine fgets gibi bir okuma ile kontrol koy...
    /*fgets dediğim C için dosyadan okuma komutlarından biri.*/
".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?

hedzuben

fread ile yaptım ama yemedi. Aslında fseek ile olması lazım neden olmuyor. Dosya sonuna gelene kadar fp yi bulunduğu yerden sizeof (struck muzik) kadar ilerletecek böylece kaç kayıt olduğunu bulmuş olucak :/

sem

Evet bana da ilk önce çok garip gelmişti. Çok fazla zamanımı almıştı. İşte "dosya delikleri" diye bir kavram var. Az önce de dediğim gibi neden gerek duyuluyor bilgim yok. Fakat dosya deliklerini oluşturabilmek için fseek ile dosya göstericisi EOF'nin daha ilerisine konumlandırılarak, sonra yazma işlemi yapmak gerekiyor. Bundan dolayıdır diye tahmin ettiğim şekilde; bizim denediğimiz şeklillerde dosya sonu kontrolü yapılamıyor. fread ile neden olmadı? Tekrardan sonsuz döngüye mi girdi?
".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?