Problem med C++ (switch-satsar)

Permalänk
Medlem

Problem med C++ (switch-satsar)

Tjena, jag har lite problem med en script ifrån en uppgift. Det är ingen form av inlämningsuppgift utan något jag bara vill göra fel fritt så jag inte fortsätter göra fel i framtiden. Om du har tiden att kika igenom om vad jag har gjort så är du guld värd. Oroa er inte över mina if statements i slutet, de ska se ut så

https://pastebin.com/z6qsVtHW

Problem som uppstår:
När jag till exempel matar in temperaturen så dyker det jag skriver här under upp två gånger efter loopar tillbaka:

cout << "\n[M]ata in temperatur\n";
cout << "[S]kriv ut temperatur\n";
cout << "[A]vsluta programmet\n\n";

Sedan så skulle jag veta ifall någon har något tips om hur jag kan förhindra att man inte kan skriva flera alternativ på en gång. Helt enkelt att man inte kan skriva "mmmm", "MSAMSAMSAM" eller liknande.

Permalänk
Medlem

Aldrig använt c++ men verkar finnas något som heter _getch() som verkar göra det du vill: https://docs.microsoft.com/en-us/cpp/c-runtime-library/refere...

Visa signatur

Primär: R9 3900X | ASUS X570-F Gaming | NH-D15 | 64GB@3200MHz | RTX 3080 10GB | Seasonic 850W | Fractal Define R6 |
Gamla bettan: i5 750@3.8GHz | 8GB | HD5770 | Corsair VS 550W | FD R2 |

Permalänk
Festpilot 2020, Antiallo
Skrivet av Xuoi:

Tjena, jag har lite problem med en script ifrån en uppgift. Det är ingen form av inlämningsuppgift utan något jag bara vill göra fel fritt så jag inte fortsätter göra fel i framtiden. Om du har tiden att kika igenom om vad jag har gjort så är du guld värd. Oroa er inte över mina if statements i slutet, de ska se ut så

https://pastebin.com/z6qsVtHW

Problem som uppstår:
När jag till exempel matar in temperaturen så dyker det jag skriver här under upp två gånger efter loopar tillbaka:

cout << "\n[M]ata in temperatur\n";
cout << "[S]kriv ut temperatur\n";
cout << "[A]vsluta programmet\n\n";

Sedan så skulle jag veta ifall någon har något tips om hur jag kan förhindra att man inte kan skriva flera alternativ på en gång. Helt enkelt att man inte kan skriva "mmmm", "MSAMSAMSAM" eller liknande.

Varför inte mata in koden i forumet med hjälp av [code][/code]-taggar?

Visa signatur

 | PM:a Moderatorerna | Kontaktformuläret | Geeks Discord |
Testpilot, Skribent, Moderator & Geeks Gaming Huvudadmin

Permalänk
Hedersmedlem

Hej!

Utan att gå in på operativsystemspecifik funktionalitet går inte detta med standard C++. Allt är buffrat rad för rad. Det är också därför du kan t.ex. trycka på backspace för att redigera innan du trycker på Enter.

En enkel lösning som gör nästan det du vill är att läsa en hel rad, och sedan plocka ur första tecknet i raden som ditt kommando.

Så här till exempel:

#include <iostream> #include <string> #include <ctype.h> using namespace std; char read_command() { string line; char command = 0; do { getline(cin, line); if (line.length() == 1) command = toupper(line.at(0)); else cout << "Du måste skriva exakt ett tecken! Försök igen." << endl; } while (command == 0); return command; } int main(int, char **) { char command; do { cout << "Skriv ett kommando. Q avslutar." << endl; command = read_command(); cout << "Du har skrivit kommandot " << command << endl; } while (command != 'Q'); cout << "Avslutar!" << endl; return 0; }

Permalänk
Medlem
Skrivet av Daz:

Aldrig använt c++ men verkar finnas något som heter _getch() som verkar göra det du vill: https://docs.microsoft.com/en-us/cpp/c-runtime-library/refere...

Ska pröva, tack för att du svarade.

Skrivet av DavidtheDoom:

Varför inte mata in koden i forumet med hjälp av [code][/code]-taggar?

Jag tänkte på det men hittade ingen knapp och jag kunde de inte utan till. Tänkte också eftersom jag kunde ha det anpassat för c++ i pastebin så kunde det underlätta för alla att läsa det men nu har jag det i åtanke inför nästa gång. Tack så mycket!

Skrivet av pv2b:

Hej!

Utan att gå in på operativsystemspecifik funktionalitet går inte detta med standard C++. Allt är buffrat rad för rad. Det är också därför du kan t.ex. trycka på backspace för att redigera innan du trycker på Enter.

En enkel lösning som gör nästan det du vill är att läsa en hel rad, och sedan plocka ur första tecknet i raden som ditt kommando.

Så här till exempel:

#include <iostream> #include <string> #include <ctype.h> using namespace std; char read_command() { string line; char command = 0; do { getline(cin, line); if (line.length() != 1) { cout << "Du måste skriva exakt ett tecken! Försök igen." << endl; } else { command = toupper(line.at(0)); } } while (command == 0); return command; } int main(int, char **) { char command; do { cout << "Skriv ett kommando. Q avslutar." << endl; command = read_command(); cout << "Du har skrivit kommandot " << command << endl; } while (command != 'Q'); cout << "Avslutar!" << endl; return 0; }

Aa precis. Jag såg detta tidigare men det verkade lite komplicerat så jag försökte på andra alternativ. Ska ge detta ett försök.
Tack så mycket för hjälpen, uppskattat att ni alla tog er tid och skrev.

Permalänk
Hedersmedlem

Efter att jag tittar en gång till på din kod så har du missuppfattat hur switch-satsar fungerar, vilket kanske också leder till att det verkar som fler än ett kommando körs åt gången.

Du har skrivit din switch-sats så här: (Jag rensade upp lite radbrytningar och indenteringar så det är lättare att läsa.)

switch (inputChar) { case 'a': case 'A': { cout << "Programmet är nu avslutat.\n"; return 0; } case 'S': case 's': { cout << "Temperaturen är: " << temp; cout << "\n\n"; } case 'M': case 'm': { cout << "Mata in temperaturen: "; cin >> temp; cout << "\n\n"; if (temp < 17) { temp = 20; } else if(temp > 25) { temp = 20; } } }

Du har alltså använt krullparenteserna {} och föreställer dig därför att det ska markera början och slutet på din kod som hanterar varje fall. Men det är inte så switch-satsen funkar!

Krullparanteserna gör i själva verket ingenting i din kod. Det enda de gör är att skapa ett kodblock som du kan t.ex. definiera en lokal variabel i. Vilket du inte gör. Så vi kan ta bort dem och koden gör fortfarande exakt samma sak. Så här:

switch (inputChar) { case 'a': case 'A': cout << "Programmet är nu avslutat.\n"; return 0; case 'S': case 's': cout << "Temperaturen är: " << temp; cout << "\n\n"; case 'M': case 'm': cout << "Mata in temperaturen: "; cin >> temp; cout << "\n\n"; if (temp < 17) { temp = 20; } else if(temp > 25) { temp = 20; } }

Sättet switch-satsen funkar på är att den helt kodens körning "hoppar" in i den plats som matchar det specifika caset. Och det jävliga är att sedan FORTSÄTTER den, tills att något gör att den slutar.

I caset A så har du en "return"-sats vilket gör att funktionen avslutas där direkt, så där är det ok.

I caset M så kör du inte mer än du tänkt, för att det är sista caset i switchen.

Men för caset S så skriver du ut temperaturen, och sedan så fortsätter programmet in i fallet M. Vilket du kanske tolkar som att den kör fler kommandon än du tänkte dig. Här måste du slänga in en break-sats! Så här alltså:

switch (inputChar) { case 'a': case 'A': cout << "Programmet är nu avslutat.\n"; return 0; case 'S': case 's': cout << "Temperaturen är: " << temp; cout << "\n\n"; break; // Här är break-satsen som fattades! case 'M': case 'm': cout << "Mata in temperaturen: "; cin >> temp; cout << "\n\n"; if (temp < 17) { temp = 20; } else if(temp > 25) { temp = 20; } }

Så då har du fått två svar av mig. Ett svar på den fråga du faktiskt ställde, och ett till svar som jag tror faktiskt löser ditt problem.

Här kan du läsa lite mer om switchar och hur de funkar:

https://docs.microsoft.com/en-us/cpp/cpp/switch-statement-cpp...
https://www.w3schools.com/cpp/cpp_switch.asp

Samt lite överkurs om hur man kan missbruka switch-statements. (Oroa dig om du inte fattar. Det här är fulkod som inte är till för nybörjare.)

https://en.wikipedia.org/wiki/Duff%27s_device

Permalänk
Medlem

@Xuoi:
Testa mata in "cin.ignore()"
Om det fungerar så läs lite om cin i kontext med .ignore() funktionen

cout << "\n[M]ata in temperatur\n"; cout << "[S]kriv ut temperatur\n"; cout << "[A]vsluta programmet\n\n"; cin.get(inputChar); cout << "\n\n"; ..... cin.ignore(); <--- läggs in i slutet av din while loop

edit: cin.ignore() ska läggas i slutet, my bad

edit2:
"char M S A" används inte och din "bool aktiverad" används heller inte, kan lika gärna bara skriva while(true).
Såvida du inte tänker lägga in i koden "aktiverad = false" och lägga din "return 0" i slutet av main funktionen.

Lite saker att tänka på utanför själva syntax och programmering språket i sig, att din beskrivning av vad programmet ska göra och hur den ska göra, dess flöde, att det inte är genomtänkt

Permalänk
Hedersmedlem
Skrivet av HappyPie:

@Droxx1998:
Testa mata in "cin.ignore()"
Om det fungerar så läs lite om cin i kontext med .ignore() funktionen

cout << "\n[M]ata in temperatur\n"; cout << "[S]kriv ut temperatur\n"; cout << "[A]vsluta programmet\n\n"; cin.get(inputChar); cin.ignore(); cout << "\n\n";

Det där funkar inte, cin.ignore() läser exakt ett tecken från strömmen bara. Inte riktigt det han vill göra.

Något sånt här kanske funkar (inte testat) om man ska använda cin.ignore() för att äta upp alla tecken fram till en newline:

cin.ignore(numeric_limits<streamsize>::max(), '\n')

Lite referens: http://www.cplusplus.com/reference/istream/istream/ignore/

Permalänk
Medlem

@pv2b: la funktionen i fel rad, ska vara i slutet av while loop:en

Permalänk
Hedersmedlem
Skrivet av HappyPie:

@pv2b: la funktionen i fel rad, ska vara i slutet av while loop:en

Nä, det funkar inte. Testa själv så får du se

Permalänk
Medlem

@pv2b: fungerar för mig, mingw som kompilator

@Xuoi: Du bör lägga en break i slutet på sin case 's' sats, annars så går den till case 'm' direkt efter case 's'