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

[Lekcja 17] Zadanie domowe - kalkulator oparty na funkcjach

Ostatnio zmodyfikowano 2014-12-03 09:17
Autor Wiadomość
Rashmistrz
» 2014-11-27 15:59:51
Czyli rozumiem, że dla każdej z dwóch
wprowadzanych liczb muszę utworzyć po 1 funkcji?
NIE!
Te funkcje miałyby takie samo zadanie,
czyli pobrać liczbę od użytkownika!
Do tej czynności wystarczy jedna funkcja!

Zmodyfikuj kalkulator, [...], aby korzystał on
ze wcześniej napisanej funkcji wczytajLiczbe.


Jak Ci się nie będzie podobać pobrana liczba
to pobieraj tak długo aż będzie odpowiednia.
P-121550
bladegd
Temat założony przez niniejszego użytkownika
» 2014-12-01 11:55:30
Czy w takim razie chodziło o coś takiego?
void wczytajLiczbe(float a, float b)
{
   bool failA, failB;
   do
   {
       cin.clear();
       cin.ignore(1000,'\n');
       cout<<"Liczba a: ";
       cin>>a;
       failA=cin.fail();
   }while(failA||a==0);
   
   do
   {
       cin.clear();
       cin.ignore(1000,'\n');
       cout<<"Liczba b: ";
       cin>>b;
       failB=cin.fail();
   }while(failB||b==0);
}

Tutaj main - i moje pytanie co robię źle, że bo nie mogę dojść. Dlaczego argumety przekazane z funkcji main do funkcji wczytajLiczbe nie zapamiętują wartości, które wpisuję do tych zmiennych:
int main()
{
    int choice;
    float a,b;
    cout << "Witaj w kalkulatorze.\nWcisnij ENTER, aby rozpocząć.";
    wczytajLiczbe(a, b);
    cout <<"Co chcesz obliczyć?"<<endl;
    cout<<"[1] Dodawanie"<<endl;
    cout<<"[2] Odejmowanie"<<endl;
    cout<<"[3] Mnozenie"<<endl;
    cout<<"[4] Dzienlenie"<<endl;
    cout<<"[5] Rezygnuj"<<endl;
    cout<<"wybierz dzialanie[1-5]: ";
    do
    {
        cin.clear();
        cin.ignore( numeric_limits < streamsize >::max(), '\n' );
        cin>>choice;
    }while(choice>5||choice<1);

    switch(choice)
    {
        case 1:
            cout<<a<<" + "<<b<<" = "<< a+b <<endl;
            break;
        case 2:
            cout<<a<<" - "<<b<<" = "<< a-b <<endl;
            break;
        case 3:
            cout<<a<<" * "<<b<<" = "<< a*b <<endl;
            break;
        case 4:
            cout<<a<<" / "<<b<<" = "<< a/b <<endl;
            break;
        case 5:
            return 0;
            break;
    }
    return 0;
}
Wynikiem wyjściowym którejkolwiek operacji jest 0(+-/*)0 = 0.
P-121814
Rashmistrz
» 2014-12-01 15:27:37
Przeczytaj jeszcze raz wszystkie
posty w tym temacie... Głównie moje. :F
___________________________________________________________________

A większość odpowiedzi na twoje problemy
z ostatniego postu znajdują się tu:
» Kurs C++ » Poziom 2Funkcje - pierwsze starcie lekcja
P-121829
bladegd
Temat założony przez niniejszego użytkownika
» 2014-12-02 12:31:43
Zrobiłem co poradziłeś i odpowiedzi nie znalazłem. Zakładając, że funkcja wczytajLiczbe, która umieściłem wyżej jest poprawna i tak właśnie miała wyglądać, a błąd mam w funkcji main(z zapisem wartości do zmiennej) - nie wiem jak powinien wyglądać zapis wartości wprowadzanych do funkcji jako argumenty tej funkcji do 2 zmiennych z innej funkcji(w tym przypadku funkcji main).
Zapis int liczba = wczytajLiczbe(); z przykładu sugeruje mi, że miałbym to zrobić na 2 funkcjach wczytujących po 1 wartości, tak jak to wcześniej zrobiłem, ale napisałeś mi, że nie o to chodzi. A funkcja ma być 1 do wprowadzanych wartości. Więc tu moje pytanie jak mam zapisać 2 wartości wprowadzone do zmiennych? Bo funkcja return wartość rozumiem, że nie zadział, bo tu mam 2 wartości do zwrócenia i zapisania.
Proszę o odpowiedź i wyjaśnienia, bo ja już nie wiem jak zwrócić 2 wartości przez funkcję tak, aby zapisało je do zmiennych w funkcji z której te zmienne pochodzą. W tej lekcji jest napisane, że:
Zmienne, które zostały utworzone w funkcji są zmiennymi tymczasowymi. Zmienne te pojawiają się do użytku przy każdym wywołaniu funkcji jak również znikają po jej opuszczeniu. Zmienne te nie trzymają stanu z poprzedniego wywołania - innymi słowy za każdym razem po wejściu w funkcję musisz nadać wartości zmiennym na nowo.
Ja już nie wiem czy zapisanie zmiennych jako argumentu funkcji zapisuje wprowadzone wartości do tych zmiennych czy nie?
P-121922
Rashmistrz
» 2014-12-02 15:53:16
//To było takie długie do napisania, że nie wiem czy wszystko jest.
//Przez przypadek mogłem napisać to co już wiesz :/

Zrobiłem co poradziłeś i odpowiedzi nie znalazłem.
Zapewniam Cię, że są...

(przed podłużną kreską sprawdź czy
zrozumiałeś opisany przed nią błąd)

nie wiem jak zwrócić 2 wartości przez funkcję tak, aby zapisało je do zmiennych w funkcji z której te zmienne pochodzą. [...]Ja już nie wiem czy zapisanie zmiennych jako argumentu funkcji zapisuje wprowadzone wartości do tych zmiennych czy nie?
Zmienne podawane w argumentach są "kopiowane",
a jak zrobić tak aby dało się modyfikować te zewnętrzne,
które podawaliśmy w argumentach, dowiesz się za parę lekcji.
_________________________________________________________

Zakładając, że funkcja wczytajLiczbe,
która umieściłem wyżej jest poprawna
Na samym początku właśnie była błędna...

Funkcja na tym "poziomie nauczania" może zwracać
tylko jedną zmienną i tylko jednego wybranego typu.
C/C++
int to_jest_moja_funkcja()
{
    int i = 0;
    return i;
}
Bądź nic nie zwracać:
C/C++
void to_jest_moja_funkcja()
{
    // tu kod Twojej funkcji
}
błędy w założeniach?
Tak jak wcześniej wspomniałem:
"
return a || b;
".
Na razie na tym poziome kursu funkcje mogą tylko zwracać jedną wartość,
a w tym przypadku wracasz sumę logiczną "a" i "b".
» Kurs C++ » Poziom 1Operacje logiczne lekcja
_________________________________________________________

Zapis
int liczba = wczytajLiczbe();
 z przykładu sugeruje mi, że miałbym to zrobić na 2 funkcjach wczytujących po 1 wartości, tak jak to wcześniej zrobiłem, ale napisałeś mi, że nie o to chodzi.

Dobrze wtedy zrobiłeś, ale mnie źle zrozumiałeś.
Mi chodziło o duplikację tych funkcji:

Czyli rozumiem, że dla każdej z dwóch
wprowadzanych liczb muszę utworzyć po 1 funkcji?
NIE!
Te funkcje miałyby takie samo zadanie,
czyli pobrać liczbę od użytkownika!
Do tej czynności wystarczy jedna funkcja!

Zmodyfikuj kalkulator, [...], aby korzystał on
ze wcześniej napisanej funkcji wczytajLiczbe.

Jak Ci się nie będzie podobać pobrana liczba
to pobieraj tak długo aż będzie odpowiednia.
PS. Na samym początku miałeś źle napisaną funkcję,
dlatego skreśliłem część cytatu. :F
_________________________________________________________________

błąd mam w funkcji main(z zapisem wartości do zmiennej)
W miejscu wywołania funkcji pojawi się zwracana wartość. ^_^
Jeśli funkcja będzie typu void to kompilator błędy wyrzuci.
C/C++
int a = wczytajLiczbe();
int b = wczytajLiczbe();
Jak Ci się nie będzie podobać pobrana liczba
to pobieraj tak długo aż będzie odpowiednia.
Polecam do tego użyć pętli.
_________________________________________________________________

nie wiem jak powinien wyglądać zapis wartości
wprowadzanych do funkcji jako argumenty tej funkcji
do 2 zmiennych z innej funkcji(w tym przypadku funkcji main).
Rozumiem w tym piąte przez dziesiąte... :/
Zmienne podawane w argumentach są "kopiowane"
i funkcja działa na odrębnych w pamięci zmiennych...

Przykład: (przeanalizuj kod i jego wynik)
C/C++
#include <iostream>
using std::cout;

short dodanie( int przyjeta = 0, int standardowa = 10 )
{
    return przyjeta + standardowa;
}

int main()
{
    int testowa = 2;
    int dodatkowa = dodanie( testowa );
    int dodatkowa2 = dodanie();
    cout << testowa << ' ' << dodatkowa << ' ' << dodatkowa2;
    return 0;
}
__________________________________________________________________

P-121939
bladegd
Temat założony przez niniejszego użytkownika
» 2014-12-02 18:18:05
Ok chyba mnie olśniło dzięki Tobie.
Czy właśnie o tego typu rozwiązanie chodziło?
#include <iostream>
#include <limits>

using namespace std;

float wczytajLiczbe(int l)
{
   float a;
   cout<<endl;
   cout<<"Liczba "<<l<<": ";
   cin>>a;
   return a;
}

int main()
{
    int choice,l;
    float a,b;
    cout << "Witaj w kalkulatorze.\nWcisnij ENTER, aby rozpocząć.";
    bool failA,failB;
    do{
       cin.clear();
       cin.ignore(1000,'\n');
       l=1;
       a=wczytajLiczbe(l);
       failA=cin.fail();
       cin.clear();
       cin.ignore(1000,'\n');
       l=2;
       b=wczytajLiczbe(l);
       failB=cin.fail();
    }while(a==0||b==0||failA||failB);

    cout <<"Co chcesz obliczyć?"<<endl;
    cout<<"[1] Dodawanie"<<endl;
    cout<<"[2] Odejmowanie"<<endl;
    cout<<"[3] Mnozenie"<<endl;
    cout<<"[4] Dzienlenie"<<endl;
    cout<<"[5] Rezygnuj"<<endl;
    cout<<"wybierz dzialanie[1-5]: ";
    do
    {
        cin.clear();
        cin.ignore( numeric_limits < streamsize >::max(), '\n' );
        cin>>choice;
    }while(choice>5||choice<1);

    switch(choice)
    {
        case 1:
            cout<<a<<" + "<<b<<" = "<< a+b <<endl;
            break;
        case 2:
            cout<<a<<" - "<<b<<" = "<< a-b <<endl;
            break;
        case 3:
            cout<<a<<" * "<<b<<" = "<< a*b <<endl;
            break;
        case 4:
            cout<<a<<" / "<<b<<" = "<< a/b <<endl;
            break;
        case 5:
            return 0;
            break;
    }
    return 0;
}

Cytat:
Zapewniam Cię, że są...
Nie przeczę ani nie zarzucam Ci kłamstwa, zwyczajnie nie byłem w stanie dostrzec rozwiązania ;).

Swoją drogą bardzo ciekawa właściwość funkcji w tym przykładzie na końcu Twojego postu. Dzięki Ci za ten przykład. Na początku nie mogłem zrozumieć o co Ci chodzi z tym przykładem bo podczas jego analizowania skupiłem się na tej właściwości (dla mnie nowej) funkcji jakiej użyłeś w tym przykładzie. A tu chodziło o to, że dana funkcja robiąc konkretne zadanie może być wykorzystana w *pip* razy, a nie tak jak ja zdublowałem funkcje, która już robiła to co miała robić. Zupełnie nie pomyślałem i bezmyślnie to zrobiłem, że jakbym miał stworzyć 10 zmiennych wprowadzanych z klawiatury to bym dopiero wtedy pewnie się skapnął, że tu jest coś bez sensu pomyślane.
Chyba, że nie o to chodziło :P.

////Offtop
Gdzie znajdę dostępne znaczniki do formatowania tekstu w poście? Bo nie wiem jak zrobić ramkę z cytatem i c++ itp. Jedyne co wiem to "code".
P-121967
Rashmistrz
» 2014-12-02 18:52:43
Czynisz postępy, jednak jeszcze
się przyczepię do paru rzeczy:

cout << "Witaj w kalkulatorze.\nWcisnij ENTER, aby rozpocząć.";
.
Nie są obsługiwane znaki polskie.
Jest oczywiście na to sposób,
ale nie w tym czasie...

Użyj funkcji wczytajLiczbe
również dla wyboru opcji.
(Gdy przypiszesz zmiennej typu int zmienną typu float,
to ulegnie ona "rzutowaniu". Efektem będzie ucięcie
części ułamkowej(mantysy), więc nie będziesz
się musiał martwić o switch'a )

Przenieś metody związane z wczytywaniem tekstu
do wnętrza funkcji wczytajLiczbe.
(Chodzi mi o "cin.clear" i inne tego typu z kropką.)

bool failA, failB;
.
cin.fail()
 i
cin.good()
 możesz wywoływać w warunku pętli C:
W miejscu wywołania funkcji pojawi się zwracana wartość. ^_^

Pierwsza pętla bardzo mi się nie podoba,
przez nią nie możemy dodać zero do zera. :F

... i zrób coś z dzieleniem po tym,
bo nie można dzielić przez zero.
____________________________________________________________________________

Gdzie znajdę dostępne znaczniki do formatowania tekstu w poście?
» KursyKurs STC kurs
P-121973
bladegd
Temat założony przez niniejszego użytkownika
» 2014-12-02 20:36:16
C/C++
#include <iostream>
#include <limits>

using namespace std;

float wczytajLiczbe()
{
    float a;
    bool fail;
    do {
        cin.clear();
        cin.ignore( numeric_limits < streamsize >::max(), '\n' );
        cin >> a;
        fail = cin.fail();
    } while( fail );
   
    return a;
}

void menu()
{
    cout << "Co chcesz obliczyc?" << endl;
    cout << "[1] Dodawanie" << endl;
    cout << "[2] Odejmowanie" << endl;
    cout << "[3] Mnozenie" << endl;
    cout << "[4] Dzienlenie" << endl;
    cout << "[5] Rezygnuj" << endl;
}

void obliczenia( float a, float b, int choice )
{
    switch( choice )
    {
    case 1:
        cout << a << " + " << b << " = " << a + b << endl;
        break;
    case 2:
        cout << a << " - " << b << " = " << a - b << endl;
        break;
    case 3:
        cout << a << " * " << b << " = " << a * b << endl;
        break;
    case 4:
        cout << a << " / " << b << " = " << a / b << endl;
        break;
    case 5:
        break;
    }
}

int main()
{
    int choice;
    float a, b;
    string text = "";
    cout << "Witaj w kalkulatorze.\nWcisnij ENTER, aby rozpoczac." << endl;
    bool failA, failB;
    do {
        cout << "Wprowadz 1 liczbe: ";
        a = wczytajLiczbe();
        cout << "Wprowadz 2 liczbe: ";
        b = wczytajLiczbe();
    } while( a == 0 || b == 0 );
   
    menu();
    do
    {
        cout << "Wybierz dzialanie[1-5]: ";
        choice = wczytajLiczbe();
    } while( choice > 5 || choice < 1 );
   
    obliczenia( a, b, choice );
   
    return 0;
}

Czy chodziło Ci o coś takiego odnośnie
cin.fail()
?
I jeszcze mam pytanie dlaczego po:
cout << "Witaj w kalkulatorze.\nWcisnij ENTER, aby rozpoczac." << endl;
do razu przechodzi mi do
cout << "Wprowadz 1 liczbe: ";
Kiedy odpalam program po kompilacji.

Pierwsza pętla bardzo mi się nie podoba,
przez nią nie możemy dodać zero do zera. :F

... i zrób coś z dzieleniem po tym,
bo nie można dzielić przez zero.
Nie ogarniam czy to na poważnie czy nie :P

Wielkie dzięki za poświęcony czas dla mnie.
P-121993
1 « 2 » 3
Poprzednia strona Strona 2 z 3 Następna strona