Differences

This shows you the differences between two versions of the page.

Link to this comparison view

so:laboratoare:laborator-02 [2019/02/24 17:25]
bogdan.purcareata [Eliminare punctaje si solutii]
so:laboratoare:laborator-02 [2022/03/11 16:38] (current)
aapostolescu [Trunchierea fișierelor] typo
Line 2: Line 2:
 ===== Materiale ajutătoare ===== ===== Materiale ajutătoare =====
  
-  * [[http://​elf.cs.pub.ro/​so/​res/​laboratoare/​lab02-slides.pdf | lab02-slides.pdf]] 
-  * [[http://​elf.cs.pub.ro/​so/​res/​laboratoare/​lab02-refcard.pdf | lab02-refcard.pdf]] 
   * [[http://​elf.cs.pub.ro/​so/​res/​tutorial/​lab-02-operatii-io/​ | Video Operații IO]]   * [[http://​elf.cs.pub.ro/​so/​res/​tutorial/​lab-02-operatii-io/​ | Video Operații IO]]
  
Line 41: Line 39:
 Un fișier are asociat cursorul de fișier (file pointer) care indică poziția curentă în cadrul fișierului. Cursorul de fișier este un întreg care reprezintă deplasamentul (offset-ul) față de începutul fișierului. Un fișier are asociat cursorul de fișier (file pointer) care indică poziția curentă în cadrul fișierului. Cursorul de fișier este un întreg care reprezintă deplasamentul (offset-ul) față de începutul fișierului.
  
-Operațiile ​specifice pentru lucrul ​cu fișiere: +Pentru a crea o paralelă între operațiile cu fișiere ​de pe Linux și Windows, vă punem la dispoziție tabelul de mai jos unde sunt descrise diverse funcționalități împreună cu apelurile de sistem care le implementează. 
-    ​* ​**deschiderea/crearea unui fișier** - înseamnă asocierea unui descriptor de fișier sau a unui handle cu un fișier identificat prin numele său (( ''​fopen'' ​(ISO C), ''​open'',​ ''​creat''​ (POSIX), ''​CreateFile''​ (Win32 API) )). ( [[#crearea deschiderea si inchiderea fisierelor|Linux]][[#crearea deschiderea si inchiderea|Windows]] ) + 
-    ​* ​**închiderea ​unui fișier** - înseamnă eliberarea structurilor de fișier asociate procesului și a descriptorului (handle-ului) acelui fișier - doar dacă nu mai există nici o intrare în tabela file descriptorilor care să puncteze spre acea structură ​(( ''​fclose'' ​(ISO C), ''​close''​ (POSIX), ''​CloseHandle''​ (Win32 API) )). ( [[#crearea deschiderea si inchiderea fisierelor|Linux]][[#crearea deschiderea si inchiderea|Windows]] ) +^  Descriere ​ ^  ISO C  ^  Linux  ^  Windows ​ ^ 
-    * **citirea ​dintr-un fișier** - înseamnă copierea unui bloc de date într-un buffer; după ce se realizează citirea se actualizează cursorul de fișier ​(( ''​fread'' ​(ISO C), ''​read''​ (POSIX), ''​ReadFile''​ (Win32 API) )). ( [[#scrierea si citirea|Linux]][[#citirea si scrierea|Windows]] ) +**Deschiderea/crearea unui fișier** - înseamnă asocierea unui descriptor de fișier sau a unui handle cu un fișier identificat prin numele său. |  ​''​fopen'' ​ ​|  ​[[#open|open]]  ​|  ​[[#createfile|CreateFile]]  | 
-    ​* ​**scrierea ​într-un fișier** - înseamnă copierea unui bloc de date dintr-un buffer în fișier; efectuarea scrierii înseamnă și actualizarea cursorului de fișier ​(( ''​fwrite'' ​(ISO C), ''​write''​ (POSIX), ''​WriteFile''​ (Win32 API) )). ( [[#scrierea si citirea|Linux]][[#citirea si scrierea|Windows]] ) +**Închiderea ​unui fișier** - înseamnă eliberarea structurilor de fișier asociate procesului și a descriptorului (handle-ului) acelui fișier - doar dacă nu mai există nici o intrare în tabela file descriptorilor care să puncteze spre acea structură. | ''​fclose'' ​|  ​[[#close|close]]  ​|  ​[[#closehandle|CloseHandle]]  | 
-    ​* ​**poziționarea într-un fișier** - înseamnă schimbarea valorii cursorului de fișier; citirile sau scrierile ulterioare vor porni din locul indicat de acest cursor de fișier ​((''​fseek'' ​(ISO C), ''​lseek''​ (POSIX), ''​SetFilePointer''​ (Win32 API) )). ( [[#​pozitionarea in fisier lseek|Linux]][[#​pozitionarea in fisier|Windows]] ) +**Citirea ​dintr-un fișier** - înseamnă copierea unui bloc de date într-un buffer; după ce se realizează citirease actualizează cursorul de fișier. |  ​''​fread'' ​ ​|  ​[[#read|read]]  ​|  ​[[#readfile|ReadFile]]  | 
-    * **schimbarea ​atributelor unui fișier** - înseamnă stabilirea unor parametri pentru fișier ​(( ''​fcntl''​ (POSIX), ​SetFileAttributes (Win32 API) )). [[#operatii speciale|Linux]])+**Scrierea ​într-un fișier** - înseamnă copierea unui bloc de date dintr-un buffer în fișier; efectuarea scrierii înseamnă și actualizarea cursorului de fișier. |  ​''​fwrite'' ​ ​|  ​[[#write|write]]  ​|  ​[[#writefile|WriteFile]]  | 
 +**Poziționarea într-un fișier** - înseamnă schimbarea valorii cursorului de fișier; citirile sau scrierile ulterioare vor porni din locul indicat de acest cursor de fișier. |  ​''​fseek'' ​ ​|  ​[[#​pozitionarea in fisier lseek|lseek]]  ​|  ​[[#​pozitionarea in fisier|SetFilePointer]]  | 
 +**Schimbarea ​atributelor unui fișier** - înseamnă stabilirea unor parametri pentru fișier. |  -    |  [[#operatii speciale|fcntl]]  |  [[https://​docs.microsoft.com/​en-us/​windows/​win32/​api/​fileapi/​nf-fileapi-setfileattributesa|SetFileAttributes]]  | 
 +| **Trunchierea fișierelor** - înseamnă modificarea dimensiunii unui fișier. |  -  |  [[#​trunchierea_fisierelor|ftruncate]] ​ |  [[#​trunchierea_fisierelor1|SetEndOfFile]] ​ | 
 +| **Redirectarea** - înseamnă modificarea unui descriptor de fișier al unui proces ​(de obicei intrarea, ieșirea sau eroarea standardcătre alt descriptor de fișier, de obicei cu scopul de a opera cu un fișier in același mod cu care operam cu intrarea, ieșirea sau eroarea standard|  -  |  ​[[#redirectari|dup]], [[#​redirectari|dup2]] ​ |  Modificarea structurii [[https://​docs.microsoft.com/​en-us/​windows/​win32/​api/​processthreadsapi/​ns-processthreadsapi-startupinfoa?​redirectedfrom=MSDN | StartupInfo]] dată ca argument pentru [[https://​docs.microsoft.com/​en-us/​windows/​win32/​api/​processthreadsapi/​nf-processthreadsapi-createprocessa?​redirectedfrom=MSDN|CreateProcess]] ​ |
  
 ===== Operații pe fișiere în Linux ===== ===== Operații pe fișiere în Linux =====
Line 57: Line 59:
  
 <code c> <code c>
-int open(const char *pathname, int flag);               /* deschidere */+int open(const char *pathname, int flags);               /* deschidere */
 int open(const char *pathname, int flags, mode_t mode); ​ /* creare */ int open(const char *pathname, int flags, mode_t mode); ​ /* creare */
 </​code>​ </​code>​
Line 139: Line 141:
 </​code>​ </​code>​
  
-Funcția [[http://​linux.die.net/​man/​2/​read|read]] întoarce numărul de octeți efectiv citiți, cel mult ''​count''​. Valoarea minimă este de ''​1''​ octet, iar când se ajunge la sfârșitul de fișier se va întoarce ''​0''​.+Funcția [[http://​linux.die.net/​man/​2/​read|read]] întoarce numărul de octeți efectiv citiți, ​**cel mult** ''​count''​. Valoarea minimă este de ''​1''​ octet, iar când se ajunge la sfârșitul de fișier se va întoarce ''​0''​.
  
 === write === === write ===
Line 149: Line 151:
 </​code>​ </​code>​
  
-Valoarea întoarsă este numărul de octeți ce au fost efectiv scriși, cel mult ''​count''​. În mod implicit nu se garantează că la revenirea din [[http://​linux.die.net/​man/​2/​write|write]] scrierea în fișier s-a terminat. Pentru a forța actualizarea se poate folosi [[http://​linux.die.net/​man/​2/​fsync|fsync]] sau fișierul se poate deschide folosind flagul ''​O_FSYNC'',​ caz în care se garantează că după fiecare write fișierul a fost actualizat.+Valoarea întoarsă este numărul de octeți ce au fost efectiv scriși, ​**cel mult** ''​count''​. În mod implicit nu se garantează că la revenirea din [[http://​linux.die.net/​man/​2/​write|write]] scrierea în fișier s-a terminat. Pentru a forța actualizarea se poate folosi [[http://​linux.die.net/​man/​2/​fsync|fsync]] sau fișierul se poate deschide folosind flagul ''​O_FSYNC'',​ caz în care se garantează că după fiecare write fișierul a fost actualizat.
  
 **Observație 1**:  **Observație 1**: 
Line 190: Line 192:
 </​code>​ </​code>​
  
-În cazul [[http://​linux.die.net/​man/​2/​ftruncate|ftruncate]],​ parametrul ''​fd''​ este file descriptorul obținut cu un apel open, care a asigurat drept de scriere. În cazul [[http://​linux.die.net/​man/​2/​ftruncate|truncate]],​ fișierul reprezentat prin ''​path''​ trebuie să aibe drept de scriere.+În cazul [[http://​linux.die.net/​man/​2/​ftruncate|ftruncate]],​ parametrul ''​fd''​ este file descriptorul obținut cu un apel open, care a asigurat drept de scriere. În cazul [[http://​linux.die.net/​man/​2/​ftruncate|truncate]],​ fișierul reprezentat prin ''​path''​ trebuie să aibă drept de scriere.
  
 ==== Exemplu utilizare operații I/O === ==== Exemplu utilizare operații I/O ===
Line 254: Line 256:
 </​code>​ </​code>​
 * dup * dup
-  * creaza ​o copie a unui file descriptor/ +  * crează ​o copie a unui file descriptor. 
-  * utilizeaza ​cel mai mic numar de descriptor neutilizat. +  * utilizează ​cel mai mic număr ​de descriptor neutilizat. 
-  * daca apelul ​reuseste, vechiul ​si noul file descriptor pot fi folositi, ei partajand ​file offset ​si file status flags.+  * dacă apelul ​reușește, vechiul ​și noul file descriptor pot fi folosiți, ei partajând ​file offset ​și file status flags.
  * dup2  * dup2
-   ​* ​asemanator ​dup, dar in loc sa se aleaga ​cel mai mic descriptor, acesta ​utilizeaza ​new_fd specificat. +   ​* ​asemănător ​dup, dar în loc să se aleagă ​cel mai mic descriptor, acesta ​utilizează ​new_fd specificat. 
-   ​* ​daca new_fd este deja fosit, acesta este mai intai inchis inainte ​de a fi reutilizat. +   ​* ​dacă new_fd este deja folosit, acesta este mai întâi închis înainte ​de a fi reutilizat. 
-   ​* ​daca old_fd nu este valid, apelul ​esueaza ​iar new_fd nu este inchis.+   ​* ​dacă old_fd nu este valid, apelul ​eșueaza ​iar new_fd nu este închis.
  
  
Line 269: Line 271:
 </​code>​ </​code>​
  
-Imaginea de mai jos prezinta ​utilizarea dup si dup2 in diferite ​situatii ​pentru o intelegere ​mai buna:+Imaginea de mai jos prezintă ​utilizarea dup și dup2 în diferite ​situații ​pentru o înțelegere ​mai bună:
  
  
Line 663: Line 665:
 </​spoiler>​ </​spoiler>​
 ===== Exerciții ===== ===== Exerciții =====
 +<note important>​
 +În cadrul laboratoarelor vom folosi repository-ul de git al materiei SO - https://​github.com/​systems-cs-pub-ro/​so. Va trebui sa clonați repository-ul pe masinile virtuale folosind comanda: ''​git clone https://​github.com/​systems-cs-pub-ro/​so''​. Dacă doriți să descărcați repositoryul în altă locație, folosiți comanda ''​git clone https://​github.com/​systems-cs-pub-ro/​so ${target}''​.
  
-În rezolvarea laboratorului ​folosiți ​arhiva ​de sarcini [[http://elf.cs.pub.ro/so/res/​laboratoare/​lab02-tasks.zip | lab02-tasks.zip]].+Pentru a actualiza repository-ul,​ folosiți comanda ''​git pull origin master''​ din interiorul directorului în care se află repository-ul. Recomandarea este să îl actualizați cât mai frecvent, înainte să începeți lucrul, pentru a vă asigura că aveți versiunea cea mai recentă. ​În cazul în care gitul detectează conflicte la nivelul vreunui fişier, ​folosiți ​următoarele comenzi pentru a vă păstra modificările:​ 
 +<​code>​ 
 +git stash 
 +git pull origin master 
 +git stash pop 
 +</​code>​ 
 + 
 +Pentru mai multe informații despre folosirea utilitarului git, urmați ghidul ​de la https://gitimmersion.com. 
 +</note>
  
 **Observații**:​ Pentru a vă ajuta la implementarea exercițiilor din laborator, în directorul ''​utils''​ din arhivă există un fișier ''​utils.h''​ cu funcții utile. **Observații**:​ Pentru a vă ajuta la implementarea exercițiilor din laborator, în directorul ''​utils''​ din arhivă există un fișier ''​utils.h''​ cu funcții utile.
Line 673: Line 685:
 </​note>​ </​note>​
  
-==== Exercițiul -1 - GSOC ==== +==== Exercițiul ​Stagii pe bune ==== 
-Google Summer of Code este un program de vară în care studenții +[[https://stagiipebune.ro/students/jobs/|Stagii pe bune]] este o platformă ​de internshipuri care vrea să ușureze și să uniformizeze procesul prin care puteți aplica la companii din România ​(București, Iași, Cluj și Timișoara)Facultatea de Automatică și Calculatoare are un parteneriat cu Stagii pe bune și vă încurajăm să le folosiți platforma pentru a aplica la internshipuri! ​
-(indiferent de anul de studiu) sunt implicați în proiecte Open Source +
-pentru a își dezvolta skill-urile de programare, fiind răsplătiți cu o +
-bursă a cărei valoare ​[[https://developers.google.com/open-source/gsoc/help/​student-stipends|depinde ​de țară]] +
-([[https://​developers.google.com/​open-source/​gsoc|pagină principală GSOC]]).+
  
-UPB se află în top ca număr de studențacceptați; în fiecare an fiind +Stagii pe bune organizează șevenimente ​de prezentare a celor mai mari companii din RomâniaPentru a fi la curent cu acestea, urmăriți și anunțurile postate ​de Stagii pe bune pe [[https://​www.facebook.com/​stagiipebune|Facebook]].
-undeva la aprox. 30-40 de studenți acceptați. +
-Vă încurajăm să aplicați! Există ​și un grup de fb cu foști +
-participanți unde puteti să îi contactați pentru sfaturi +
-[[https://​www.facebook.com/​groups/​240794072931431/​|facebook page]] +
- +
-==== Exercițiul 0 - Joc interactiv ==== +
- +
-    * Detalii desfășurare [[http://​ocw.cs.pub.ro/​courses/​so/​meta/​notare#​joc_interactiv|joc]].+
  
 ===== Linux ===== ===== Linux =====
Line 741: Line 741:
 === 3c. /dev/nasty === === 3c. /dev/nasty ===
  
-Inițializați fișierul ''/​dev/​nasty'':<​code bash>​./​set_nasty.sh</​code>​+Inițializați fișierul ''/​dev/​nasty'':​ 
 +<code bash> 
 +sudo apt-get install linux-modules-$(uname -r) linux-headers-$(uname -r) 
 +./​set_nasty.sh 
 +</​code>​
  
 Încercați funcționalitatea de copiere pe fișierul ''/​dev/​nasty'':​ <code bash>​./​mcat /dev/nasty Încercați funcționalitatea de copiere pe fișierul ''/​dev/​nasty'':​ <code bash>​./​mcat /dev/nasty
Line 750: Line 754:
 Testați **scrierea** cu: <code bash>​./​mcat Makefile /dev/nasty ; cat /​dev/​nasty</​code>​ Testați **scrierea** cu: <code bash>​./​mcat Makefile /dev/nasty ; cat /​dev/​nasty</​code>​
 <note tip> <note tip>
-În cazul în care ultima comandă nu produce rezultatul așteptat, cel mai probabil nu ați tratat corect cazurile în care ''​read''/''​write''​ întorc o valoare mai mică decât al treilea parametru.  ​+În cazul în care ultima comandă nu produce rezultatul așteptat, cel mai probabil nu ați tratat corect cazurile în care ''​read''/''​write''​ întorc o valoare mai mică decât al treilea parametru ​- i.e. nu s-a citit/scris tot.  ​
  
 **Hint: ** Pentru a garanta scrierea/​citirea numarului exact de bytes care este dat ca parametru, se recomanda apelarea read/write **in bucla.** ​ **Hint: ** Pentru a garanta scrierea/​citirea numarului exact de bytes care este dat ca parametru, se recomanda apelarea read/write **in bucla.** ​
Line 764: Line 768:
 Deschideți folderul ''​win''​ din arhiva laboratorului 2 și intrați în proiectul ''​1-cat'',​ iar apoi urmăriți sursa ''​cat.c''​ Deschideți folderul ''​win''​ din arhiva laboratorului 2 și intrați în proiectul ''​1-cat'',​ iar apoi urmăriți sursa ''​cat.c''​
  
-Compilați și testați executabilul ''​cat.exe''​ folosind command prompt-ul de Visual Studio: Tools -> Visual Studio Command Prompt+Compilați și testați executabilul ''​cat.exe''​ folosind command prompt-ul de Visual Studio: Tools -> Visual Studio Command Prompt, sau folosind Makefile-ul. 
 + 
 +<​note>​ 
 +Observați că cei ''​bytesRead''​ octeți prin apelul ''​ReadFile''​ sunt scriși la ''​stdout''​ **intr-o buclă**, deoarece nu avem garanția că ''​WriteFile''​ va scrie întotdeauna atâția octeți cât îi specificăm prin al treilea parametru (''​dwBytesToWrite''​). 
 + 
 +Folosiți această tehnică și la exercițiile următoare! 
 +</​note>​ 
  
 ==== Exercițiul 2 - CRC ==== ==== Exercițiul 2 - CRC ====
Line 780: Line 791:
 Revedeți secțiunile [[#crearea deschiderea si inchiderea|Crearea,​ deschiderea și închiderea fișierelor]],​ cât și [[#citirea si scrierea|Citirea și scrierea fișierelor]]. Revedeți secțiunile [[#crearea deschiderea si inchiderea|Crearea,​ deschiderea și închiderea fișierelor]],​ cât și [[#citirea si scrierea|Citirea și scrierea fișierelor]].
  
-Urmăriți comentariile cu ''​TODO 1''​.+Urmăriți comentariile cu ''​TODO 1''​. ​Pentru testare folosiți-vă de fișierele din directorul ''​tests''​. Pentru a compara două fișiere, puteți folosi utilitarul ''​comp''​ astfel: 
 +<​code>​ 
 +PS C:...> .\crc.exe -g tests\test_in\test1.in crc1.out 
 +PS C:...> comp.exe crc1.out tests\test_out\test1.out 
 +</​code>​
  
 === 2b. Comparare === === 2b. Comparare ===
Line 790: Line 805:
   * Folosiți doar funcția ''​[[http://​msdn.microsoft.com/​en-us/​library/​aa365541%28VS.85%29.aspx|SetFilePointer]]''​   * Folosiți doar funcția ''​[[http://​msdn.microsoft.com/​en-us/​library/​aa365541%28VS.85%29.aspx|SetFilePointer]]''​
  
-Dacă dimensiunile sunt egale, comparați cele 2 fișiere bucată cu bucată. ​Deși în acest caz particular fișierele de comparat conțin doar câte un CRC de 4 octeți, funcția trebuie să trateze și cazul în care fișierele sunt mai mari. Nu citiți tot fișierul în memorie, ci câte ''​CHUNKSIZE = 32''​ bytes o dată. ​Urmăriți comentariile marcate cu ''​TODO ​3''​.+Dacă dimensiunile sunt egale, comparați cele 2 fișiere bucată cu bucată. ​Funcția trebuie să compare corect cele două fișiere, indiferent de dimensiunea acestora. Nu citiți tot fișierul în memorie, ci câte ''​CHUNKSIZE = 32''​ bytes o dată. ​Pentru aceasta, va trebui să implementați funcția ''​ReadChunk'',​ urmand indicațiile de la ''​TODO 3''​. Apoi, urmăriți comentariile marcate cu ''​TODO ​4''​. 
 + 
 +<note important>​ 
 +Pentru a putea compara un fișier cu el însuși, va trebui ca în cadrul funcției ''​CompareFiles''​ să deschideți ambele fișiere folosind ''​FILE_SHARE_READ''​. 
 +</​note>​
  
 ==== BONUS - Linux ==== ==== BONUS - Linux ====
Line 816: Line 835:
 Utilitar echivalent cu ''​ls -a -R''​. Utilitar echivalent cu ''​ls -a -R''​.
  
-== Creare utilitar ls ==+=== Creare utilitar ls ===
  
-Deschideți din arhiva laboratorului 2 proiectul ''​3-ls''​. Completați fișierul ''​ls.c''​ pentru ca programul ''​3-ls.exe''​ să se comporte ca utilitarul ''​ls''​.+Deschideți din arhiva laboratorului 2 proiectul ''​3-ls''​. Completați fișierul ''​ls.c''​ pentru ca programul ''​ls.exe''​ să se comporte ca utilitarul ''​ls''​.
  
 Afișarea fișierelor dintr-un director se face în doi pași: Afișarea fișierelor dintr-un director se face în doi pași:
Line 824: Line 843:
     * se iterează această listă folosind funcția: [[http://​msdn.microsoft.com/​en-us/​library/​aa364428%28VS.85%29.aspx|FindNextFile]]     * se iterează această listă folosind funcția: [[http://​msdn.microsoft.com/​en-us/​library/​aa364428%28VS.85%29.aspx|FindNextFile]]
    
- Pentru rezolvare, urmăriți comentariile marcate cu  ''​TODO 1''​. +Pentru rezolvare, urmăriți comentariile marcate cu  ''​TODO 1''​. ​Ca să afișați detaliile cu o spațiere consecventă,​ folosiți funcția ''​PrintPadding''​ definită în schelet, iar pentru ​testarefolosiți dintr-un prompt Visual Studio: <code bash>​ls.exe ..</​code>​
-Pentru ​testare folosiți dintr-un prompt Visual Studio: <code bash>​ls.exe ..</​code>​+
  
 == Afișare detalii pentru parametrul -a == == Afișare detalii pentru parametrul -a ==
Line 833: Line 851:
  
 Atributele unui fișier sunt definite într-o structură de forma: [[http://​msdn.microsoft.com/​en-us/​library/​aa365740%28VS.85%29.aspx|WIN32_FIND_DATA]]. Pentru a verifica dacă un fișier e director, trebuie să aibă bitul "​FILE_ATTRIBUTE_DIRECTORY" ​ din câmpul "​dwFileAttributes"​ ( vezi [[http://​msdn.microsoft.com/​en-us/​library/​ee332330%28v=VS.85%29.aspx|File Attributes]]). Atributele unui fișier sunt definite într-o structură de forma: [[http://​msdn.microsoft.com/​en-us/​library/​aa365740%28VS.85%29.aspx|WIN32_FIND_DATA]]. Pentru a verifica dacă un fișier e director, trebuie să aibă bitul "​FILE_ATTRIBUTE_DIRECTORY" ​ din câmpul "​dwFileAttributes"​ ( vezi [[http://​msdn.microsoft.com/​en-us/​library/​ee332330%28v=VS.85%29.aspx|File Attributes]]).
-   * Urmăriți comentariile marcate cu  ''​TODO 2''​+   * Urmăriți comentariile marcate cu  ''​TODO 2''​
 +   * Pentru a afișa detaliile cu o spațiere consecventă,​ folosiți funcția ''​PrintPadding''​ definită în schelet.
  
 == Afișare detalii pentru parametrul -R == == Afișare detalii pentru parametrul -R ==
Line 841: Line 860:
 Pentru rezolvare, urmăriți comentariile marcate cu ''​TODO 3''​. Aveți grijă să concatenați numele noului director la calea deja existentă. Pentru rezolvare, urmăriți comentariile marcate cu ''​TODO 3''​. Aveți grijă să concatenați numele noului director la calea deja existentă.
  
-== Troubleshooting ==+=== Troubleshooting ​===
  
 Deschideți din arhiva laboratorului 2 proiectul ''​4-trouble''​. Programul ar trebui să creeze un fișier cu mesajul "​Testing 123". Deschideți din arhiva laboratorului 2 proiectul ''​4-trouble''​. Programul ar trebui să creeze un fișier cu mesajul "​Testing 123".
Line 852: Line 871:
     *Studiați exemplele din {{so:​laboratoare:​pyfileoperations.zip|arhivă}},​ citiți documentația și observați diferențele între API-uri     *Studiați exemplele din {{so:​laboratoare:​pyfileoperations.zip|arhivă}},​ citiți documentația și observați diferențele între API-uri
  
-/* 
- 
-===== Soluții ===== 
- 
-[[http://​elf.cs.pub.ro/​so/​res/​laboratoare/​lab02-sol.zip | lab02-sol.zip]] 
  
-*/ 
  
 ===== Resurse utile ===== ===== Resurse utile =====
so/laboratoare/laborator-02.txt · Last modified: 2022/03/11 16:38 by aapostolescu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0