Wracanie do konkretnego miejsca w programie

0

Witam. Czy jest możliwość wrócenia do odpowiedniego miejsca programu? Przykładowo robię program, który wyświetla po kolei pytania i oczekuje na nie odpowiedzi. Przy każdorazowym wyświetleniu programu była by możliwa opcja wstecz (do poprzedniego pytania). Szukając w internecie natknąłem się na rozwiązanie mojego problemu funkcją "goto", jednak czytałem, że jej stosowanie jest nie wskazane. Macie może inne pomysły na rozwiązanie mojego problemu?

0

Pokaż kod. I piszesz to w konsoli czy w czymś innym?

0
Archeolog123 napisał(a)

Szukając w internecie natknąłem się na rozwiązanie mojego problemu funkcją "goto", jednak czytałem, że jej stosowanie jest nie wskazane. Macie może inne pomysły na rozwiązanie mojego problemu?
Nie funkcja, tylko instrukcja. Jakieś brednie czytałeś.

0

goto, longjmp - zwykle zbędne, ale raz na ruski rok niezastąpione.
najczęściej jest tak, że jeżeli potrzebne to znaczy, że kod nieprzemyślany.

2

Może wreszcie ktoś odpowie na pytanie:
Rozwiązaniem twojego problemu nie jest goto (ono jest zwykle źródlem problemów ;]) tylko podział programu na funkcje oraz wykorzystanie pętli.

0

A tak przy okazji, przydała wam się kiedyś faktycznie instrukcja goto? I co to był za przypadek?

0

Polecenie if w dosie nie miało else. Zatem goto było niezbędne.
W "normalnych" językach, nigdy.

0

kopiowałem CP/M <-> DOS, parę lat temu :-)

0
ubuntuser napisał(a)

A tak przy okazji, przydała wam się kiedyś faktycznie instrukcja goto? I co to był za przypadek?

Przydało,kiedy była potrzeba przerwania zagnieżdżonych pętli.

Inny przypadek to długawa funkcja mająca tylko 1 return na końcu (taki wymóg odgórny),a na początku sprawdzająca intensywnie parametry.Łatwiej analizowało się kod:

if(param1!=coś_tam)
{
     errorCode=SomeEnum::ErrorCode;
     goto exit_function;//jump down to line XXX
}
//spooro kodu,którego podział na kilka funkcji nie wchodził w rachubę
exit_function:
    rerun errorCode;

Parametrów było z 6,a każdy miał naprawdę nieźle pokomplikowane sprawdzenia,no i w przypadku jak nieprawidłowy okazywał się choćby 1 z nich to funkcję należało zakończyć.Wbrew obiegowej opinii taki kod czytało się łatwiej,bo po napotkaniu goto człowiek nie musiał śledzić pozostałych ifów i ciała funkcji,tylko od razu szedł do llinii XXX.

Kolejny przypadek to znów pozagnieżdżane pętle.W pewnym momencie zmieniła się funkcjonalność,tak że pewien fragment kodu w pewnych okolicznościach trzeba było powtórzyć.Dodanie kolejnego whila spowodowało paskudny wygląd całości,i tutaj znów z pomocą przyszło minimalistyczne,proste goto

@autor
Wracając do meritum sprawy,najpewniej potrzebujesz pętli.Ale tego bez zobaczenia kodu to ci nie powiemy na 100%.

0

@ubuntuser: W C czasami się przydaje. Zdarza się tak, że funkcja trochę pracuje na stercie, np alokowane są jakieś większe tablice. Wewnątrz funkcji jest kilka przypadków jej zakończenia działania i za każdym razem trzeba posprzątać ten syf, przesłać dane do jakiegoś pliku itp. Oczywiście, że można wydzielić sztuczną funkcję, ale po co? Jaki jest z tego zysk? Etykiety też mają nazwy. To tylko zbędne rozrzucanie kodu w pliku. W C++ jest trochę inaczej, bo tam zwykle kompilator załatwia sprawę za pomocą destruktorów, które są odpalane przed każdym wyjściem z funkcji.
No i oczywiście zagnieżdżone pętle. Rozumiem, że wszyscy przeciwnicy goto nie korzystają także z while(1)... argumentacja ta sama.

0

Taki prosty kod do odpalenia w konsoli. Jak napisałem w komentarzu interesuje mnie powrót do jednego z pytań, po czym kontynuacja programu na miejscu na którym skończyłem, oraz drugi sposób, czyli powrót do interesującego mnie pytania i wykonanie od tego miejsca programu jeszcze raz. Mam nadzieje że zrozumieliście ;p

#include <iostream>
#include <conio.h>
//Jakas ankieta

using namespace std;

int main()
{

    short wb,wiek,wzrost,waga,wstecz;

    do
    {
        cin.clear();
        cin.sync();
        system("cls");
        cout << "Mini ankieta, czy chcesz wziac udzial?" << endl << endl;
        cout << "1. Tak" << endl << "2. Nie" << endl;
        cin >> wb;
    }while(wb>2 || wb<1 || cin.fail());
    if(wb==1)
    {

        cin.clear();
        cin.sync();
        //Pierwsze pytanie
        do
        {
         system("cls");
         if(cin.fail())cout << "Podano zly wiek. Wiek musi byc liczba naturalna." << endl;
         cin.clear();
         cin.sync();
         cout << "Podaj swoj wiek (w latach):" << endl;
         cin >> wiek;
        }while(cin.fail()|| wiek<1);
        //Drugie pytanie
        do
        {
         system("cls");
         if(cin.fail())cout << "Podano zla wage. Waga musi byc liczba naturalna." << endl;
         cin.clear();
         cin.sync();
         cout << "Podaj swoja wage (w kilogramach):" << endl;
         cin >> waga;
        }while(cin.fail() || waga<1);
        //Trzecie pytanie
        do
        {
         system("cls");
         if(cin.fail())cout << "Podano zly wzrost. Wzrost musi byc liczba naturalna." << endl;
         cin.clear();
         cin.sync();
         cout << "Podaj swoj wzrost (w cm)" << endl;
         cin >> wzrost;
        }while(cin.fail() || wzrost<1);

        //Mozliwosc wrocenia do poprzedniego pytania
        do
        {
            cin.clear();
            cin.sync();
            system("cls");
            cout << "Czy chcesz wrocic do ktoregos z pytan?" << endl;
            cout << "1. Tak, chce wrocic do pytania nr 1" << endl;
            cout << "2. Tak, chce wrocic do pytania nr 2" << endl;
            cout << "3. Tak, chce wrocic do pytania nr 3" << endl;
            cout << "4. Nie, chce przejsc dalej" << endl;
            cin >> wstecz;

        }while(wstecz <1 || wstecz >4 || cin.fail());

        //Kod, ktory umozliwia przejscie do poprzedniego pytania. Chcialbym, znac 2 przyklady:
        //1. Przenosze sie np do pytania nr 1 i odpowiadam tylko na nie, po czym kontynuuje program,
        //2. Przenosze sie np do pytania nr 1 odpowiadam na nie, po czym wedlug kodu przechodze do pytania nr 2
        system("cls");
        cout << "Oto twoje dane:" << endl << "Masz " << wiek << " lat, " << wzrost << "cm wzrostu i wazysz " << waga << "kg." << endl;
        cout << "Aby zakonczyc nacisnij dowolny klawisz";
        getch;
    }
    if(wb==2)return 0;
}
 
0

Przepraszam ale czy ty jesteś normalny? Za używanie kombinacji ctrl+c i ctrl+v powinien być zakaz programowania.
Taki kod:

        do
        {
         system("cls");
         if(cin.fail())cout << "Podano zla wage. Waga musi byc liczba naturalna." << endl;
         cin.clear();
         cin.sync();
         cout << "Podaj swoja wage (w kilogramach):" << endl;
         cin >> waga;
        }while(cin.fail() || waga<1);

Powtarzasz tutaj kilka razy. Nie dalo się napisac funkcji:

int pytania(string pytanie, string blad)
        do
        {
         system("cls");
         if(cin.fail())cout << blad << endl;
         cin.clear();
         cin.sync();
         cout << pytanie << endl;
         int wartosc;
         cin >> wartosc;
        }while(cin.fail() || wartosc<1);
return wartosc;

Tak trudno?
Pytania i blędy można stablicować, wtedy wystarczy ci wywołanie:

// wracamy do pytania nr X?
int wynik = pytania(pyt[X],err[X]);
2

Przydało,kiedy była potrzeba przerwania zagnieżdżonych pętli.
To jest najczęściej przytaczany argument „za”, ale świadczy o skomplikowanym kodzie — pętla powinna prawdopodobnie być w odrębnej metodzie, i starczyłby return albo break.

0

Przepraszam, jestem początkujący a uczę się jedynie ze źródeł internetowych, więc prosiłbym o zrozumienie że mam braki, co nie oznacza żeby od razu nazywać mnie nienormalnym (nie wierzę Shalom, że Ty od razu pisałeś idealne programy). Wracając do tematu, niekoniecznie podałem dobry przykład. Jeżeli mam program, który np w 1 części programu podaję pole kwadratu i na podstawie tego oblicza mi długość boku, następnie w 2 częsci na podstawie długości boku oblicza mi przekątną kwadratu, w 3 części na podstawie przekątnej oblicza.... itd. Czy jeżeli chcę zrealizować program oparty na takiej zasadzie to dla każdej "części" programu muszę napisać oddzielną funkcję? Jeżeli tak, to w jaki sposób wykonać, aby wracając np do części 1 zostały wykonywane kolejne kroki?

0

Zobacz przykład "demonstrating..." na tej stronie:
http://www.java-samples.com/showtutorial.php?tutorialid=327

Dodaj do tego pętlę while(1) i masz rozwiązanie:

//main
while(1) {
  switch(cos_tam) {
  }
}

Podział na funkcje to dość zaawansowany temat, ale najprościej to ujmując:

  • niech każda funkcja robi dokładnie jedną rzecz
  • najlepiej jeśli funkcja ma od 2 linijek do maks dwóch ekranów
  • jedną funkcję możesz wywołać z innej
  • przykłady:
    • wczytaj plik
    • wyszukaj dane w strukturze
    • oblicz wartość parametru X
    • zapisz plik
    • wyświetl raport końcowy
0

Dzięki vpiotr, o to mi właśnie chodziło. Chciałbym jeszcze, aby ktoś potwierdził czy dobrze rozumuje. Do każdego "etapu" muszę napisać oddzielną funkcję, aby wywołać którąś z funkcji jeszcze raz po prostu ją wywołuje. Jeżeli chcę, aby po odwołaniu się do pewnego elementu programu został on wykonany jeszcze raz, a następnie kolejne elementy muszę zrobić nieskończoną pętle while(1), następnie za pomocą instrukcji wyboru switch dopasować pod każdy "przypadek" jedną z fuknkcji, lecz breaka umieścić dopiero po wszystkich wywołaniach. Jeżeli wybiorę jeszcze raz którąś z nich, to funkcję zostaną wykonane po kolei. Jeżeli nie chcę powtarzać funkcji, wychodzę za pomocą breaka z nieskończonej pętli i kontynuuje program. Dobrze myślę?

0

Mniej wiecej tak, ale zarowno ze switcha jak i z while'a wychodzi sie przez break (jak zauwazyles), wiec bedziesz potrzebowal jakos wykryc po switch potrzebe zakonczenia while, jesli dodasz w tym celu zmienna to mozesz jej uzyc w warunku petli while - wtedy break bedzie potrzebny tylko w switch.

0

Ok wszystko jasne. Jeszcze raz dziękuje :)

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