C++ zadanie z wykorzystaniem klas i dziedziczeniem

0

Witam,
Dostałem dosyć skomplikowane (jak dla mnie) zadanie w wykorzystaniem klas. Dopiero zaczynam się uczyć obiektowo, więc prosiłbym o wyrozumiałość. Może na początku przedstawię to co chcę zrobić:

Program powinien składać się z co najmniej czterech klas:
1 klasy figura posiadającej parametry wierzchołki,
2 klasy trójkąt posiadającej trzy wierzchołki (definiowane poprzez trzy parametry – punkty – w konstruktorze),
3 klasy czworokąt posiadającej cztery wierzchołki (definiowane jak powyżej),
4 klasy kwadrat posiadającej cztery wierzchołki (definiowane jak powyżej, ze sprawdzeniem, czy jest to kwadrat).
Klasy trójkąt, czworokąt i kwadrat mają dziedziczyć po klasie figura. Klasa figura ma udostępniać metody:

  • wyświetlającej wszystkie wierzchołki figury,
  • liczącej pole figury,
  • liczącej obwód figury.
    Przykładowy scenariusz użycia:
  1. Uruchomienie programu
  2. Wprowadzenie liczy i typu figur: ‘tts’ (trójkąt, trójkąt, czworokąt)
  3. Wprowadzenie trzech punktów (2,2) (3,3) (1,1) – wierzchołków pierwszego trójkąta
  4. Wprowadzenie trzech punktów (5,0) (0,0) (2.5,2.5) – wierzchołków drugiego trójkąta
  5. Wprowadzenie czterech punktów (0,0) (2,0) (2,2) (0,2) – wierzchołków kwadratu
  6. Wywołanie obliczenia wszystkich pól trzech figur

Nie mam pomysłu jak prawidłowo zaalokować pamięć do poszczególnych współrzędnych i potem je bez problemu odczytywać.

Jak do tej pory zrobiłem tyle:

#include <cstdlib>
#include <iostream>

using namespace std;


class Figura
      {
            public:
                   void figura();
      };
            
class Trojkat : public Figura
      {
              private:
                      double * wierzcholekT;
              public:
                     Trojkat();
              
      };

Trojkat::Trojkat()
{
     wierzcholekT =  new double[6];
}
 
int main()
{
    int dl;
    char napis[100] = {'\0'};
    cout << "Podaj kombinacje figur (t- trojkat, c- czworokat, k- kwadrat): \n";
    cin >> napis;
    dl = strlen(napis);
   
    Figura * ZadanieTrzecie;
    ZadanieTrzecie = new Figura[dl];
    for(int i=0; i <= dl; i++)
    {
             switch (napis[i])
             {
                    case 't':
                         double A[2], B[2], C[2];
                         ZadanieTrzecie[i] = new Trojkat();
                         break;
                         // tutaj oczywiscie reszta sprawdzania
             }
    }
}
0

Klasa Figura powinna mieć:
Kontener na wierzchołki,np taki

std::vector<std::pair<double,double> > wierzcholki;

Zdeklarowane jako czysto wirtualne funkcje liczPole,liczObwod
Zdefiniowaną funkcję pokazWierzcholki(),która to będzie wyciągała pary X,Y z kontenera wierzcholki i wypisywała je

0

Co mam rozumiec pod słowem kontener? parametry klasy?
vector rozumiem, ze to komenda, w jakiej ona bibliotece sie znajduje? i czemu akurat tak to zdefiniowałeś? (kompilator mi tego nie przełyka).
Ostatnie pytanie czym jest tez to 'pair' ?

1

I co mamy ci w takiej sytuacji powiedzieć? STL to najbardziej podstawowa rzecz, którą powinieneś mieć opanowaną zaraz po poznaniu składni języka.

Powiem tak: obrażasz nas próbując tracić nasz czas na coś, co możesz znaleźć w pierwszych rozdziałach absolutnie każdej książki i podręcznika traktującego o C++.

0

Naszukałem i naczytałem się dużo w internecie o klasach/dziedziczeniu zanim tutaj napisałem. Przeczytałem co to STL i pierwszy raz dopiero o takim czymś słyszę. Nikogo nie miałem zamiaru obrazić. Przedstawiłem swój problem, możesz pomóc bądź nie, myślę, że to sprawa indywidualna. Dla jednego to banalne rzeczy a np. dla mnie jeszcze skomplikowane.

0

Skomplikowane jest dlatego, że nie poświęciłeś nawet chwili na zrozumienie jej. Użytkownicy forum nie są twoimi prywatnymi nauczycielami, forum nie jest kursem nauki programowania ani podręcznikiem. Forum służy rozwiązywaniu problemów i dostałeś idealną odpowiedź od MasterBLB. To jest już tylko i wyłącznie twój problem, że jak ostatni sęp nie podziękowałeś i nie poszedłeś analizować odpowiedzi. Z PODRĘCZNIKIEM W RĘKU.

Tym, którzy dalej będą mi próbowali wmówić, że po to jest forum, pozwólcie, że przytoczę regulamin:

  • Poszukaj w pomocy/podręczniku, czy odpowiedź na Twoje pytanie nie znajduje się właśnie tam.
  • Lenistwo nie jest tolerowane.
1

Troche odbiega od wymogow, ale nie bede robil wszystkiego. Wystarczy do figury wrzucic vector<punkt> (jesli nie wiesz jak korzystac z pair) i pozmieniac pare funkcji. Dodaj sobie reszte rzeczy szablon tu jest. Jesli mowisz ze czytales i rozumiesz to, to powinienes dac rade.

#include <iostream>
#include <vector>

using namespace std;

struct punkt
{
    int x;
    int y;
};

ostream &operator<<(ostream &os, punkt p)
{
    os << p.x << " " << p.y << endl;
    return os;
}

class Figura
{
public:
    Figura(){}
    virtual int pole()=0;
    virtual int obwod()=0;
    virtual void wierzcholki()=0;
};

class Trojkat: public Figura
{
private:
    punkt a;
    punkt b;
    punkt c;
public:
    Trojkat(punkt a, punkt b, punkt c);
    int pole(){}
    int obwod(){}
    void wierzcholki(){cout << "Trojkat\n" << a << b << c;}
};

Trojkat::Trojkat(punkt a,punkt b, punkt c) : Figura()
{
    this->a=a;
    this->b=b;
    this->c=c;
}

class Kwadrat: public Figura
{
private:
    punkt a;
    punkt b;
    punkt c;
    punkt d;
    bool CzyKwadrat;
public:
    Kwadrat(punkt a, punkt b, punkt c, punkt d);
    int pole(){}
    int obwod(){}
    void wierzcholki(){cout << "Kwadrat\n" << a << b << c << d;}
};

Kwadrat::Kwadrat(punkt a, punkt b, punkt c, punkt d) : Figura()
{
    this->a=a;
    this->b=b;
    this->c=c;
    this->d=d;
}


int main()
{
    vector<Figura*>figury;
    int ile;
    cin >> ile;
    char wybor;
    while(ile--){
        cin >> wybor;
        switch(wybor)
        {
        case 't':
            figury.push_back(new Trojkat({1,2},{1,3},{1,4})); //inicjalizacja punktami dozwolona w standardzie c++0x
            break;
        case 'k':
            figury.push_back(new Kwadrat({1,2},{1,3},{1,4},{1,5}));
            break;
        }
    }
    for(int i=0;i<figury.size();i++)
    {
        figury[i]->wierzcholki();
    }
    cout << endl;
    return 0;
}
0

Kolega MasterBLB dobrze Ci podpowiedział. Zadeklaruj sobie składnik klasy typu std::vector<std::pair<double,double> > wierzcholki
Dzięki temu nie będziesz się musiał martwić o alokację pamięci dla tablicy. Dodanie wierzchołka o wspolrzednych 100, 100 bedzie sie odbywało mniej więcej tak (pisze z pamieci wiec nie gwarantuje ze bedzie dzialalo):

pair<double,double> my_vertex = new pair<100, 100>(); //utworzenie nowego obiektu wierzchołka o wspolrzednych 100, 100
wierzcholki.push_back(my_vertex); //dodanie wierzchołka do kontenera "wiercholki"

Pamiętaj potem o usuwaniu z pamięci obiektów wierzchołków które utworzyłeś poprzez "new"

pzdr
squash

0
Squash napisał(a)

Dzięki temu nie będziesz się musiał martwić o alokację pamięci dla tablicy. Dodanie wierzchołka o wspolrzednych 100, 100 bedzie sie odbywało mniej więcej tak (pisze z pamieci wiec nie gwarantuje ze bedzie dzialalo):

pair<double,double> my_vertex = new pair<100, 100>(); //utworzenie nowego obiektu wierzchołka o wspolrzednych 100, 100
wierzcholki.push_back(my_vertex); //dodanie wierzchołka do kontenera "wiercholki"

No Bracie,niezupełnie tak jak piszesz :]

wierzcholki.push_back(std::make_pair<double,double>(1.0,2.0));
0

dodaj jeszcze (jak już wspomniałem na innym forum) destruktor wirtualny.

0

Dokończyłem to zadanie, dziękuję za podpowiedzi i pomoc. Program znajduje się w załączniku jakby ktoś kiedyś potrzebował lub miał podobne zadanie.

Teraz zacząłem się męczyć z kolejnym zadaniem:

Działania powinny być wprowadzane przy pomocy jednej zmiennej, która przekazana do odpowiedniej metody klasy Calculator odczyta typ działania, liczby. Liczby zespolone powinny być wprowadzane w postaci ‘część_rzeczywista ± iczęść_urojona’. Część urojona liczby powinna być oznaczona symbolem ‘i’ lub ‘j’. Wprowadzone parametry powinny być zapisywane w klasie Calculator w formie tablicy obiektów klasy Parametr, posiadającej dwa atrybuty – wartość oraz symbol. Wczytanie nowego/nadpisanie starego parametru powinno odbywać się poprzez wprowadzenie działania ‘symbol_parametru = wartość’.
Przykładowy scenariusz użycia:

  1. Uruchomienie programu
  2. Wprowadzenie równania ‘a=5’
  3. Wprowadzenie równania ‘b=-3+ia + 5+i10’
  4. Wprowadzenie równania ‘a-b’
  5. Wyświetlenie wyniku ‘-3+i15’
  6. Wprowadzenie równania ‘a’
  7. Wyświetlenie wyniku ‘5’
  8. Powrót do oczekiwania na wpisanie kolejnego równania

Zacząłem tak:

#include <cstdlib>
#include <iostream>
#include <string.h>
#include <vector>

using namespace std;

class Parametr   // struktura do zapamietywania rownan np. a=2
{
    private:
    char * symbol;
    double wartosc;

    public:
    Parametr(char * symbol, char * wartosc);
};

Parametr::Parametr(char * symbol, char * wartosc)
{
    this->symbol=symbol;
    this->wartosc=(double)(*wartosc);

    cout << symbol << endl << wartosc << endl;
}

class Calculator
{
        private:
        char * rownanie;

        public:
        Calculator(char * rownanie);
};

Calculator::Calculator(char * rownanie)
{
    this->rownanie=rownanie;
    cout << rownanie; // do testow
}

//////////////////////////////////////////////////////////////////////
char * UtworzWartosc(int i, char * rownanie)
{
    char * zmienna;

    zmienna = new char(strlen(rownanie)-i);
    for(int k=i+1; k < strlen(rownanie); k++)
        zmienna[k] = rownanie[k];

    return zmienna;
}

char * UtworzPomoc(int i, char * rownanie)
{
                char * pomoc;
                pomoc = new char(i);
                for(int k=0; k < i; k++)
                pomoc[k] = rownanie[k];

                return pomoc;
}

void SkrocRownanie(int i, char * rownanie)
{

    for(int m=0; m < strlen(rownanie)-i; m++)
            rownanie[m] = rownanie[i+m];
}



int main()
{
    vector <Calculator*> dodawaj;
    vector <Calculator*> odejmuj;
    vector <Parametr*> parametry;

    char rownanie[100];

    cout << "Podaj przykladowe rownanie.\n";
    cin >> rownanie;

    int dlugosc = strlen(rownanie);

    for(int i=0; i < dlugosc; i++)
    {
        switch (rownanie[i])
        {
            case '=':
            parametry.push_back(new Parametr(UtworzPomoc(i, rownanie),UtworzWartosc(i, rownanie)));
            case '+':
            dodawaj.push_back(new Calculator(UtworzPomoc(i, rownanie)));
            SkrocRownanie(i, rownanie);
            break;

            case '-':
            odejmuj.push_back(new Calculator(UtwurzPomoc(i, rownanie)));
            SkrocRownanie(i, rownanie);
            break;

            default:
            break;
        }
        dlugosc = strlen(rownanie);
    }

    system("PAUSE");

    //liczba = ((double)(*rownanie));  //konwertowanie liczb z char do double

}
 

Co o tym sądzicie? Może macie inny pomysł jak się za to zabrać?

0
char * UtwurzWartosc(int i, char * rownanie)

Na miejscu sprawdzającego w tym momencie zacząłbym nieprzychylnie myśleć o kodzie i na siłę szukałbym błędów, na których mógłbym uwalić punkty - oficjalnie za niepoprawny kod, faktycznie za brak poszanowania dla języka polskiego.

A poza tym, to poczytaj sobie teraz o <string> w C++, skoro już zaprzyjaźniasz się z STL'em.

0

Ok, trochę poczytałem o stringach o operacjach, które można na nich wykonywać i uzyskałem taki kod:

#include <cstdlib>
#include <iostream>
#include <string.h>
#include <sstream>
#include <vector>

using namespace std;

class Parametr  // klasa do zapamietywania rownan np. a=2
{
    public:
    string symbol;
    int wartosc;
    Parametr(string symbol, int wartosc);
};

Parametr::Parametr(string symbol, int wartosc)
{
    this->symbol=symbol;
    this->wartosc=wartosc;
}

///////////////////////////////////////////////////////////////////////

class Zliczaj                   // klasa do zapamietywania czesciowych wynikow
{
    public:
    char znak;
    int wartosc;
    Zliczaj(int wartosc, char znak);
};

Zliczaj::Zliczaj(int wartosc, char znak)
{
    this->wartosc=wartosc;
    this->znak=znak;
}

////////////////////////////////////////////////////////////////////////

class Calculator                    //glowna klasa kalkulatora
{
        private:
        string rownanie;
        string symbol, str;
        int wartosc;
        int wynik;
        vector <Parametr*> zmienne;
        vector <Zliczaj*> zlicz;

        public:
        Calculator(){}
        int StrToInt(string str);
        int SprawdzRownanie(string rownanie);
        int SprawdzReszte(string rownanie);
        int UzyskajWynik();
        int SprawdzBaze(string pomoc);
        void Zapisz(string symbol, int wynik);
        void Wyswietlanie();
};

///////////KONWERSJA STRINGA W L.C.///////////////////////////

int Calculator::StrToInt(string str)
{
    stringstream zamien;
    int temp;

    zamien << str;
    zamien >> temp;

    return temp;
}

/////////////ZAPISANIE/NADPISANIE ROWNANIA DO BAZY////////////////////

void Calculator::Zapisz(string symbol, int wynik)
{
    int n=0;
    for(int i=0; i < zmienne.size(); i++)
    {
        if(zmienne[i]->symbol == symbol)
        {
            zmienne[i]->wartosc = wynik;
            n=1;
            break;
        }
    }
    if(n==0)
    zmienne.push_back(new Parametr(symbol, wynik));
}

////////////////ZLICZENIE DANYCH Z KONTENERA////////////////////

int Calculator::UzyskajWynik()
{
    wynik=zlicz[0]->wartosc;
    for(int i=1, j=0; i < zlicz.size(); i++, j++)
    {
        switch (zlicz[j]->znak)
        {
            case '+':
            wynik+=zlicz[i]->wartosc;
            break;

            case '-':
            wynik-=zlicz[i]->wartosc;
            break;

            case '*':
            wynik*=zlicz[i]->wartosc;
            break;

            case ';':
            vector<Zliczaj*>().swap(zlicz);
            return wynik;
        }
    }
}

/////////////////////////////SPRAWDZENIE ROWNANIA///////////////////////

int Calculator::SprawdzRownanie(string rownanie)
{
    int ro=0;

for(int i=0; i < rownanie.size(); i++)
{
    if(rownanie[i] == '=')
    ro = 1;
}

    if(ro == 1)
    {
    for(int i=0; i < rownanie.size(); i++)
    {
        switch (rownanie[i])
        {
            case '=':
            {
            for(int m=i+1; m < rownanie.size(); m++)
            {
                if(rownanie[m] == '=')
                {
                    cout << "Rownanie jest niepoprawne, zawiera zbyt wiele znakow rownosci.\n";
                    system("PAUSE");
                    return 0;
                }
            }
            for(int k=i+1; k < rownanie.size(); k++)
            {
                 if(rownanie[k] == '+' || rownanie[k] == '-' || rownanie[k] == '*' || rownanie[k] == '/')
                    {
                        ro=0;
                        break;
                    }
            }
                    if(ro==0)
                    {
                        symbol.assign(rownanie.begin(), rownanie.begin() + i);
                        str.assign(rownanie.begin()+i+1, rownanie.end() );
                        rownanie.clear();
                        rownanie = str;
                        wynik = SprawdzReszte(rownanie);
                            if(wynik == 0)
                                {
                                    return 0;
                                }
                            else
                            {
                                wartosc = UzyskajWynik();
                                Zapisz(symbol, wartosc);

                                cout << "Rownosc zostala dodana do bazy.\n";
                                cout << "Wynik rownania: " << wartosc;
                                system("PAUSE");
                                return 0;


                            }

                    }
                  else if(ro==1)
                    {
                        symbol.assign(rownanie.begin(), rownanie.begin() + i);
                        wartosc = StrToInt(str.assign(rownanie.begin()+i+1, rownanie.end() ) );
                        Zapisz(symbol, wartosc);
                        cout << "Rownosc zostala dodana do bazy.\n";
                        system("PAUSE");
                        return 0;
                    }
            break;
            }

            default:
            break;
        }
    }
    }
    else
    {
        for(int i=0; i < rownanie.size(); i++)
            {
                 if(rownanie[i] == '+' || rownanie[i] == '-' || rownanie[i] == '*' || rownanie[i] == '/')
                 {
                        wynik = SprawdzReszte(rownanie);
                            if(wynik == 0)
                                {
                                    return 0;
                                }
                            else
                            {
                                wartosc = UzyskajWynik();
                                cout << "Wynik rownania: " << wartosc << endl;
                                system("PAUSE");
                                return 0;
                            }
                 }
            }
    }
}

/////////////SPRAWDZANIE ROWNAN W BAZIE/////////////////////////////

int Calculator::SprawdzBaze(string pomoc)
{
    cout << pomoc << endl;
    for(int i=0; i < zmienne.size(); i++)
    {
        if(zmienne[i]->symbol == pomoc)
        {
            wartosc = zmienne[i]->wartosc;
            return wartosc;
        }
    }

    istringstream iss(pomoc);
    int liczba;


    if (iss >> liczba)
    {
        return wartosc = StrToInt(pomoc);
    }
    else
    {
        iss.clear();
        cout << "W rownaniu znajduja sie nieoznaczone symbole.\n";
        vector<Zliczaj*>().swap(zlicz);
        system("PAUSE");
        return 0;
    }
}

/////////////////DODAWANIE DO KONTENERA OBLICZEN CZASTKOWYCH////////////////////////

int Calculator::SprawdzReszte(string rownanie)
{
    string pomoc;
    pomoc.clear();

    for(int i=0; i < rownanie.size(); i++)
    {
        switch(rownanie[i])
        {
            case '+':
            {
                pomoc.assign(rownanie.begin(), rownanie.begin()+i );
                str.assign(rownanie.begin()+i+1, rownanie.end() );
                rownanie.clear();
                rownanie = str;
                wartosc = SprawdzBaze(pomoc);
                if(wartosc == 0)
                    {
                        return 0;
                    }
                else
                    {
                        zlicz.push_back(new Zliczaj(wartosc, '+' ));
                        SprawdzReszte(rownanie);
                    }
                break;
            }
            case '-':
            {
                pomoc.assign(rownanie.begin(), rownanie.begin()+i );
                str.assign(rownanie.begin()+i+1, rownanie.end() );
                rownanie.clear();
                rownanie = str;
                wartosc = SprawdzBaze(pomoc);
                if(wartosc == 0)
                    {
                        return 0;
                    }
                else
                    {
                        zlicz.push_back(new Zliczaj(wartosc, '-' ));
                        SprawdzReszte(rownanie);
                    }
                break;
            }
            case '*':
            {
                pomoc.assign(rownanie.begin(), rownanie.begin()+i );
                str.assign(rownanie.begin()+i+1, rownanie.end() );
                rownanie.clear();
                rownanie = str;
                wartosc = SprawdzBaze(pomoc);
                if(wartosc == 0)
                    {
                        return 0;
                    }
                else
                    {
                        zlicz.push_back(new Zliczaj(wartosc, '*' ));
                        SprawdzReszte(rownanie);
                    }
                break;
            }
            case ';':
            {
                pomoc.assign(rownanie.begin(), rownanie.end()-1);
                rownanie.clear();
                wartosc = SprawdzBaze(pomoc);
                if(wartosc == 0)
                {
                    return 0;
                }
                else if(wartosc != 0)
                {
                    zlicz.push_back(new Zliczaj(wartosc, ';' ));
                    return 1;
                }
                break;
            }
            default:
            break;
        }
    }
}

////////////////////WYSWIETLANIE////////////////////////

void Calculator::Wyswietlanie()
{
    if(zmienne.size() != 0)
    {
        for(int i=0; i < zmienne.size(); i++)
        {
            cout << "Parametr: " << zmienne[i]->symbol << "   ";
            cout << "Wartosc: " << zmienne[i]->wartosc << endl;
        }
    }
    else
        cout << "Brak danych.\n";
}

/////////////////////MAIN///////////////////////////////

int main()
{
    string rownanie;
    Calculator obiekt;

    cout << "UWAGA! Skomplikowane rownania musisz zakonczyc srednikiem (Np. 'a=5', 'a=5+a;' .\n";
    cout << "Jesli chcesz zakonczyc dzialanie programu wpisz 'STOP'.\n";
    cout << "Jesli chcesz zobaczyc wprowadzone parametry wpisz 'SHOW'.\n";

    cout << "Prosze podac rownanie:\n";
    cin >> rownanie;

    while(1)
    {
            if(rownanie.compare("STOP") == 0 || rownanie.compare("stop") == 0)
            {
                cout << "Program zakonczyl swoje dzialanie.\n";
                break;
            }
            else if(rownanie.compare("show") == 0 || rownanie.compare("SHOW") ==  0)
            {
                obiekt.Wyswietlanie();

                cout << endl << endl;
                cout << "Prosze podac kolejne rownanie.\n";
                cin >> rownanie;
            }
            else
            {
                cout << obiekt.SprawdzRownanie(rownanie) << endl;
                system("CLS");
                cout << "Prosze podac kolejne rownanie.\n";
                cin >> rownanie;
            }
    }

    system("CLS");
    cout << "Zapamietane rownania to:\n";
    obiekt.Wyswietlanie();
    system("PAUSE");
}
 

Mam jednak problem z wyświetlaniem, ponieważ zmienne w klasie Parametr są prywatne i nie wiem jak zrobić, żebym mógł je odczytać za pomocą klasy Calculator, jak już je tam zapiszę. Jak zmienię w klasie Parametr na 'public' to działa.

EDIT:
Napisałem więcej, sporo różnych założeń, natomiast dziwi mnie jedna rzecz. Przy przechwytywaniu rownania coś tam namotałem, natomiast kompilator nic nie krzyczy, a żeby było jeszcze ciekawiej, wynik jest poprawny.

EDIT:
Ok, program już napisałem, nieaktualne już. :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1