Fizikus C++ labor

1. hét: make és C ismétlés2. hét: pontosság és pontatlanság3. hét: azonos nevű függvények, referencia
4. hét: egyszerű osztályok5. hét: konstruktor és operator overloading6. hét: osztály dinamikus adattaggal
9. hét: >> és << használata I/O-ra, statikus tagok10. hét / 1: STL vector10. hét / 2: STL string, algorithm
11. hét: generikus algoritmusok és osztályok12. hét: öröklés13. hét: heterogén kollekció
14. hét: C++11 kitekintő15. hét: Nagyházi bemutatás

7. hét: >> és << használata I/O-ra, statikus tagok

0. feladat

Sztring osztály.

Sztring osztály
#include <cstring>
#include <iostream>
class string {
char *t;
int n;
public:
string() :n(0) { t = new char[1]; t[0] = '\0'; }
~string() { delete[]t; }
string(const string &s) {
t = NULL;
*this = s;
}
const string &operator=(const string &s) {
if (this == &s)
return *this;
delete[]t;
t = new char[s.n + 1];
n = s.n;
strcpy(t, s.t);
return *this;
}
string(const char *s) {
n = strlen(s);
t = new char[n + 1];
strcpy(t, s);
}
string operator+(const char *s) {
string ret;
ret.n = n + strlen(s);
ret.t = new char[ret.n + 1];
strcpy(ret.t, t);
strcat(ret.t, s);
return ret;
}
string operator+(const string &b) {
return *this + b.t;
}
//friend std::ostream & operator<<(std::ostream & os, const string &s);
void print(std::ostream &os)const {
os << t;
}
};
string operator+(const char*s, const string &b) {
return string(s) + b;
}
//using namespace std;
std::ostream & operator<<(std::ostream & os, const string &s) {
s.print(os);
return os;
}

1. feladat

a) Egészítsük ki a két héttel ezel tt készült racionális szám osztályt beolvasást végzô >> és kiírást végzô << operátorokkal! A két függvény prototípusa:

istream & operator>>(istream &, Rac &);

ostream & operator<<(ostream &, const Rac &);

A beolvasás és a kiírás formátuma ugyanaz legyen, pl. sz/n.

b) Zárjuk az osztályt és a hozzá tartozó globális függvényeket a Q névtérbe.

c) A tesztelô olvasson be két számot, és írja ki az összegüket.

2. feladat

a) Egészítsük ki a múlt héten készült vektor osztályt beolvasást végzô >> és kiírást végzô << operátorokkal! A beolvasott értékeket Kelvinben kifejezett hômérsékletnek tekintjük, és a beolvasott számsorozat végét egy negatív érték jelzi. Kiírásnál a vektorban szereplô értékek szóközzel elválasztott számsorozatát egy negatív érték (pl. -1) kövesse.

b) Írjunk programot, amely beolvas egy vektort, kiírja azt, majd kiírja az átlag feletti értékeket.

c) Legyen egy smartPrint tagfüggvény, amely Kelvinben, Farenheitben vagy Celsiusban írja ki a tárolt hômérsékletet, a következôk szerint. Legyen egy statikus tagfüggvénnyel beállítható statikus tagváltozója is az osztálynak, amely a kiírásnál használt mértékegységet tartalmazza. Ne feledkezz meg a tagváltozó inicializálásáról!

Gyakorló feladatok

1.

a) Egészítsük ki a komplex szám osztályt beolvasást végzô >> és kiírást végzô << operátorokkal! Zárjuk az egészet a Komplex névtérbe!

b) Legyen egy statikus tagváltozója az osztálynak, mely azt befolyásolja, hogy a kiíró i-t vagy j-t (ahogy a villamosmérnökök) használjon a képzetes egység jelölésére. (érdekes, rövid cikk: http://www.johndcook.com/blog/2013/04/23/why-j-for-imaginary-unit/).

2 (nehéz feladat)

Alakítsd át a vektor osztályt úgy, hogy bár a tárolt értékek mindig Kelvinben legyenek, az [] operátor segítségével Kelvinben, Farenheitben vagy Celsiusban adhassunk értéket ill olvashassunk ki értéket a vektor valamely eleméb l, a statikus változónak megfelelôen.

Mintamegoldások:

1. órai feladat
#include <cstdio>
#include <stdexcept>
#include <iostream>

namespace Q{

    class Rac{
        int sz, n;
        int lnko(int a, int b)const;
        void egyszerusit();
    public:
        Rac(int sz = 0, int n = 1){
            this->sz = sz; this->n = n;
            if (n == 0)
                throw std::domain_error("Rac::Rac: 0 a nevezoben");
            egyszerusit();
        }

        Rac(double szam, int tizedes){
            bool neg = false;
            if (szam < 0)
                szam = -szam, neg = true;
            if (tizedes < 0)
                throw std::domain_error("Rac::Rac: tizedes jegyek szama<0");
            n = 1;
            for (; tizedes > 0; tizedes--)
                n *= 10;
            sz = (int)(szam*n + 0.5);
            sz = neg ? -sz : sz;
            egyszerusit();
        }

        void print()const{
            printf("(%d/%d)\n", sz, n);
        }

        Rac operator+(const Rac &b)const;

        const Rac& operator+=(const Rac&);

        Rac operator/(const Rac& b);

        bool operator==(const Rac& b){ return sz == b.sz && n == b.n; }
        bool operator!=(const Rac&b){ return !(*this == b); }

        operator double()const{ return (double)sz / n; }

        void set(int sz, int n = 1){
            this->sz = sz, this->n = n;
            if (n == 0)
                throw std::domain_error("Rac::set: 0 a nevezoben");
            egyszerusit();
        }
        int getSz()const{ return sz; }
        int getN()const{ return n; }
    };

    int Rac::lnko(int a, int b)const{
        a = a < 0 ? -a : a;
        b = b < 0 ? -b : b;
        while (b > 0){
            int temp = b;
            b = a % b;
            a = temp;
        }
        return a;
    }

    void Rac::egyszerusit(){
        int neg = sz < 0 ? -1 : 1;
        neg *= n < 0 ? -1 : 1;
        sz = sz < 0 ? -sz : sz;
        n = n < 0 ? -n : n;
        int oszto = lnko(sz, n);
        if (oszto != 0)
            sz /= oszto, n /= oszto;
        sz *= neg;
    }

    inline Rac Rac::operator+(const Rac &b)const{
        int oszto = lnko(n, b.n);
        return Rac(b.n / oszto*sz + n / oszto*b.sz, n / oszto*b.n); // konstruktor: egyszer s t is
    }

    inline const Rac& Rac::operator+=(const Rac& b){
        *this = *this + b; //op+ majd egyszer s t
        return *this;
    }

    inline Rac Rac::operator/(const Rac& b){
        if (b.sz == 0)
            throw std::domain_error("Rac::operator/: osztas 0-val");
        int oszto1 = lnko(sz, b.sz);
        int oszto2 = lnko(n, b.n);
        return Rac((sz / oszto1)*(b.n / oszto2), (n / oszto2)*(b.sz / oszto1));
    }

    std::istream &operator>>(std::istream &is, Rac &r){
        int sz, n;
        is >> sz;
        is.get();
        is >> n;
        r.set(sz, n);
        return is;
    }

    std::ostream &operator<<(std::ostream &os, const Rac &r){
        os << r.getSz() << '/' << r.getN();
        return os;
    }

}

int main(){
    Q::Rac r1,r2;
    std::cin >> r1 >> r2;
    std::cout << r1 + r2 << std::endl;
    return 0;
}

 

2. órai feladat
#include <iostream>
#include <stdexcept>

class vektor{
public:
    enum temp_type{ Kelvin, Celsius, Farenheit };
private:
    double *t;
    int n;
    static temp_type temp;
public:
    vektor() :t(NULL), n(0){}
    ~vektor(){ delete[]t; }
    vektor(const vektor &masik);
    const vektor &operator=(const vektor &masik);
    double &operator[](int i){
        if (i < 0 || i >= n)throw std::out_of_range("vektor::operator[]: out of tange");
        return t[i];
    }
    const double &operator[](int i)const{
        if (i < 0 || i >= n)throw std::out_of_range("vektor::operator[]: out of tange");
        return t[i];
    }
    void push_back(double);
    int getSize()const{ return n; }
    void reset(){ delete[]t; t = NULL; n = 0; }
    static void setTempType(temp_type uj){ temp = uj; }
    void smartPrint(){
        for (int i = 0; i < n;i++)
            switch (temp){
            case Kelvin: std::cout << t[i] << ' '; break;
            case Celsius: std::cout << t[i] - 273.15 << ' '; break;
            case Farenheit: std::cout << (t[i] - 273.15)*1.8 + 32 << ' '; break;
            default: throw std::invalid_argument("vektor::smartPrint: invalid tempereature type");
        }
        std::cout << std::endl;
    }
};

vektor::temp_type vektor::temp = vektor::Kelvin;

vektor::vektor(const vektor &masik) :n(masik.n){
    t = new double[n];
    for (int i = 0; i < n; i++)
        t[i] = masik.t[i];
}

const vektor &vektor::operator=(const vektor & masik){
    if (this == &masik)
        return *this;
    delete[]t;
    n = masik.n;
    t = new double[n];
    for (int i = 0; i < n; i++)
        t[i] = masik.t[i];
    return *this;
}

void vektor::push_back(double uj){
    double *p = new double[n + 1];
    for (int i = 0; i < n; i++)
        p[i] = t[i];
    p[n] = uj;
    n++;
    delete[]t;
    t = p;
}

vektor first(const vektor &v, int n){
    vektor uj;
    for (int i = 0; i < n; i++)
        uj.push_back(v[i]);
    return uj;
}


std::istream &operator>>(std::istream &is, vektor &v){
    v.reset();
    double d;
    while ((is >> d) && d >= 0)
        v.push_back(d);
    return is;
}

std::ostream &operator<<(std::ostream &os, const vektor &v){
    for (int i = 0; i < v.getSize(); i++){
        os << v[i] << ' ';
    }
    os << -1;
    return os;
}

double vek_average(const vektor &v){
    double sum = 0;
    for(int i = 0; i < v.getSize(); i++)
        sum += v[i];
    return v.getSize()>0 ? sum / v.getSize() : 0;
}

vektor above_average(const vektor &v){
    vektor ret;
    double aver = vek_average(v);
    for (int i = 0; i < v.getSize(); i++)
        if (v[i]>aver)
            ret.push_back(v[i]);
    return ret;
}

void print_above_average(const vektor &v){
    double aver = vek_average(v);
    for (int i = 0; i < v.getSize(); i++)
        if (v[i]>aver)
            std::cout << v[i] << ' ';
    std::cout << std::endl;
}

int main(){
    vektor v;
    std::cin >> v;
    std::cout << v << std::endl;
    vektor v2 = above_average(v);
    std::cout << v2 << std::endl; //  gy persze odateszi a -1-et is a v g re
    print_above_average(v); //  gy meg nem.
    v.smartPrint();
    v.setTempType(vektor::Celsius);
    v.smartPrint();
    v.setTempType(vektor::Farenheit);
    v.smartPrint();
    return 0;
}

 

2. gyakorló feladat
#include <iostream>
#include <stdexcept>

class vektor{
public:
    enum temp_type{ Kelvin, Celsius, Farenheit };
private:
    class konverter{
        double *p;
        temp_type tip;
    public:
        konverter(double *p,temp_type t) :p(p),tip(t){}
        const konverter &operator=(double T){
            switch (tip){
                case Kelvin:    *p = T; break;
                case Celsius:   *p = T + 273.15; break;
                case Farenheit: *p = (T - 32) / 1.8 + 273.15; break;
                default: throw std::invalid_argument("konverter::operator=: invalid tempereature type");
            }
            return *this;
        }
        operator double()const{
            switch (tip){
                case Kelvin:    return *p; break;
                case Celsius:   return *p - 273.15; break;
                case Farenheit: return (*p - 273.15)*1.8 + 32; break;
                default: throw std::invalid_argument("konverter::operator double: invalid tempereature type");
            }
        }
    };
    double *t;
    int n;
    static temp_type temp;
public:
    vektor() :t(NULL), n(0){}
    ~vektor(){ delete[]t; }
    vektor(const vektor &masik);
    const vektor &operator=(const vektor &masik);
    konverter operator[](int i){
        if (i < 0 || i >= n)throw std::out_of_range("vektor::operator[]: out of tange");
        return konverter(&t[i],temp);
    }
    konverter operator[](int i)const{
        if (i < 0 || i >= n)throw std::out_of_range("vektor::operator[]: out of tange");
        return konverter(&t[i], temp);
    }
    void push_back(double);
    int getSize()const{ return n; }
    void reset(){ delete[]t; t = NULL; n = 0; }
    void setTempType(temp_type uj){ temp = uj; }
    void smartPrint(){
        for (int i = 0; i < n;i++)
            switch (temp){
                case Kelvin: std::cout << t[i] << ' '; break;
                case Celsius: std::cout << t[i] - 273.15 << ' '; break;
                case Farenheit: std::cout << (t[i] - 273.15)*1.8 + 32 << ' '; break;
                default: throw std::invalid_argument("vektor::smartPrint: invalid tempereature type");
        }
        std::cout << std::endl;
    }
};

vektor::temp_type vektor::temp = vektor::Kelvin;

vektor::vektor(const vektor &masik) :n(masik.n){
    t = new double[n];
    for (int i = 0; i < n; i++)
        t[i] = masik.t[i];
}

const vektor &vektor::operator=(const vektor & masik){
    if (this == &masik)
        return *this;
    delete[]t;
    n = masik.n;
    t = new double[n];
    for (int i = 0; i < n; i++)
        t[i] = masik.t[i];
    return *this;
}

void vektor::push_back(double uj){
    double *p = new double[n + 1];
    for (int i = 0; i < n; i++)
        p[i] = t[i];
    p[n] = uj;
    n++;
    delete[]t;
    t = p;
}

int main(){
    vektor v;
    v.push_back(300);
    v.push_back(0);
    std::cout << v[0] << ", " << v[1] << std::endl;
    vektor::setTempType(vektor::Celsius); // v.setTempType(vektor::Celsius);
    std::cout << v[0] << ", " << v[1] << std::endl;
    v[1] = 0;
    std::cout << v[0] << ", " << v[1] << std::endl;
    v.setTempType(vektor::Farenheit);
    std::cout << v[0] << ", " << v[1] << std::endl;
    v[0] = 0;
    std::cout << v[0] << ", " << v[1] << std::endl;
    vektor::setTempType(vektor::Kelvin);
    std::cout << v[0] << ", " << v[1] << std::endl;
    return 0;
}