<div dir="ltr"><div>Buna, Darius,</div><div><br></div>Multumesc mult pentru explicatie!<div><br></div><div>Andra</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">În dum., 3 mar. 2019 la 13:25, Darius Mihai <<a href="mailto:dariusmihaim@gmail.com">dariusmihaim@gmail.com</a>> a scris:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Sun, Mar 3, 2019 at 1:19 PM Adrian Șendroiu via so<br>
<<a href="mailto:so@cursuri.cs.pub.ro" target="_blank">so@cursuri.cs.pub.ro</a>> wrote:<br>
><br>
> On Sun, 3 Mar 2019 at 13:05, Andra Danciu via so <<a href="mailto:so@cursuri.cs.pub.ro" target="_blank">so@cursuri.cs.pub.ro</a>> wrote:<br>
> ><br>
> > Hello!<br>
> ><br>
> > La cursul 2, la unul dintre demo-uri, Razvan Deaconescu a dat close pe stdin, a deschis un fisier si a citit un string cu scanf, presupunand ca scanf-ul va citi din fisier. La curs acest demo nu a mers, nu imi explic de ce. La mine a functionat. Am dat insa de un comportament ciudat.<br>
> ><br>
> > Acestui cod i-am dat ca argumente 3 fisiere random cu text in ele:<br>
> > <a href="https://pastebin.com/xhy4gt6d" rel="noreferrer" target="_blank">https://pastebin.com/xhy4gt6d</a><br>
> ><br>
> > La stdout se afiseaza primele 3 cuvinte din primul fisier, in loc sa afiseze primul cuvant din fiecare fisier. Fisierele sunt, cumva, serializate desi le inchid inainte sa citesc tot continutul (nu imi va citi nimic din fisierul 2 pana nu ajunge la finalul primului fisier). Care e explicatia?<br>
><br>
> Salut,<br>
><br>
> Explicația este că funcțiile din stdio fac buffering. Primul scanf<br>
> citește cu read într-un buffer mai mare, iar următoarele vor întoarce<br>
> date direct din buffer, fără să mai citească din fișier. scanf n-are<br>
> de unde să știe că între timp ai închis și redeschis file descriptorul<br>
> asociat lui stdin.<br>
<br>
Bună, Andra,<br>
<br>
Așa cum a spus și Adrian, problema este combinarea funcțiilor de<br>
sistem (open) cu funcții de bibliotecă (scanf). Cu toate că<br>
într-adevăr stdio folosește implicit file descriptor-ul 0 pentru a<br>
citi, iar close + open îl vor suprascrie, primul scanf va umple<br>
buffer-ul implicit al stdin cu date din primul fișier. Tu chiar dacă<br>
faci close pe stdin, funcțiile open și close sunt transmise direct<br>
sistemului de operare, iar funcțiile de bibliotecă nu vor goli<br>
buffer-ul.<br>
<br>
Abordarea coretă este:<br>
  - folosești freopen pentru a redeschide stdin pentru a citi din alt fișier<br>
  - folosești read pentru a citi datele din fișiere<br>
<br>
Dacă vrei să folosești neapărat close + open + scanf, trebuie să<br>
declari buffer-ul stdin ca NULL folosind setbuf(stdin, NULL);<br>
<br>
Darius<br>
</blockquote></div>