Differences

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

Link to this comparison view

poo:laboratoare:13 [2026/01/12 08:42]
george.tudor1906
poo:laboratoare:13 [2026/01/12 08:46] (current)
george.tudor1906
Line 1: Line 1:
  
-===== Breviar ​13 =====+===== Laboratorul ​13 – Fluxuri I/O. Funcționale ​=====
  
-==== 1Fluxuri (Streams) ====+{{:​poo:​laboratoare:​arhiva_13.zip|Arhiva laborator}}
  
-=== 1.1 Introducere ​===+=== Problema ​1 ===
  
-Dennis Ritchie implementează în 1984 primul sistem I/O pe bază de stream în cadrul +Să se scrie un program pentru afișarea ​pe ecran a liniilor aflate pe poziții impare 
-sistemului de operare UnixAcest concept are la bază crearea unui canal de comunicație +dintr-un fișier textFiecare linie va fi precedată de numărul ei și un spațiu.
-între două entități: **sursă** și **destinație**. Sursa scrie informații în canalul de +
-comunicație,​ iar destinația poate să citească aceste date, canalul permițând trecerea +
-fluxului de date într-o singură direcție.+
  
-**Clasificarea fluxurilor:**+În implementare,​ se va folosi un obiect de tip **LineNumberReader**.
  
-După direcția canalului de comunicație+Cerințe
-  * fluxuri de intrare (pentru citirea datelor) +  * Tratați toate excepțiile care ar putea să apară exact acolo unde apar! 
-  * fluxuri de ieșire (pentru scrierea datelor)+  * Atenție la închiderea fișierelor – să se facă chiar dacă apare excepție la citire!
  
-După tipul de date pe care le operează:​ +Pentru validarea acestei cerințe, puteți folosi fișierul text //​test01.in//​ pus la 
-  * fluxuri de octeți (transfer serial pe 8 biți) +dispoziție în arhiva laboratorului.
-  * fluxuri de caractere (transfer serial pe 16 biți)+
  
-După acțiunea lor: +=== Problema 2 ===
-  * fluxuri primare de citire/​scriere a datelor +
-  * fluxuri pentru procesarea datelor+
  
-Datorită faptului că există două direcții ​de comunicare, există două tipuri mari de +Să se scrie un program care citește un text de la tastatură și îl salvează într-un 
-stream-uri pentru orice nod de comunicație:​ **input stream** ​ș**output stream**+fișier pe disc. Citirea se va face până la introducerea cuvântului ​**exit**.
-Tastatura ar fi un exemplu de input stream, iar monitorul un output stream. +
-Sursa și destinația nu trebuie să fie neapărat periferice, ele pot fi și module soft.+
  
-=== 1.2 Fluxuri ​de octeți ===+În implementare se va utiliza metoda **readLine()** pentru un obiect ​de tip 
 +**DataInputStream** sau **BufferedReader**.
  
-Programele folosesc fluxuri de octeți pentru a citi sau scrie date pe 8 biți (un octet). +Tratați toate excepțiile care ar putea să apară!
-Fluxurile la nivel de octet utilizează două ierarhii având drept clase rădăcină:​ +
-**InputStream** și **OutputStream**.+
  
-Cele mai utilizate clase sunt **FileInputStream** și **FileOutputStream**.+=== Problema 3 ===
  
-<code java> +Să se implementeze un program care citește din fișierul //​test02.in//​ un text și 
-public class Copy { +determină numărul de cuvinte din text.
-    private String input, output;+
  
-    public Copy(String input, String output) { +Pentru citire ​se vor utiliza un obiect ​de tip **FileReader** și unul de tip **StreamTokenizer**.
-        this.input = input; +
-        this.output = output; +
-    } +
- +
-    public void copyFile() { +
-        InputStream in = null; +
-        OutputStream out = null; +
-        try { +
-            in = new FileInputStream(input);​ +
-            out = new FileOutputStream(output);​ +
-            while (in.available() > 0) +
-                out.write(in.read());​ +
-        } catch (FileNotFoundException e) { +
-            e.printStackTrace();​ +
-        } catch (IOException e) { +
-            e.printStackTrace();​ +
-        } finally { +
-            try { +
-                if (out != null) out.close();​ +
-                if (in != null) in.close();​ +
-            } catch (IOException e) { +
-                e.printStackTrace();​ +
-            } +
-        } +
-    } +
-+
-</​code>​ +
- +
-<note warning>​ +
-IMPORTANT! Fișierele text trebuie să se afle în folderul rădăcină al proiectului +
-care conține clasele care prelucrează informația din aceste fișiere. +
-</​note>​ +
- +
-=== 1.3 Fluxuri de caractere === +
- +
-Limbajul Java stochează valorile ​de tip caracter folosind convenții Unicode. +
-Fluxurile de caractere I/O își translatează automat formatul intern de la setul +
-de caractere locale. +
- +
-Toate clasele de fluxuri de caractere moștenesc clasele **Reader** și **Writer**. +
-Pentru operațiile I/O cu fișiere: ​**FileReader** și **FileWriter**.+
  
 <code java> <code java>
-public class Read { +FileReader ​in = new FileReader(new ​File("​test02.in")); 
-    private String input; +StreamTokenizer str new StreamTokenizer(in);
- +
-    public Read(String input) { +
-        this.input = input; +
-    } +
- +
-    public void read() { +
-        ​FileReader ​stream = null; +
-        BufferedReader br = null; +
-        try { +
-            stream ​= new FileReader(input); +
-            br = new BufferedReader(stream); +
-            String line = br.readLine()+
-            while (line != null) { +
-                System.out.println(line); +
-                ​line ​br.readLine(); +
-            } +
-        } catch (FileNotFoundException e) { +
-            e.printStackTrace();​ +
-        } catch (IOException e) { +
-            e.printStackTrace();​ +
-        } finally { +
-            try { +
-                if (stream != null) stream.close();​ +
-                if (br != null) br.close();​ +
-            } catch (IOException e) { +
-                e.printStackTrace();​ +
-            } +
-        } +
-    } +
-}+
 </​code>​ </​code>​
  
-<​note>​ +=== Problema 4 – Funcționale ===
-Observație: Obiectul BufferedReader creează un flux de intrare a caracterelor cu +
-stocare temporară (și posibilitate de citire a caracterelor sub formă de linii) +
-din fluxul de intrare a caracterelor primit ca parametru. +
-</​note>​+
  
-=== 1.4 Fluxuri ​cu zone tampon (Buffer) ===+Realizați o arhitectură unificată, similară ​cu Collections,​ pentru manipularea listelor 
 +care să conțină:
  
-Pentru un flux I/O fără zone tamponfiecare cerere de citire sau scriere este +  * Interfața **Function**,​ parametrizată corespunzătorcare conține o metodă **execute**,​ având ca parametru un obiect ​de tip **A** și un rezultat ​de tip **B**unde **A** și **B** sunt două tipuri formale;
-administrată direct ​de sistemul ​de operare. Aceasta face ca programul să fie mai +
-puțin eficientdeoarece fiecare cerere declanșează accesul la disc, activitate +
-în rețea sau alte operații care consumă timp.+
  
-Pentru ​reduce timpul ​de procesareplatforma Java implementează fluxuri I/O cu +  * Interfaț**Addition** folosită pentru a calcula suma a două numere ​de tip **T**unde **T** este un subtip al lui **Number** (aceasta va conține ​metodă **zero** care va întoarce elementul neutru al operației ​de adunare și o metodă **add**, care primește două obiecte ​de tip **T** și returnează suma lor);
-zone tampon: +
-  ​Fluxurile de intrare cu zone tampon citesc datele dintr-zonă de memorie cunoscută ca **buffer** +
-  * API-ul ​de intrare este apelat numai când tamponul este gol +
-  ​Similarfluxurile de ieșire scriu datele în zona de tampon ​și API-ul de ieșire este apelat când tamponul este plin+
  
-Un program poate converti un flux fără zonă tampon într-un flux cu zonă tampon +  ​Doi algoritmi polimorfici: **reverse** care inversează elementele unei liste și **sum** care calculează suma elementelor din listă; acești algoritmi trebuie să poată fi folosiți pe implementări diferite de listedeoarece le abordează la nivel de interfață;
-astfel: un obiect de tip flux fără zonă tampon este trecut ca argument unui +
-constructor pentru o clasă de tip flux cu zonă tampon. +
- +
-=== 1.5 Fluxuri standard === +
- +
-Limbajul Java pune la dispoziția utilizatorului trei fluxuri standard pentru +
-comunicare cu consola: +
- +
-**Flux** | **Descriere** | **Referință** | +
-| Standard Input | pentru citirea datelor | System.in (InputStream) | +
-| Standard Output | pentru afișarea datelor | System.out (PrintWriter) | +
-| Standard Error | pentru afișarea erorilor | System.err (PrintWriter) | +
- +
-<​note>​ +
-ObservațieNu este necesară instanțierea acestor trei stream-uri, deoarece ele +
-se deschid automat înaintea execuției aplicației. De asemenea, acestea nici nu +
-se închid prin apelul metodei close(). +
-</​note>​ +
- +
-**Exemplu cu InputStreamReader și BufferedReader:​** +
- +
-<code java> +
-public class Suma { +
-    int a, b; +
- +
-    public void read() { +
-        InputStreamReader stream = null; +
-        BufferedReader br = null; +
-        try { +
-            stream = new InputStreamReader(System.in);​ +
-            br = new BufferedReader(stream);​ +
-            String line = br.readLine();​ +
-            a = Integer.parseInt(line);​ +
-            line = br.readLine();​ +
-            b = Integer.parseInt(line);​ +
-        } catch (IOException e) { +
-            e.printStackTrace();​ +
-        } finally { +
-            try { +
-                if (stream != null) stream.close();​ +
-                if (br != null) br.close();​ +
-            } catch (IOException e) { +
-                e.printStackTrace();​ +
-            } +
-        } +
-    } +
-+
-</​code>​ +
- +
-**Exemplu cu Scanner:​** +
- +
-<code java> +
-public class Test { +
-    public static void main(String args[]) throws Exception { +
-        Scanner in = new Scanner(System.in);​ +
-        int a, b; +
-        a = in.nextInt();​ +
-        b = in.nextInt();​ +
-        int result = a + b; +
-        System.out.println(a + " + " + b + " = " + result); +
-        in.close();​ +
-    } +
-+
-</​code>​ +
- +
-==== 2. Funcționale ==== +
- +
-=== 2.1 Introducere === +
- +
-În paradigma funcțională,​ funcțiile sunt valori de ordinul 1 ce pot fi manipulate +
-ca orice altă valoare. **Funcționalele** sunt funcții ​care manipulează alte funcții, +
-primindu-le ca argumente sau returnându-le ca rezultat. +
- +
-=== 2.2 Lista funcționalelor === +
- +
-== foldl(function,​ init, list) == +
- +
-Returnează rezultatul aplicării funcției **function** pe rând asupra unui element +
-din listă și a unui acumulator ​**init**. Ordinea folosirii elementelor din listă +
-este de la **stânga la dreapta**. +
- +
-<​code>​ +
-foldl(f(x, y) = x + y, 5, [0, 1, 2, 3]) +
-= f(f(f(f(5, 0), 1), 2), 3) +
-= f(f(f(5, 1), 2), 3) +
-= f(f(6, 2), 3) +
-= f(8, 3) +
-= 11 +
-</​code>​ +
- +
-== foldr(function,​ init, list) == +
- +
-Are un comportament similar cu foldl, însă ordinea folosirii ​elementelor din listă +
-este de la **dreapta la stânga**. +
- +
-<​code>​ +
-foldr(f(x, y) = y, 4, [0, 1, 2, 3]) +
-= f(0, f(1, f(2, f(3, 4)))) +
-= f(0, f(1, f(2, 4))) +
-= f(0, f(1, 4)) +
-= f(0, 4) +
-= 0 +
-</​code>​ +
- +
-== map(function,​ list) == +
- +
-Returnează lista rezultatelor aplicării unei funcții **f** asupra fiecărui element +
-dintr-o listă. +
- +
-<​code>​ +
-map(f(x) = 2*x[0, 1, 2, 3]) => [0, 2, 4, 6] +
-</​code>​ +
- +
-== filter(predicat,​ list) == +
- +
-Returnează lista elementelor dintr-o listă care satisfac un predicat **p**. +
-Un predicat este o funcție care are un rezultat ​de tip Boolean. +
- +
-<​code>​ +
-filter(f(x) = x % 2 == 0, [0, 1, 2, 3]) => [0, 2] +
-</​code>​ +
- +
-== reduce(function,​ list) == +
- +
-Aplică funcția pentru primele două elemente din listă, apoi pentru rezultatul +
-obținut anterior și următorul element și tot așa. +
- +
-<​code>​ +
-reduce(f(x, y) = x + y, [47, 11, 42, 13]) +
-= f(f(f(47, 11), 42), 13) +
-= f(f(58, 42), 13) +
-= f(100, 13) +
-= 113 +
-</​code>​ +
- +
-== all(predicat,​ list) == +
- +
-Primește un predicat și verifică dacă **toate** elementele din listă satisfac predicatul. +
- +
-<​code>​ +
-all(f(x) = x > 0, [0, 1, 2, 3])   => False  (0 nu e > 0) +
-all(f(x) = x >= 0, [0, 1, 2, 3]) => True +
-</​code>​ +
- +
-== any(predicat,​ list) == +
- +
-Primește un predicat și verifică dacă există **cel puțin un element** în listă +
-care satisface predicatul. +
- +
-<​code>​ +
-any(f(x) = x < 0, [1, 2, 3, 4])   => False +
-any(f(x) = x % 2 == 0, [1, 2, 3]) => True   (2 e par) +
-</​code>​+
  
-=== 2.3 Rezumat ​funcționale ===+  * O serie de metode care au un comportament similar cu funcționalele din paradigma funcțională.
  
-| **Funcțională** **Descriere** | **Exemplu** | +Veți porni implementarea de la clasa **ListUtil**, pusă la dispoziție în arhiva laboratorului.
-| **foldl** | Agregare stânga→dreapta cu acumulator | foldl(+0, [1,2,3]) = 6 | +
-| **foldr** | Agregare dreapta→stânga cu acumulator | foldr(-, 0, [1,2,3]) = 2 | +
-| **map** | Transformă fiecare element | map(x→x*2,​ [1,2]) = [2,4] | +
-| **filter** | Păstrează elementele care satisfac predicatul | filter(par, [1,2,3]) = [2] | +
-| **reduce** | Agregare fără acumulator inițial | reduce(+, [1,2,3]) = 6 | +
-| **all** | Toate satisfac predicatul? | all(>0, [1,2]) = True | +
-| **any** | Există cel puțin unul care satisface? | any(<0, [1,2]) = False |+
  
poo/laboratoare/13.1768200139.txt.gz · Last modified: 2026/01/12 08:42 by george.tudor1906
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