• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Niezrozumiałe zachowanie pętli while, defaulta w switchu i wejścia

Object Storage Arubacloud
0 głosów
179 wizyt
pytanie zadane 2 kwietnia 2022 w C i C++ przez Konrad Nabożny Stary wyjadacz (13,460 p.)
#include <iostream>
#include <windows.h>
 
 
using namespace std;
 
int main()
{
 
 
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
 
 
    int choice;
    bool wrongChoice=false;
 
 
 
    SetConsoleTextAttribute(hConsole, 10);
    cout<<endl<<endl << "Co mam uruchomic?" << endl;
    cout << "Wpisz cyfre i zatwierdz klawiszem ENTER" << endl << endl;
    cout << "Lista:" << endl<<endl;
 
    SetConsoleTextAttribute(hConsole, 15);
 
 
    cout << "1. Moj komputer" << endl;
    cout << "2. Informacje o systemie" << endl;
    cout << "3. Konfiguracja systemu" << endl;
    cout << "4. Wlasciwosci systemu" << endl;
    cout << "5. Kopia zapasowa i przywracanie" << endl;
    cout << "6. Ustawienia myszy" << endl;
    cout << "7. Rejestr systemu" << endl;
    cout << "8. Ustawienia zasilania" << endl;
    cout << "9. Monitor zasobow" << endl;
    cout << "10. Dodatkowe funkcje systemu Windows" << endl;
    cout << "11. Lupa systemowa (przeciagaj kursor na krawedz ekranu aby przesuwac widok)" << endl;
    cout << "12. Tablica znakow specjalnych" << endl;
    cout << "13. Polaczenia sieciowe" << endl;
    cout << "14. Systemowe narzedzie do usuwania wirusow i zlosliwego oprogramowania" << endl;
    cout << "15. Meneger urzadzen" << endl;
    cout << "16. Zarzadzanie kontami uzytkownikow" << endl;
    cout << "17. Uslugi" << endl;
    cout << "18. Dodaj lub usun programy" << endl;
    cout << "19. Panel sterowania" << endl;
    cout << "20. Biezacy folder uzytkownika" << endl;
    cout << "21. Klawiatura ekranowa" << endl;
    cout << "22. Narzedzie wycinanie" << endl;
    cout << "23. Diagnostyka pamieci systemu Windows" << endl;
    cout << "24. Podlaczanie pulpitu zdalnego" << endl;
    cout << "25. Wiersz polecen" << endl;
 
    do  {
 
        cin>>choice;
 
        switch(choice)  {
            case 1:
            system("explorer =");
            break;
            case 2:
            system("msinfo32");
            break;
            case 3:
            system("msconfig");
            break;
            case 4:
            system("sysdm.cpl");
            break;
            case 5:
            system("sdclt");
            break;
            case 6:
            system("main.cpl");
            break;
            case 7:
            system("regedit");
            break;
            case 8:
            system("powercfg.cpl");
            break;
            case 9:
            system("resmon");
            break;
            case 10:
            system("optionalfeatures");
            break;
            case 11:
            system("magnify");
            break;
            case 12:
            system("charmap");
            break;
            case 13:
            system("ncpa.cpl");
            break;
            case 14:
            system("mrt");
            break;
            case 15:
            system("devmgmt.msc");
            break;
            case 16:
            system("netplwiz");
            break;
            case 17:
            system("services.msc");
            break;
            case 18:
            system("appwiz.cpl");
            break;
            case 19:
            system("control");
            break;
            case 20:
            system(".");
            break;
            case 21:
            system("osk");
            break;
            case 22:
            system("snippingtool");
            break;
            case 23:
            system("mdsched");
            break;
            case 24:
            system("mstsc");
            break;
            case 25:
            system("cmd");
            break;
            default:
                cerr<<"Wpisales niewlasciwa liczbe, litere, lub znak. Sprobuj ponownie:";
                wrongChoice = true;
                continue;
        }
 
    } while (wrongChoice);
 
    return 0;

Problem polega na tym, że chcę po prostu zrobić walidację wejścia do switcha, że jeśli ktoś źle wpisze cyfrę to będzie miał kolejną próbę. Prosta sprawa. ALE cokolwiek bym nie robił to default wpada mi w pętlę i wywala na ekranie loop z tekstem Wpisałeś niewłaściwą liczbę(...) itp. Próbowałem wraz z kolegą który zna się dosyć dobrze na programowaniu szczególnie w C++ ogarnąć ten problem. Kolega twierdzi że na 100% to jest wina wejścia, dlatego więc mówił żebym pobierał wejście zamiast cinem to scanf. Nie pomogło. Próbowaliśmy string parsować do inta też nic nie dało. Próbowaliśmy wszystkiego co on sam wie i nie poradziliśmy sobie z tym. Wiem że są inne możliwości zrobienia walidacji, ale ja wybrałem taką metodę i chcę dojść do skutku i źródla problemu. Wiem że na pewno da się to naprawić i zrobić tak żeby było dobrze. Pomóżcie bo całą noc nad tym siedzieliśmy i zonk :( 

1 odpowiedź

0 głosów
odpowiedź 2 kwietnia 2022 przez j23 Mędrzec (194,920 p.)
wybrane 3 kwietnia 2022 przez Konrad Nabożny
 
Najlepsza

Na początku pętli daj  wrongChoice = false;

 

komentarz 2 kwietnia 2022 przez Konrad Nabożny Stary wyjadacz (13,460 p.)
Niestety nic to nie daje. Problem jest na 99% z wejściem.
2
komentarz 2 kwietnia 2022 przez j23 Mędrzec (194,920 p.)
edycja 2 kwietnia 2022 przez j23

Z wejściem byłby problem, gdybyś wpisał coś, co nie jest liczbą. Ale tak, to też powodowałoby zapętlenie.

Na wszelki wypadek możesz zrobić tak:

if(!(cin >> choice)) {
    cin.clear();
    cin.ignore(666, '\n');
    break;
}

Ten continue jest bez sensu, bo masz wrongChoice do przerwania pętli.

komentarz 3 kwietnia 2022 przez Konrad Nabożny Stary wyjadacz (13,460 p.)
Hmmm faktycznie działa to tak jak należy, lecz jeszcze jeden problem napotkałem na drodze w tym miejscu, mianowicie: jak wpiszę liczbę ponad 25 czyli np. 333 555 123 32 itp to wszystko działa w porządku. Wyświetla błąd że nieprawidłowe wejście, ale gdy już np. wpiszę litery, to wyrzuca mi tyle razy napis że nieprawidłowe wejście ile liter napisałem. Napiszę bbb, to wypisze mi błąd 3 razy. Nie pytam o rozwiązanie a proszę o lekkie nakierunkowanie mnie na dobry tok myślowy, kombinował ze stringiem i funkcją stoi() ale nie zdało to egzaminu.
komentarz 3 kwietnia 2022 przez j23 Mędrzec (194,920 p.)
Pokaż kod po zmianach, bo coś mi tu nie pasuje (o ile dobrze wstawiłeś warunek, który podałem).
komentarz 3 kwietnia 2022 przez Konrad Nabożny Stary wyjadacz (13,460 p.)
do  {
        wrongChoice = false;

        if(!(cin >> choice)) {
        cin.clear();
        cin.ignore(666, '\n');

    }

        switch(choice)  {
            case 1:

 

 

Doszedłem sam do tego że jeśli usunę break; to wszystko działa.

Powiedz mi taką rzecz, czy cin.ignore(666, '\n'); oznacza że ma ignorować maksymalnie 666 wpisanych błędnie znaków? Załóżmy hipotetycznie że user wpisze 900 znaków, program wtedy się wysypie? Jeśli tak to czy jest jakaś opcja na takie 100% zabezpieczenie? Z resztą pytam jak głupek, na pewno jest, ale czy w przypadku pobierania wejścia z cina to możliwe, czy nie lepszy byłby getline() do stringa a potem jeśli isdigit() to sprawdza czy nie większy niż 25? 

komentarz 3 kwietnia 2022 przez j23 Mędrzec (194,920 p.)

Doszedłem sam do tego że jeśli usunę break; to wszystko działa.

Ten break dałem na potrzeby przykładu, by przerwać pętlę. Zamiast niego możesz dać np. choice = 666; wtedy wykona się default ze switcha i wybór opcji zacznie się od nowa.

Tak jak masz teraz jest źle, bo nic z tej obsługi błędu strumienia nie wynika poza "wyczyszczeniem" strumienia.

Powiedz mi taką rzecz, czy cin.ignore(666, '\n'); oznacza że ma ignorować maksymalnie 666 wpisanych błędnie znaków?

Tak. Ma zignorować maksymalnie 666 znaków, chyba że napotka wcześniej znak końca linii \n.

Jeśli tak to czy jest jakaś opcja na takie 100% zabezpieczenie?

Zamiast 666 daj std::numeric_limits<std::streamsize>::max().

czy nie lepszy byłby getline() do stringa a potem jeśli isdigit() to sprawdza czy nie większy niż 25? 

isdigit nie konwertuje stringa na liczbę, tylko sprawdza, czy znak jest cyfrą.

 

komentarz 3 kwietnia 2022 przez Konrad Nabożny Stary wyjadacz (13,460 p.)
Wielkie dzięki już wiem wszystko co chciałem wiedzieć. Może któregoś dnia bedę miał taką wiedzę jak Ty :)

Podobne pytania

0 głosów
1 odpowiedź 2,306 wizyt
pytanie zadane 29 sierpnia 2017 w C i C++ przez Mithriandil Początkujący (250 p.)
+1 głos
1 odpowiedź 225 wizyt
pytanie zadane 7 marca 2021 w C i C++ przez Waran3 Początkujący (460 p.)
+1 głos
1 odpowiedź 532 wizyt
pytanie zadane 15 listopada 2017 w C i C++ przez Kamil Kukła Nowicjusz (160 p.)

92,572 zapytań

141,423 odpowiedzi

319,645 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...