Problem z pętlą while z trzema warunkwami – pętla działa niezależnie

0

Witam, mam problem z pętlą while, w której znajdują się 3 warunki:

            cin>>bet;
                while(bet!='L' || bet!='X' || bet!='H'){
                    cout<<"Zla opcja! Jedyne mozliwe to: L/X/H"<<endl;
                    cout<<"Zwroc uwage na wielkosc litery!"<<endl;
                    cout<<"Co chcesz obstawic? [L/X/H]"<<endl;
                    cin>>bet;
                }

Problem polega na tym, że pętla działa niezależnie od wartości w zmiennej char o nazwie bet.

4

bo warunek jest taki, ze zawsze bedzie spelniony - podstawy logiki jesli masz a != 1 lub a != 2 - to czy bedzie j1, 2 czy cokolwiek innego warunek zawsze bedze spelniony. Pomysl raz jeszcze nad tym warunkiem.

5

Podstawy logiki. Jak działa OR:

p q p ∨ q
0 0 0
0 1 1
1 0 1
1 1 1

Więc

znak bet!='L' bet!='X' bet!='H' bet!='L'bet!='X'bet!='H'
L 0 1 1 1
X 1 0 1 1
H 1 1 0 1
każdy inny 1 1 1 1
6

Tak naprawdę lepiej zrobić do...while, bo niepotrzebnie się powtarzasz:

do
{

}while(bet!='L' && bet!='X' && bet!='H');

A jeszcze lepiej zrobić sobie kolekcję znaków, które definiują warunek i sprawdzać czy wpisany znak występuje w kolekcji:

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

int main(){
    char bet;
    vector<char> bets = { 'L', 'X', 'H' };
    do{
        cout<<"Zla opcja! Jedyne mozliwe to: L/X/H"<<endl;
        cout<<"Zwroc uwage na wielkosc litery!"<<endl;
        cout<<"Co chcesz obstawic? [L/X/H]"<<endl;
        cin>>bet;
    }while(find(bets.begin(), bets.end(), bet) == bets.end());

    return 0;
}
0

@kaczus: @kq
Słuszna uwaga, dzięki :)
@grzesiek51114
Jeszcze się z czymś takim nie spotkałem, stąd brak takiej metody ;P

0

Teraz pytanie czy da się to napisać, używając absolutnych podstaw c++?
Czy pozostaje jedynie kolekcja znaków zaproponowana przez Grześka?

2

Kolekcja Grześka również należy do absolutnych podstaw C++ i pozwala w ładny sposób ominąć konieczność definiowania łańcuszka zależności w warunku. :-)

3

Masz wyżej odpowiedź, również od @grzesiek51114 - && zamiast || i poprawny warunek logiczny ;​)

Choć z punktu widzenia czytelności takiego kodu i szukania w nim błędów kolekcja jest wielokrotnie lepszym rozwiązaniem.

3

Mówiąc szczerze, kiedy widzę w kodzie produkcyjnym, wewnątrz if'a więcej niz 3 warunki to mnie krew zalewa. Zamiast zgrupować warunki w odpowiednie funkcje, które zwracają wartość logiczną, to do dziś pokutuje stara moda wciskania wszystkiego jak leci do if'a, z którego później nic już nie wiadomo.

Nie wiesz później czy te trzy warunku dotyczą np. stricte jakiejś sprzedaży, a tamte cztery kolejne np. naliczania wartości netto. Nie, bo nie... bo nie chciało się wsadzić ich do funkcji i odpowiednio ponazywać. Jestem szczególnie wyczulony na takie rzeczy, bo refaktoryzowałem taki kod wiele razy i już nie chcę tego robić. ;-)

0

O rany, że mi umknął ten spójnik chyba czas do spania ;)
Już wszystko jasne, dzięki raz jeszcze.

3

To ja jeszcze uczepię się jednej rzeczy:

cout<<"Zwroc uwage na wielkosc litery!"<<endl;

Serio użytkownik ma podawać literki z użyciem Shiftu? Wkurzysz go niepotrzebnie…

Powinieneś pobrać znak z klawiatury i użyć odpowiedniej funkcji do przerobienia małej litery na dużą. No i zastanów się też nad zmianą kodu pobierającego znak, tak aby wykluczyć też konieczność stukania w Enter. ;)

1

@furious programming: słusznie. @demonox: jeśli już jesteśmy przy czepianiu się to endl jest niepotrzebne tutaj. Zastosuj zamiast tego \n, bo endl czyści bufor bodajże, a jest to operacja kosztowna. Do tego jeszcze w pętli to sam rozumiesz.

0

@furious programming: @grzesiek51114
Tu wychodzi kolejne niedopatrzenie wykładowcy oraz prowadzącego zajęcia. Wykładowca we wszystkich slajdach na wykładach przedstawia endl'a, z kolei prowadzący wspomniał o "\n", ale powiedział że woli żebyśmy używali endl'a bo jest to bardziej przejrzyste.

0

Pytanie tylko po co? Po co, na przykładzie Twojego kodu, czyścić az trzy razy strumień skoro można użyć zwykłego znaku nowej linii?

W tym wątku na Stacku jest ciekawa dyskusja odnośnie wspomnianego tematu: https://stackoverflow.com/questions/213907/c-stdendl-vs-n

Oczywiście, zapewne w tak prostych i błahych programach nie ma to żadnego znaczenia, jednakże lepiej wiedzieć co i gdzie stosować. Tym bardziej, że operacje IO są dość kosztowne.

0

Stwierdziłem, że zamienie instrukcję warunkową na switch'e bo zrobił się straszny bałagan i pojawił się kolejne problemy. Pierwszy z nich, to że program jak już jest w case '1' i przy wprowadzeniu błędnych wartości nie wraca do "bet=getchar();" lecz do początku nieskończonej pętli - w tym przypadku wyświetla menu. Kolejnym błędem jest wchodzenie w default, po pierwszym wykonaniu całej pętli i wybraniu po raz kolejny case '1'

        cout<<"Co chcesz zrobic?\n";
        cout<<"1. Grac.\n";
        cout<<"2. Sprawdzic balans.\n";
        cout<<"3. Zasady.\n";
        cout<<"4. Zakonczyc gre.\n";
        x=getch();
        switch(x){
            case '1':
                {
                    system("cls");
                    cout<<"Co chcesz obstawic? [L/X/H]\n";
                    bet=getchar();
                    switch(bet){
                    case'l': case'L': case'H': case'h': case'x': case'X':
                    {

                    }
                    break;

                    default:
                            {
                            system("cls");
                            cout<<"Zla opcja! Jedyne mozliwe to: L/X/H\n";
                            cout<<"Co chcesz obstawic? [L/X/H]\n";
                            cout<<endl;
                            }
       
             }
                }
            break;

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