Differences

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

Link to this comparison view

sd-ca:articole:tutorial-02-1 [2016/02/28 20:27]
darius.neatu created
sd-ca:articole:tutorial-02-1 [2016/03/03 01:02] (current)
andrei.vasiliu2211 [Obiective]
Line 1: Line 1:
-TO DO+====== Tutorial 2.1 - Point2D ====== 
 + 
 +În acest tutorial, ne propunem să construim o structură de tip Point2D capabil să rețină coordonatele unui punct în plan și să permită anumite prelucrări pe un set de puncte. 
 + 
 +===== Obiective ===== 
 + 
 +Ne dorim: 
 +  * să construim class Point2D, cu doi membri de tip double astfel încât să poată memora cele două coordonate 
 +  * să adaugam lui class Point2D o metode de tip SETTER/​GETTER pentru a putea accesa/​modifica coordonatele unui punct 
 +  * să adaugam si alte functionalitati lui class Point2D, precum posibilitatea calculării distanței dintre două puncte 
 +  * să testam class Point2D printr-un cod simplu care arată cum creează elemente de tip Point2D și cum se calculează distanța dintre două puncte 
 +  * să exemplificăm conceptul de rule of three 
 +  * să găsim cele mai apropiate două puncte dintr-un set de puncte date 
 +  * să verificam cu Valgrind că nu sunt memory leaks. 
 + 
 +===== Dezvoltare ===== 
 + 
 +==== Varianta de bază a lui class Point2D ==== 
 + 
 +Vom considera ca variantă de bază un struct care conține două elemente de tip double. 
 + 
 +<code cpp> 
 +#ifndef __POINT2D__ 
 +#define __POINT2D__ 
 + 
 +struct Point2D { 
 + ​ double x, y; // coordonatele punctului 
 +}; 
 + 
 +#endif __POINT2D__ 
 +</​code>​ 
 + 
 +Această abordare are dezavantajul că variabilele x și y sunt publice, lucru care nu este dorit în general. O abordare elegantă este următoarea:​ 
 + 
 +<code cpp> 
 +#ifndef __POINT2D__ 
 +#define __POINT2D__ 
 + 
 +class Point2D { 
 + ​private:​ 
 + ​ double x, y; // coordonatele punctului 
 + 
 + ​public:​ 
 +  // Metoda setter pentru x 
 +  void setX(const double& x) { 
 + ​ this->​x = x; 
 +  } 
 + 
 +  // Metoda setter pentru y 
 +  void setY(const double& y) { 
 + ​ this->​y = y; 
 +  } 
 + 
 +  // Metoda getter pentru x 
 + ​ double getX() { 
 + ​ return x; 
 +  } 
 + 
 + // Metoda getter pentru y 
 + ​ double getY() { 
 + ​ return y; 
 +  } 
 + 
 +}; 
 + 
 +#endif // __POINT2D__ 
 +</​code>​ 
 + 
 +Observați folosirea referințelor și a cuvântului cheie const! 
 + 
 +==== Adaugarea de constructori ==== 
 + 
 +Pentru a putea inițializa un punct, mai exact coordonatele punctului, cu anumite valori, putem folosi un constructor. În această situație putem inițializa cu valori prestabilite la compile time (Default Constructor),​ valori cunoscute la runtime (un constructor cu parametri). 
 + 
 +<code cpp> 
 +        // Constructor default 
 + ​ Point2D() { 
 +  x = 0; 
 +  y = 0; 
 +  } 
 + 
 +  // Constructor cu parametri 
 + ​ Point2D(const double &x, const double &y) { 
 + ​ this->​x = x; 
 + ​ this->​y = y; 
 +  } 
 + 
 +  // Copy-constructor 
 + ​ Point2D(Point2D&​ p) { 
 + ​ this->​x = p.x; 
 +   
 +</​code>​ 
 + 
 +Metoda care implemenetează calculul distanței dintre două puncte este următoarea:​ 
 + 
 +<code cpp> 
 +  // Metoda care calculeaza distanta intre doua puncte in plan 
 + ​ double distance(const Point2D &p) { 
 + ​ return sqrt( (x - p.x) * (x - p.x) + (y - p.y) * (y - p.y) ); 
 +  } 
 +</​code>​ 
 + 
 +Atenție! Trebuie inclusă biblioteca cmath pentru a putea utiliza funcția sqrt! 
 +<code cpp> 
 +#ifndef __POINT2D__ 
 +#define __POINT2D__ 
 + 
 +#include <​cmath>​ 
 +.... 
 + 
 +</​code>​ 
 + 
 +Putem testa funcționalitățile implementate cu o sursă foarte scurtă. 
 + 
 +<code cpp> 
 +#include <​iostream>​ 
 +#include "​point2D.h"​ 
 + 
 +int main() { 
 + Point2D A, B; 
 + 
 + std::cin >> A >> B; 
 + 
 + std::cout << A.distance(B);​ 
 + 
 + return 0; 
 +
 +</​code>​ 
 + 
 +Pentru compilare și rulare in bash folosiți comanda 
 +<code cpp> 
 +g++ main.cpp -o main && ./main 
 +</​code>​ 
 + 
 + 
 +==== Adaugarea de alte elemente (e.g. functii de citire/​scriere) ==== 
 + 
 +Pentru a putea lucra cu ușurință cu elemente de tip Point2D, putem supraîncărca operatorii de citire/​afișare,​ atribuire, egalitate.  
 +De asemenea, întrucât am definit Copy-Constructir și operator de atribuire, se impune definirea unui destructor.  
 + 
 +<code cpp> 
 +#ifndef __POINT2D__ 
 +#define __POINT2D__ 
 + 
 +#include <​cmath>​ 
 + 
 +class Point2D { 
 +  
 +  ............ 
 + 
 + ​public:​ 
 +  // Destructor 
 + ​ ~Point2D() { 
 +  // Nu avem memorie de eliberat. 
 +  } 
 + 
 +  // Operator de atribuire 
 + ​ Point2D&​ operator=(const Point2D&​ p) { 
 + ​ this->​x = p.x; 
 + ​ this->​y = p.y; 
 + ​ return *this; // intoarce referinta pentru atribuiri inlantuite 
 +  } 
 + 
 + // Operator de egalitate 
 +  bool operator==(const Point2D&​ p) { 
 +  // Testez daca cele doua puncte au coordonate egale. 
 +  if (x == p.x && y == p.y) { 
 + ​ return true; 
 +  } 
 + 
 + ​ return false; 
 +  } 
 + 
 + ​ //​funcţii operator pentru supraîncărcarea operatorilor de intrare/​ieşire ​  
 +    //declarate ca funcţii de tip "​friend" ​   
 +    friend std::​ostream&​ operator<<​ (std::​ostream&​ out, const Point2D&​ p); 
 +    friend std::​istream&​ operator>>​ (std::​istream&​ is, Point2D&​ p); 
 +}; 
 + 
 + 
 +std::​ostream&​ operator<<​(std::​ostream&​ out, const Point2D&​ p){ 
 +   out << "​("​ << p.x << ","​ << p.y << "​)"<<​ std::​endl;​ 
 +   ​return out; 
 +
 +  
 +std::​istream&​ operator>>​(std::​istream&​ in, Point2D&​ p){ 
 +  in >> p.x>> p.y; 
 +  return in; 
 +
 + 
 +#endif // __POINT2D__ 
 +</​code>​ 
 + 
 +===== Testare si Evaluare ===== 
 + 
 +==== Program de test ==== 
 + 
 +În continuare vom face un program care prima dată citește un număr n si un element de tip Point2D, numit p, apoi încă n element de tip Point2D. Se cere să se găsească cel mai apropiat punct (din cele n) față de punctul de referință p. 
 + 
 +<code cpp> 
 +#include <​iostream>​ 
 +#include <​cmath>​ // pentru abs 
 +#include "​point2D.h"​ 
 + 
 +int main() { 
 + int n; // numarul de puncte 
 + Point2D p; // punctul de referinta 
 + Point2D *v; // vectorul de puncte dat de la tastatura 
 + 
 + //citire 
 + std::cout << "n = "; 
 + std::cin >> n;; 
 + 
 + std::cout << "p = "; 
 + std::cin >> p; 
 +  
 + v = new Point2D[n];​ 
 + for ( int i = 0; i < n; ++i ) { 
 + std::cout << "​v["​ << i << "​]=";​ 
 + std::cin >> v[i]; 
 +
 + 
 + double minDistance = (1<<​30);​ // initializez distanta minima cu ceva foarte mare 
 + int index = -1; // indicele celui mai apropiat punct 
 + 
 + for ( int i = 0; i < n; ++i) { 
 + double currentDistance = p.distance(v[i]);​ //distanta fata de punctul curent 
 + 
 + if ( currentDistance < minDistance ) { 
 + minDistance = currentDistance;​ 
 + index = i; 
 +
 +
 + 
 +        // afisare rezultat 
 + std::cout << "Cel mai apropiat punct este : " << index << " = " << v[index] << '​\n';​ 
 + 
 + //​eliberare memorie 
 + delete[] v; 
 + 
 + return 0; 
 +
 +</​code>​ 
 + 
 +Exemplu: 
 + 
 +<code bash> 
 +n = 5 
 +p = 0 0 
 +v[0]= 5 5 
 +v[1]=40 5 
 +v[2]= 5 -5  
 +v[3]= 4 3            
 +v[4]= 8 8 
 +Cel mai apropiat punct este : 3 = (4,3) 
 + 
 +</​code>​ 
 + 
 +==== Verificare cu Valgrind ==== 
 + 
 +Pentru acelasi test rulat cu <code bash> valgrind ./main </​code>​ toata memoria va fi eliberata. 
 + 
 +<code bash> 
 +==9360== Memcheck, a memory error detector 
 +==9360== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
 +==9360== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info 
 +==9360== Command: ./main 
 +..................... 
 +==9360==  
 +==9360== HEAP SUMMARY: 
 +==9360== ​    in use at exit: 0 bytes in 0 blocks 
 +==9360== ​  total heap usage: 13 allocs, 13 frees, 772 bytes allocated 
 +==9360==  
 +==9360== All heap blocks were freed -- no leaks are possible 
 +==9360==  
 +==9360== For counts of detected and suppressed errors, rerun with: -v 
 +==9360== ERROR SUMMARY: 0 errors from 0 contexts (suppressed:​ 0 from 0) 
 + 
 +</​code>​ 
 + 
 +==== Aprofundare ==== 
 +Încercați să extindeți class Point2D la class Point3D (punct în spațiu). Care sunt diferențele?​
sd-ca/articole/tutorial-02-1.1456684028.txt.gz · Last modified: 2016/02/28 20:27 by darius.neatu
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