[Çözüldü] ungetc fonksiyonunu "r+" modunda dosyaya yazmama nedeni nedir?

Başlatan blacksnow, 24 Temmuz 2015 - 12:08:25

« önceki - sonraki »

0 Üyeler ve 5 Ziyaretçi konuyu incelemekte.

blacksnow

ungetc fonksiyonunun dosya üzerinde değişiklik yapmayıp sadece buffer üzerinde değişiklik yaptığını biliyorum.Dosyayı kapatmak için fclose fonksiyonunu çağırdığımda ise buffer boşaltılıp dosyaya yazılıyor diye biliyorum.Bu durumda "r+" modunda iken ungetc ile buffer üzerinde yapılan değişikliğin dosyaya yazılması gerekmiyor mu?Nedense öyle olmuyor.

putc fonksiyonu da aynı şekilde buffer' a yazıyor ve sonra buffer boşaldığında dosyaya yazıyor(yine "r+" modunda).Neden putc dosyaya yazabiliyorken, ungetc yazamıyor?
#include <stdio.h>
int main ()
{
FILE * file;
        file = fopen("file", "r+"); // file dosyasında sadece 'A' karakteri yazmakta, çıktıda da hiçbir değişiklik olmuyor.
        ungetc('B', file);

fclose(file);
return(0);
}
/* program sonlandığında file dosyasının içeriği */
A

Reverser

ungetc fonksiyonu, stream ile birlikte çalışır ve streamı okur ama dosyayı modifiye edemez. putc fonksiyonu, stream'a yazmak için kullanılır ve byte cinsinden dosyaya yazar.

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

int main (int argc, char *argv[])
{
   char buffer[256];
   FILE * file;
       file = fopen("file.txt", "a+"); // file dosyasında sadece 'A' karakteri yazmakta, çıktıda da hiçbir değişiklik olmuyor.
       ungetc('B', file);

//fclose(file);
fgets(buffer,256,file);
fputs(buffer,file);
return 0;
}

XFCE ROCKS !
Powered by Thunar & XFWM4



blacksnow

Alıntı Yapungetc fonksiyonu, stream ile birlikte çalışır ve streamı okur ama dosyayı modifiye edemez. putc fonksiyonu, stream'a yazmak için kullanılır ve byte cinsinden dosyaya yazar.
Burada stream ne anlama geliyor?Benim bildiğim dosyanın yazıldığı yer ve dosyaya yapılan girdilerin tutulduğu buffer var.Stream farklı bir şey mi yoksa buffer ile aynı şey mi?Biraz kavram karmaşası yaşıyorum.

Verdiğiniz örnekte buffer' dan veriyi okuyup tekrar fputs ile buffer' a yazılcağını düşünmüştüm.fputs girdileri önce bir buffer'a koyup sonra dosyaya yazmıyor mu?Tam olarak ne olaylar oluyor anlamayamadım.

-DıLgEş-

Stream kanal demek. Bu durumda C dili kanalları kontrol ediyor.
Aşkın; gözü kör, kulağı sağır, dili tutuk, aklı kıttır..! Hayır yani bu halde nasıl herkesi madara ediyor onu çözemedim..

blacksnow

Maalesef hiç anlamıyorum.Bu konuları nasıl öğrendiniz?Kaynak paylaşabilir misiniz?

-DıLgEş-

Ben bir değil birden çok kaynak kullandım, kaynaklarım c++ ve c var. Size yarın indirme adresini yollarım.
Aşkın; gözü kör, kulağı sağır, dili tutuk, aklı kıttır..! Hayır yani bu halde nasıl herkesi madara ediyor onu çözemedim..

blacksnow

Alıntı Yapungetc İşlevi

Bu işlev dosyadan okunan karakteri, dosyanın tampon alanına geri koyar.
int ungetc(int c, FILE *f);
ungetc işlevi için dosyanın okuma modunda açılmış olması gerekir. İşlevin çağrılmasından sonra yapılan ilk okumada c değeri okunur. İşlev başarılı olursa, c değerine geri döner.Başarısızlık durumunda dosyanın tampon alanında bir değişiklik olmaz ve EOF değeri döndürülür. İşlev, karakteri tampon alanına yerleştirdikten sonra EOF bayrağını da sıfırlar. Dosya konum göstericisi yeniden konumlandırılmadan ungetc işlevi arka arkayaçağırılmamalıdır.

Necati Ergin - C Ders Notları

Burada da anlatılana göre okunanan karakter dosyaya değil bir tampon alanına yazılıyor.Dosya modifiye edilmiyor.Buraya kadar tamam fakat sonra ben fclose ile dosyayı kapattığımda dosya için ayrılan tampon bölge dosyaya yazılmıyor mu?Bu esnada ungetc ile tampona yazılan karakterde dosyaya yazılması gerekmiyor mu?Anlamak istediğim tek şey bu.

Düzenleme:
Alıntı yapılan: Reverser - 24 Temmuz 2015 - 13:12:35
ungetc fonksiyonu, stream ile birlikte çalışır ve streamı okur ama dosyayı modifiye edemez. putc fonksiyonu, stream'a yazmak için kullanılır ve byte cinsinden dosyaya yazar.

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

int main (int argc, char *argv[])
{
   char buffer[256];
   FILE * file;
       file = fopen("file.txt", "a+"); // file dosyasında sadece 'A' karakteri yazmakta, çıktıda da hiçbir değişiklik olmuyor.
       ungetc('B', file);

//fclose(file);
fgets(buffer,256,file);
fputs(buffer,file);
return 0;
}

@Reverser, yazdığınız kodları tekrardan inceledim.Programın nasıl çalıştığını anlatmak istiyorum.Yanlışlarımı düzeltirseniz daha iyi anlayacağım.

1- İlk önce dosyayı fopen ile açtığımızda dosyadaki ilk satır file dosyasının tampon bölgesine kopyalanıyor.
2- Sonra tampon bölgesini ungetc ile bir karakter geri alınıp 'B' karakteri ekleniyor.
3- fgets fonksiyonu da file dosyasının tamponundan 255 karakterlik bölümü kopyalayıp buffer dizisine kopyalıyor.
4- Daha sonra fputs fonksiyonu ile buffer dizisi, file dosyasının tamponuna tekrar yazılıyor.
5- En son program sonlandığı için dosyalar kendiliğinden kapandığı için file dosyasının tamponunu dosyanın içine yazılıyor.

4. aşamada anlama sorunu yaşıyorum.Muhtemelen yanlış düşünüyorum.Eğer bu şekilde açıklayabilirseniz anlayabilirim.Şimdiden teşekkürler.

-DıLgEş-

C streamları otomatik olarak konsola bağlıdır. Bu durumda yazdığınız her şey tampon bölgeye yazıldıktan sonra dosya kapandığında konsola aktarır. Dosyaya sadece bytes yoluyla yazar.
Aşkın; gözü kör, kulağı sağır, dili tutuk, aklı kıttır..! Hayır yani bu halde nasıl herkesi madara ediyor onu çözemedim..

blacksnow

Alıntı yapılan: nurullahisrgan - 25 Temmuz 2015 - 14:20:23
C streamları otomatik olarak konsola bağlıdır. Bu durumda yazdığınız her şey tampon bölgeye yazıldıktan sonra dosya kapandığında konsola aktarır. Dosyaya sadece bytes yoluyla yazar.
Sizde aynı şeyi söylüyorsunuz.Benim dediklerimden bir farkı yok.O zaman ilk örnekte ungetc ile tampon bölgeye yazılanlar fclose ile dosya kapandığında neden dosyaya aktarılmıyor.Dosya "r+" modunda yazmaması için neden nedir?

Reverser

@blacksnow, tabii ki nedendir.
"r+" ve "w+" ikisi de dosyaya yazıp okuyabilir ama "r+" dosya içeriğini silmez ve eğer bahsi geçen dosya yoksa, dosyayı oluşturmaz.
"w+" ile dosya içeriğini siler ve dosya yoksa dosyayı oluşturur.


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

int main (int argc, char *argv[])
{
   char buffer[256];
   FILE * file;
   file = fopen("file.txt", "w+");
   ungetc('B', file);

fgets(buffer,256,file);
fputs(buffer,file);
fclose(file);
return 0;
}


XFCE ROCKS !
Powered by Thunar & XFWM4



blacksnow

Alıntı yapılan: Reverser - 25 Temmuz 2015 - 15:00:35
@blacksnow, tabii ki nedendir.
"r+" ve "w+" ikisi de dosyaya yazıp okuyabilir ama "r+" dosya içeriğini silmez ve eğer bahsi geçen dosya yoksa, dosyayı oluşturmaz.
"w+" ile dosya içeriğini siler ve dosya yoksa dosyayı oluşturur.


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

int main (int argc, char *argv[])
{
   char buffer[256];
   FILE * file;
   file = fopen("file.txt", "w+");
   ungetc('B', file);

fgets(buffer,256,file);
fputs(buffer,file);
fclose(file);
return 0;
}

Dosyayı daha önceden oluşturduğum için "r+" modunda yazması gerekli.Sizin ilk yazdığınız kod bir çözüm fakat benim sorumu yanıtlamıyor.
İlk yazdığım örneği incelerseniz, sanki ungetc için ayrı bir tampon var gibi ve bu tampon dosya modu ne olursa olsun dosyaya yazdırılmıyor.Tabi bu benim fikrim, herhangi bir kanıtım yok.

Burada verilen ilk cevabın yorumlarını okursanız ungetc için ayrı bir tampon olduğundan bahsediliyor.
http://stackoverflow.com/questions/23338218/fopen-in-read-only-mode-and-its-buffer

blacksnow

Konu hakkında cevaplar yazıldı fakat tam olarak istediğimi alamadım.Soruyu tekrarlamak istiyorum ama bu sefer herhangi bir çözüm beklemiyorum.Konunun en başında yazdığım program neden beklediğim gibi çalışmıyor? Direkt program üzerinde hatayı gösteriniz.

Amenofis

Bu fonksiyonu daha önce hiç kullanmadım. Ne amaçla kullanıldığını da anlamadım ama dokumanlarda dosya üzerinde herhangi bir değişiklik yapmadığı yazıyor. Zaten sadece girdi dosyalarında kullanıldığı için dosyayı güncellemesi mümkün değil.

unget için ayrı tampon diye bişey olmaz. Giriş tamponu üzerinde değişiklik yapıyor fakat adı üzerinde "giriş" tamponu, yani dosyaya yansıtılması mümkün olamaz.

blacksnow

@Amenofis, giriş tamponu derken okuma yaparken kullanılandan bahsediyorsunuz sanırım.Dosyayı güncellemesi mümkün değil dediniz, ben aslında bu sınırlamayı nasıl yapıyorlar onu merak etmiştim.Mesela ungetc fonksiyonundan sonra putc ile bir şey yazmaya çalışırsam segmentation fault hatası alıyorum.Burada mesela ungetc sadece okuma yaptığı için putc varolan tampona bir şeyler yazmaya çalıştığında bu hatayı verdiğini düşünmüştüm.Yine buna da bir kanıtım yok.Açıkcası arka planda neler dönüyor onu merak ediyorum.

Yukarıda bahsettiğim örnek;
#include <stdio.h>
int main ()
{
char buffer[256];
FILE * file;
        file = fopen("file", "r+");

ungetc('A', file);
putc('B', file);           // Segmentation fault

fgets(buffer, 255, file);
fputs(buffer, stdout);

fclose(file);
return(0);
}

Amenofis

Orada ilk yaptığın işlem unget olduğu için seg fault alıyorsun. getc dosya işaretçisini 1 arttırırken ungetc 1 azaltıyor. İlk işlem ungetc olunca işaretçi -1 konumunu gösteriyor, geçersiz bi konuma yazmaya kalkınca da ban yiyorsun.

blacksnow

Alıntı yapılan: Amenofis - 26 Temmuz 2015 - 23:28:51
Orada ilk yaptığın işlem unget olduğu için seg fault alıyorsun. getc dosya işaretçisini 1 arttırırken ungetc 1 azaltıyor. İlk işlem ungetc olunca işaretçi -1 konumunu gösteriyor, geçersiz bi konuma yazmaya kalkınca da ban yiyorsun.
Aynı dediğiniz gibi oluyormuş.Bunu düşünmemiştim hiç.Asıl konuya dönersekte, ungetc okuma yapmak için kullanılan bir fonksiyon olduğu için dosyaya yazma yapması bir şekilde engellenmiş.Bunun şu an nasıl yapıldığını anlayamadım fakat daha da ilerledikçe kaynak kodları okuyup merakımı giderebilirim.Herkese teşekkürler.