Kalkulator obiektowy i prośba o ocenę.

0

Witam. Napisałem pierwszy program w C++ i chciałbym zapytać się czy jest w miarę ok, mam też kilka pytań, mianowicie do pętli while wczytującej dane do switcha, czy jest zrobiona poprawnie oraz do metod w klasie, jak odrzucać najlepiej błędne dane ( typu litery zamiast cyfer). W C używałem do tego zawsze pętli do while i wartości zwracanej ze scanfu, tutaj podobno stosuje się cin.getline i obiekt zwracany, ale widziałem kilka opcji i mam mały mętlik w głowie.
Jedno pytanie też dotyczy konstruktora, czy w ten sposób domyślny może być używany, bo Prata w swojej książce poleca robienie osobno domyślnego i osobno innego, nawet jeśli tylko jedna kategoria jest niedomyślna. Z góry dzięki za pomoc.
Zapodaję pliki, podzieliłem zgodnie z zaleceniami program na 3 części:
wynik_dzialania.h

#ifndef WYNIK_DZIALANIA_H_
#define WYNIK_DZIALANIA_H_

class Wynik_dzialania
{
    private:
        double first;
        double second;
        double result;

    public:
        Wynik_dzialania(double a = 1, double b = 1, double wynik = 1);
        ~Wynik_dzialania();
        void dodawanie();
        void odejmowanie();
        void mnozenie();
        void dzielenie();
};

#endif
 

wynik_dzialania.cpp

#include <iostream>
#include "wynik_dzialania.h"

Wynik_dzialania::Wynik_dzialania(double a, double b, double wynik)
{
    first = a;
    second = b;
    result = wynik;
}
Wynik_dzialania::~Wynik_dzialania()
{

}

void Wynik_dzialania::dodawanie()
{
    using namespace std;
    cout << "Wybrales dodawanie!"<<endl<<"Wprowadz prosze liczbe pierwsza:";
    cin >> first;
    cout << "Wprowadz prosze liczbe druga"<<endl;
    cin >> second;
    result = first + second;
    cout << "Wynik to:" << result << endl;

}
void Wynik_dzialania::odejmowanie()
{
    using namespace std;
    cout << "Wybrales odejmowanie!"<<endl<<"Wprowadz prosze liczbe pierwsza:";
    cin >> first;
    cout << "Wprowadz prosze liczbe druga"<<endl;
    cin >> second;
    result = first - second;
    cout << "Wynik to:" << result << endl;

}
void Wynik_dzialania::mnozenie()
{
    using namespace std;
    cout << "Wybrales mnozenie!"<<endl<<"Wprowadz prosze liczbe pierwsza:";
    cin >> first;
    cout << "Wprowadz prosze liczbe druga"<<endl;
    cin >> second;
    result = first * second;
    cout << "Wynik to:" << result << endl;

}
void Wynik_dzialania::dzielenie()
{
    using namespace std;
    cout << "Wybrales dzielenie!"<<endl<<"Wprowadz prosze liczbe pierwsza:";
    cin >> first;
    do
    {
        cout << "Wprowadz prosze liczbe druga rozna od zera"<<endl;
        cin >> second;
    }
    while(second==0);

    result = first / second;
    cout << "Wynik to:" << result << endl;

}

 

main.cpp

 #include <iostream>
#include <cstdlib>
#include "wynik_dzialania.h"

int main()
{
    using namespace std;

    char ch = '1'; // zeby losowo nie przydzielilo sie zero
    Wynik_dzialania cos;

    while(ch != '0' )
    {
        cout << "Kalkulator obiektowy\n";
        cout << "    MENU    \n";
        cout << "1.dodawanie\n";
        cout << "2.odejmowanie\n";
        cout << "3.mnozenie\n";
        cout << "4.dzielenie\n";
        cout << "0. Wyjscie z programu\n";
        cin >> ch;
        switch(ch)
        {
            case '1': cos.dodawanie();
                    break;
            case '2': cos.odejmowanie();
                    break;
            case '3': cos.mnozenie();
                    break;
            case '4': cos.dzielenie();
                    break;
            default: cout << "brak takiej opcji!\n";
        }
        cin.clear(); // czyszczenie bufora, to samo co fflush(stdin) w C ?

    }
    cout << " Do widzenia!\n";


    return 0;
}

Każdą uwagę przyjmę z miłą chęcią.

1

Oddziel logikę od interfejsu.
Fajnie byłoby pobrać wynik działania bez większej zabawy, tj coś w ten deseń
foo = obliczenia(1, 2).mnożenie()
lub
foo = obliczenia(1, 2, obliczenia::mnożenie)()

1

Jest późno, więc pewnie później uznam ten kod za śmieciowy...

#include <iostream>
#include <vector>
#include <map>
using namespace std;

template<class iterator>
class Calculation{
	typedef typename iterator::value_type result_type;
	typedef result_type(Calculation::*action_pointer)() const;
	iterator _begin, _end;
public:
	Calculation(iterator begin, iterator end):
		_begin(begin), _end(end){}
		
	result_type sum() const{
		result_type result = 0;
		for(auto it = _begin; it != _end; ++it)
			result += *it;
		return result;
	}
	
	result_type mul() const{
		result_type result = *_begin;
		for(auto it = _begin+1; it != _end; ++it)
			result *= *it;
		return result;
	}
};

int main(){
	vector<int> v = {1, 2, 3, 4};
	Calculation<vector<int>::iterator> calculation(v.begin(), v.end());
	cout << calculation.sum() << endl;
	cout << calculation.mul() << endl;
	return 0;
}

out:

10
24
0

Ok, póki co to tak zaawansowanego kodu nie rozumiem, bo dopiero co zacząłem czytać o klasach i obiektach, widzę więc że muszę się douczyć sporo :p

Co do tego foo, to wiem o co chodzi z nazwą, miałem na myśli użycie tego przypisania - to co jest po prawej stronie.

Jeśli chodzi o nie używanie w metodach publicznych zapytań i wczytań do zmiennych, to nie wiem za bardzo jak mam to zrobić, skoro z założenia atrybuty powinny być prywatne, więc bezpośrednio z maina nie mogę się do nich odwołać. Chyba, że miałeś na myśli stworzenie osobnej metody, która by pobierała z normalnych zmiennych te dane i przypisywała je atrybutom?

2

Źle, źle, źle - http://pl.wikipedia.org/wiki/DRY
Imho, w takiej formie, w jakiej to masz, potrzebujesz klasy będącej kalkulatorem, która wczytuje liczby i posiada metodę compute przyjmującą jako argument interfejs/klasę abstrakcyjną będącą generycznym działaniem (i ewentualnie drugi parametr typu bool oznaczający, czy zwolnić potem tę klasę, aby nie było memleaków).
Potem tworzysz klasy dziedziczące po tym interfejsie i dopiero one powinny coś liczyć.
Na zasadzie:

Calculator calc;
calc.input(10);
calc.input(20);
cout << calc.compute(new Adder(), true) << endl; // 30
0

Dobra, dzięki za pomoc, muszę dalej czytać Pratę, bo o dziedziczeniu wiele nie wiem, więc na dzień dzisiejszy programu nie jestem w stanie poprawić.

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