Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++]Kalkulator

Ostatnio zmodyfikowano 2016-05-25 11:29
Autor Wiadomość
grzekuu
Temat założony przez niniejszego użytkownika
[C++]Kalkulator
» 2016-05-23 17:38:21
Witam, niedawno miałem lekcję o funkcjach i zadanie domowe polegało na ulepszeniu tego podstawowego kalkulatora używając funkcji. Niestety w tym momencie przestał on działać i nie wiem dlaczego. Bardzo proszę o pomoc ;) Wiem, że wyjście z programu nie zadziała, ale potem to zmienię, chodzi mi generalnie o funkcjonowanie kalkulatora.
EDIT:
Precyzując, nie działa zabezpieczenie przy czytaniu liczby 2 i nie pokazuje wyniku. Na sam koniec zapętla się wyświetlanie opcji.

C/C++
#include <iostream>

using namespace std;

short opcje_kalkulatora()
{
    short wybor;
   
    cout << "Oto kalkulator prosty, wybierz dzialanie, ktore chcialbys wykonac." << endl << endl;
    cout << "[1] Dodawanie" << endl;
    cout << "[2] Odejmowanie" << endl;
    cout << "[3] Mnozenie" << endl;
    cout << "[4] Dzielenie" << endl;
    cout << "[5] Wyjscie" << endl << endl;
   
    cout << "Wybor: ";
    do
    {
        cin.clear();
        cin.sync();
       
        cin >> wybor;
       
        if( cin.good() == 0 || wybor > 5 )
        {
            cout << endl;
            cout << "Nie ma takiej opcji" << endl;
            cout << "Co chcesz zrobic? ";
        }
       
    } while( cin.good() == 0 || wybor > 5 );
   
    return wybor;
}

float liczba_1()
{
    float liczba_1;
    cout << endl << "Wprowadz liczbe nr 1: ";
    do
    {
        cin.clear();
        cin.sync();
        cin >> liczba_1;
       
        if( cin.good() == 0 )
        {
            cout << "Musisz wprowadzic liczbe!!!" << endl;
            cout << endl;
            cout << "Podaj liczbe jeszcze raz: ";
        }
       
    } while( cin.good() == 0 );
   
    return liczba_1;
}

float liczba_2()
{
    float liczba_2;
    cout << "Wprowadz liczbe nr 2: ";
    do
    {
        cin.clear();
        cin.sync();
        cin >> liczba_2;
        if( cin.good() == 0 )
        {
            cout << "Musisz wprowadzic liczbe!!!" << endl;
            cout << endl;
            cout << "Podaj liczbe jeszcze raz: ";
        }
       
        if( opcje_kalkulatora() == 4 && liczba_2 == 0 && cin.good() == 1 )
        {
            cout << "Nie mozna dzielic przez 0." << endl;
            cout << endl;
            cout << "Podaj liczbe jeszcze raz: ";
        }
       
    } while( cin.good() == 0 ||( opcje_kalkulatora() == 4 && liczba_2 == 0 && cin.good() == 1 ) );
   
    return liczba_2;
}


void dodawanie()
{
    cout << "Wynik to: " << liczba_1() + liczba_2();
}

void odejmowanie()
{
    cout << "Wynik to: " << liczba_1() - liczba_2();
}

void mnozenie()
{
    cout << "Wynik to: " << liczba_1() * liczba_2();
}

void dzielenie()
{
    cout << "Wynik to: " << liczba_1() / liczba_2();
}


int main()
{
    do
    {
        switch( opcje_kalkulatora() )
        {
        case 1:
            dodawanie();
            break;
        case 2:
            odejmowanie();
            break;
        case 3:
            mnozenie();
            break;
        case 4:
            dzielenie();
            break;
        case 5:
            break;
        }
       
        if( opcje_kalkulatora() != 5 )
        {
            opcje_kalkulatora();
            liczba_1();
            liczba_2();
        }
       
       
    } while( opcje_kalkulatora() != 5 );
   
    return 0;
}
P-148521
carlosmay
» 2016-05-24 01:50:59
C/C++
} while( cin.good() == 0 ||( opcje_kalkulatora() == 4 && liczba_2 == 0 && cin.good() == 1 ) );

C/C++
if( opcje_kalkulatora() != 5 )
W tych warunkach ponownie uruchamiasz działanie funkcji opcje_kalkulatora(), choć pewnie spodziewasz się,
że to co było wprowadzone za pierwszym razem jest tam zapisane.

Zapisz wynik funkcji w jakiejś zmiennej i używaj tej zmiennej.

Podział na funkcje jest sensowny jeśli ma ona tylko jedną funkcjonalność.
Zbyt dużo logiki w jednej funkcji zmniejsza czytelność kodu i jest złą praktyką (co zresztą było przyczyną problemów).

Trochę uproszczony i do uzupełnienia kod:
C/C++
void menu()
{
    cout << "Oto kalkulator prosty, wybierz dzialanie, ktore chcialbys wykonac." << endl << endl;
    cout << "[1] Dodawanie" << endl;
    cout << "[2] Odejmowanie" << endl;
    cout << "[3] Mnozenie" << endl;
    cout << "[4] Dzielenie" << endl;
    cout << "[5] Wyjscie" << endl << endl;
    cout << "Wybor: ";
}

float getNumber()
{
    float number;
    while( !( std::cin >> number ) )
    {
        std::cin.clear();
        std::cin.ignore( std::numeric_limits < std::streamsize >::max(), '\n' );
        std::cout << "Podaj prawidłowe dane:\n ";
    }
    return number;
}

float addition( float num1, float num2 )
{
    return num1 + num2;
}


float division( float num1, float num2 )
{
    if( num2 != 0 ) {
        return num1 / num2;
    }
    else {
        std::cerr << "Nie można dzielić przez zero!\n";
        return 0;
    }
}


auto main()->int
{
    int switchOption;
    float number1;
    float number2;
   
    do
    {
        menu();
        switchOption = static_cast < int >( getNumber() ); // zastosowanie rzutowania na int,
        // aby nie pisać nowej funkcji dla całkowitych
        if( switchOption != 5 ) {
            number1 = getNumber();
            number2 = getNumber();
        }
       
        switch( switchOption ) {
        case 1:
            std::cout << addition( number1, number2 ) << '\n';
            break;
        case 2:
            // ...
            break;
        case 3:
            // ...
            break;
        case 4:
            std::cout << division( number1, number2 ) << '\n';
            break;
        case 5:
            // ...
            break;
        default:
            std::cout << "Nie wybrano poprawnej opcji\n";
        }
       
    } while( switchOption != 5 );
   
    return 0;
}

Ten przykład można jeszcze udoskonalić. Spróbuj napisać funkcję,
która wykona odpowiednie działanie na podstawie otrzymanego znaku arytmetycznego.
P-148534
grzekuu
Temat założony przez niniejszego użytkownika
» 2016-05-24 12:04:51
Generalnie udało mi się to rozwiązać w ten sposób, że właśnie przypisałem wartość funkcji do zmiennej(na początku tego nie zrozumiałem po prostu, że użycie funkcji to wywowłanie jej za każdym razem), ustawieniu argumentu opcja=0(jako domyślnie,trochę wymuszone) przy funkcji liczba_2 i jeżeli wybrałem dzielnie to mam liczba_2(4) czyli warunek wystąpienia komunikatu zabezpieczającego przed dzieleniem przez 0.
C/C++
#include <iostream>

using namespace std;

short opcje_kalkulatora()
{
    short wybor;
   
    cout << "Oto kalkulator prosty, wybierz dzialanie, ktore chcialbys wykonac." << endl << endl;
    cout << "[1] Dodawanie" << endl;
    cout << "[2] Odejmowanie" << endl;
    cout << "[3] Mnozenie" << endl;
    cout << "[4] Dzielenie" << endl;
    cout << "[5] Wyjscie" << endl << endl;
   
    cout << "Wybor: ";
    do
    {
        cin.clear();
        cin.sync();
       
        cin >> wybor;
       
        if( cin.good() == 0 || wybor > 5 )
        {
            cout << endl;
            cout << "Nie ma takiej opcji" << endl;
            cout << "Co chcesz zrobic? ";
        }
       
    } while( cin.good() == 0 || wybor > 5 );
   
    return wybor;
}

float liczba_1()
{
    float liczba_1;
    cout << endl << "Wprowadz liczbe nr 1: ";
    do
    {
        cin.clear();
        cin.sync();
        cin >> liczba_1;
       
        if( cin.good() == 0 )
        {
            cout << "Musisz wprowadzic liczbe!!!" << endl;
            cout << endl;
            cout << "Podaj liczbe jeszcze raz: ";
        }
       
    } while( cin.good() == 0 );
   
    return liczba_1;
}

float liczba_2( short opcja = 0 )
{
    float liczba_2;
    cout << "Wprowadz liczbe nr 2: ";
    do
    {
        cin.clear();
        cin.sync();
        cin >> liczba_2;
        if( cin.good() == 0 )
        {
            cout << "Musisz wprowadzic liczbe!!!" << endl;
            cout << endl;
            cout << "Podaj liczbe jeszcze raz: ";
        }
       
        if( opcja == 4 && liczba_2 == 0 && cin.good() == 1 )
        {
            cout << "Nie mozna dzielic przez 0." << endl;
            cout << endl;
            cout << "Podaj liczbe jeszcze raz: ";
        }
       
    } while( cin.good() == 0 ||( opcja == 4 && liczba_2 == 0 && cin.good() == 1 ) );
   
    return liczba_2;
}


void dodawanie()
{
    cout << "Wynik to: " << liczba_1() + liczba_2() << endl;
}

void odejmowanie()
{
    cout << "Wynik to: " << liczba_1() - liczba_2() << endl;
}

void mnozenie()
{
    cout << "Wynik to: " << liczba_1() * liczba_2() << endl;
}

void dzielenie()
{
    cout << "Wynik to: " << liczba_1() / liczba_2( 4 ) << endl;
}


int main()
{
    short opcja;
    do
    {
        opcja = opcje_kalkulatora();
        switch( opcja )
        {
        case 1:
            dodawanie();
            break;
        case 2:
            odejmowanie();
            break;
        case 3:
            mnozenie();
            break;
        case 4:
            dzielenie();
            break;
        case 5:
            break;
        }
       
       
    } while( opcja != 5 );
   
    return 0;
}
P-148542
carlosmay
» 2016-05-24 12:27:31
Popracuj nad logiką programu (jest niepoprawna).

Pisanie takich funkcji mija się z celem, o czym nadmieniłem w poprzednim poście.
C/C++
float liczba_2( short opcja = 0 )
{
    float liczba_2;
    cout << "Wprowadz liczbe nr 2: ";
    do
    {
        cin.clear();
        cin.sync();
        cin >> liczba_2;
        if( cin.good() == 0 )
        {
            cout << "Musisz wprowadzic liczbe!!!" << endl;
            cout << endl;
            cout << "Podaj liczbe jeszcze raz: ";
        }
       
        if( opcja == 4 && liczba_2 == 0 && cin.good() == 1 )
        {
            cout << "Nie mozna dzielic przez 0." << endl;
            cout << endl;
            cout << "Podaj liczbe jeszcze raz: ";
        }
       
    } while( cin.good() == 0 ||( opcja == 4 && liczba_2 == 0 && cin.good() == 1 ) );
   
    return liczba_2;
}

edit:
warunek też jest skomplikowany i nieczytelny:
C/C++
bool isGoodNumber = false;
// ....
do {
    // ...
    isGoodNumber = liczba_2 != 0 && cin.good() == true;
} while( !isGoodNumber ); // lub zostawić (liczba_2 != 0  && cin.good() == true)

Tak jest trochę czytelniej (opcji nie ma co sprawdzać i przekazywać do funkcji,
tym powinien zajmować się
switch
).
P-148543
grzekuu
Temat założony przez niniejszego użytkownika
» 2016-05-24 22:22:51
Dobra, może i niepoprawna, ale programuje tydzień. Uczę się dopiero, a poza tym miałem zadanie zrobić kalkulator z użyciem dużej ilości funkcji żeby zrozumieć ich działanie, a teraz przynajmniej wiem jak co w miarę  działa, jak są wywoływane i jak pobierać z nich wartości. Z góry dzięki za odpowiedź i pomoc, ale z tego kodu co mi podałeś i tak nic nie rozumiem, bo tak jak wspomniałem dopiero zacząłem, co zresztą widać po kodzie, który piszę :) 
P-148557
carlosmay
» 2016-05-24 22:53:21
Dobra, może i niepoprawna, ale programuje tydzień.
To nie znaczy, że nie można próbować pisać lepiej.

Prościej: Jeśli funkcja np. twoja int liczba_2 ma pobrać liczbę od użytkownika,
niech tylko tym się zajmuje.
Sprawdzanie opcji dla switch niech robi kolejna funkcja.

Rozbijaj kod na małe fragmenty i składaj jak klocki.
P-148558
grzekuu
Temat założony przez niniejszego użytkownika
» 2016-05-25 11:29:29
Staram się jak mogę ;) Teraz zrobiłem to tak, że wczytywaniem liczby zajmuje się jedna funkcja zarówno do opcji kalkulatora jak i liczb, także na razie to jest szczyt moich możliwości, a uczę się dalej ;)
P-148564
« 1 »
  Strona 1 z 1