Permalänk
Medlem

C++ switch-sats och loopar

Hej.

Jag behöver hjälp med en övningsuppgift som jag ska skriva ett program som simulerar en bank.
Man ska kunna sätta in pengar och ta ut pengar, samt kolla saldo.
Detta görs via en meny som jag ska göra med en switch-sats.

[I]nsättning
[U]ttag
[S]aldo
[A]vsluta

Jag har kommit en liten bit på vägen får till menyn och att man kommer till rätt undermeny men sen blir jag osäker hur jag ska t.ex när jag skrivit in min insättning hur kan jag då sedan läsa av den i saldo osv.
Så här långt har jag hunnit just nu.
Jag misstänker ju att jag behöver göra någon slags insättning

#include <iostream> using namespace std; int main() { while (true) { cout << "[I]ns\x84ttning\n"; //Här skriv det olika meny alternativen samt cout << "[U]ttag\n"; // vilken knapp man skall trycka på för att aktivera rätt meny. cout << "[S]aldo\n"; cout << "[A]vsluta\n"; char menyVal; cin >> menyVal; switch (menyVal) { case 'i': int nr1; cout << "ins\x84ttning: "; cin >> nr1; break; case 'u': int nr2; cout << "V\x84lj summa f\x94r uttag: "; cin >> nr2; break; case 's': int nr3; cout << "Ditt saldo ligger p\x86: "; cin >> nr3; break; case 'a': int nr4; cout << "Avslutar"; cin >> nr4; break; default: break; } }

Redigerat in [code]-taggar //Mod
Permalänk
Medlem

Tror jag förstår vad du frågar om, gjorde några ändringar och la till kommentarer:

#include <iostream> using namespace std; int main() { /* God sed är att alltid definera dina variabler längst upp, som du hade det innan så skulle varje variabel blivit återställd varje gång ett menyval gjordes */ int nr1; //Duger med denna variabel för inläsning, då den får ett nytt värde vid vaje cin. int saldo = 0; //Uppdateras genom insättningar och uttag while (true) { cout << "[I]ns\x84ttning\n"; //Här skriv det olika meny alternativen samt cout << "[U]ttag\n"; // vilken knapp man skall trycka på för att aktivera rätt meny. cout << "[S]aldo\n"; cout << "[A]vsluta\n"; char menyVal; cin >> menyVal; switch (menyVal) { case 'i': cout << "ins\x84ttning: "; cin >> nr1; saldo += nr1; //+= ger samma effekt som "saldo = saldo + nr1;" break; case 'u': cout << "V\x84lj summa f\x94r uttag: "; cin >> nr1; saldo -= nr1; break; case 's': cout << "Ditt saldo ligger p\x86: "; cout << saldo << "kr\n"; break; case 'a': cout << "Avslutar"; /* Du behöver nödvändigtvis inte läsa av någon input här return 0; duger (då avslutas programmet) */ return 0; default: break; } } }

Läs igenom och förstå ändringarna. Lämnar felhantering och dylikt till dig, vad händer om en användare tar ut pengar när saldo är 0 t.ex.?

Tips: lägg till "<code></code>" (ersätt < & > med [ & ]) runt din kod så presenteras den snyggare i inlägget

Permalänk
Medlem

@Poptart: Okej tack ska kolla lite mer imorgon. Jo jag är helt ny med programmering så alla bra tips uppskattas
Som du ska vill ju att det ska se bra ut också när man skrivit koden.

Permalänk
Hedersmedlem

En liten detalj att tänka på: 'i' och 'I' är olika tecken. Programmet skriver ut som om man ska ange versaler, men accepterar enbart gemener.
Du kan ha flera case-labels på rad för att ta hand om båda, t ex:

switch (menuVal) { case 'i': case 'I': // Hantera insättning ... }

Visa signatur

Asus ROG STRIX B550-F / Ryzen 5800X3D / 48 GB 3200 MHz CL14 / Asus TUF 3080 OC / WD SN850 1 TB, Kingston NV1 2 TB + NAS / Corsair RM650x V3 / Acer XB271HU (1440p165) / LG C1 55"
Mobil: Moto G200

Permalänk
Medlem

@Thomas: Om man vill ha lite intuition till varför det funkar kan man tänka sig "break;" som golvet, innan ett break faller man bara igenom "nedåt" så att säga

Permalänk
Medlem

@blewz: Väldigt förenklat så "lever" variabler bara inom ett scope, där ett scope definieras av { } i C++. D.v.s.:

{ // Här börjar ett nytt scope. // Här definieras en variabel 'i' i detta scope. // Varje gång du kommer in i detta scope så skapas en ny variabel 'i'. int i; cin >> i; } // Här slutar scopet, och variabeln 'i' upphör att existera.

Så dina variabler som du deklarerat i switch-satsen kommer glömmas bort så fort du går ur switch-satsen, och lösningen är därför som Poptart visar att deklarera variabler utanför switch-satsen.

Lite överkurs när det gäller just switch-satser är för övrigt att { }-regeln gäller även där, så detta är t.ex. giltigt (men inte rekommenderat ):

switch (var) { int a; case 1: int i; break; int b; case 2: i = 4; // Använder i från ovanstående case. break; int c; }

D.v.s. all kod i en switch-sats ligger i samma scope, och case markerar bara vart switch-satsen ska hoppa (se Duff's device för hur man missbrukar detta ). Problemet med detta är att en switch-sats kan hoppa över kod, så när du senare börjar med t.ex. klasser så kommer du få problem om du deklarerar variabler på detta sätt. D.v.s.:

switch (var) { case 1: SomeClass c; // Kompileringsfel, ett hopp till case 2 skulle hoppa över initialiseringen av c. break; case 2: ... }

Lösningen är att helt enkelt introducera ett nytt scope:

switch (var) { case 1: { SomeClass c; // Ok, nu ligger c i ett eget scope och kan endast användas i detta case. } break; case 2: ... }

Permalänk

Som perost nämner så är scopes en viktig sak att förstå inom programmering

Skulle rekommendera att läsa på om det och förstå hur det fungerar

Permalänk
Medlem

@Poptart: I modern C++ tror jag det rekommenderas att man deklarerar och initierar variabler där de används. Mer C-stil att ta dem i en klump i början. Sen när det gäller input-variablerna så spelar det ingen roll att de försvinner efter varje iteration genom switch-loopen eftersom de då redan använts för att uppdatera summan. Det kan nästan vara bättre att låta dem försvinna per case eftersom det ger kompilatorn mer koll på hur variabeln faktiskt används.

Visa signatur

.<

Permalänk
Medlem

@oelrich: Sitter för det mesta och kör C, antar att annat än variabler längst upp sticker lite i ögonen Men ja, blir väl som du och andra säger mer logiskt att deklarera in-scope!

Permalänk
Medlem

Tack så mycket för alla bra tips och råd. Nu gäller det bara att jag lär mig något av allt detta också känner mig väldigt taggad för att lära mig dock är det tid som det brister på.

ps.
Sweclockers forum känner mig sig verkligen omhändertagen i verkligen ett plus i kanten!

Tänkte bara posta lösningen jag fick av läraren. Tänkte höra vad ni tycker om den ?
Den skrevs ju på lite annat sätt än hur jag började min med. Men förstår väl att det går att lösa uppgifterna på många olika sätt.
Det jag märkte med de programmet är ju att det användes inga t.ex int nr1 som jag skrev i cases där togs int bort helt.

#include <iostream> #include <clocale> using namespace std; int main() { setlocale (LC_ALL,"swedish"); char val; float saldo = 1000, insattning, uttag; cout << "***EN MENY*** \n \n"; cout << "[I]nsättning \n"; cout << "[U]ttag \n"; cout << "[S]aldo \n"; cout << "[A]vsluta \n"; cout << "Ditt val: "; cin >> val; switch(val){ case 'I': cout << "Hur mycket pengar vill du sätta in? "; cin >> insattning; saldo += insattning; break; case 'U': cout << "Hur mycket pengar vill du ta ut? "; cin >> uttag; saldo -= uttag; if(saldo < 0) { cout << "Du kan inte ta ut ett belopp som är större än aktuellt saldo \n"; } break; case 'S': cout << "Ditt saldo blir nu " << saldo << endl; break; case 'A': cout << "Hej då " << saldo << endl; break; default: cout << "Du har gjort ett fel val "; } return 0; }

Permalänk

Nä precis som du säger, programmet har inga ints i switch casen.

Programmet skapar istället 3 float variabler i början (float för att kunna ha t.ex ören etc, eftersom float är ett decimal tal ). saldo (som han ger ett startvärde på 1000), insattning samt uttag.

Programmet ger insattning och uttag nya värden i de olika casen (beroende på vilket case) samt använder det tillfälliga värdet för att öka och minska saldo

Väldigt intressant att den inte har någon while loop though

Permalänk
Medlem

C++ switch-sats och loopar

Hej!
Jag vet inte om koden är helt rätt, men det kan vara ett litet hjälp.( i alla fall funkar)
#include <iostream>

using namespace std;

int main ()
{
int saldo = 10000;
int nr1, nr2, nr3;
char menySelection; //Skrivs bara en gång.

do
{
//Meny:
cout << "Välj: " << endl;
cout << "[I]nsättningt" << endl;
cout << "[U]ttag" << endl;
cout << "[S]aldo" << endl;
cout << "[A]vsluta" << endl;

cin >> menySelection;

switch (menySelection)
{
case 'i':

cout << "Ange hur mycket du vill sätta in: " << endl;
cin >> nr1;
saldo += nr1;
break;

case 'u':

cout << "Ange hur mycket du vill ta ut: " << endl;
cin >> nr2;
saldo -= nr2;
break;

if (saldo < 0)
{
cout << "Du kan inte ta ut pengar." << endl;// Kod funkar utan if-sats.
}
case 's':

cout << "Ditt saldo är: " << saldo << "kr." << endl;
break;

case 'a':

cout << " " << endl;
break;

default:
cout << "DU har gjort ett fel val " << endl;
break;

}

}

while (menySelection != 'a');
{
cout << "Program avslutar!" << endl;
}

system ("pause");
return 0;

}

Permalänk
99:e percentilen

@blewz: Nu har du visat ett program som bara förstår gemener och ett som bara förstår versaler som input från användaren. @Thomas är inne på detta, men jag skulle definitivt säga att kod som

switch (val) { case 'i': case 'I': // Hantera insättning ... }

bryter mot grundprincipen Don't Repeat Yourself (DRY). Koden ovan kräver två ändringar för att ändra en sak. Utgångsläget vid programmering bör alltid vara att sträva efter att skriva vad man menar™, och jag vill hävda att det man som programmerare menar™ här, det är inte "om användaren skriver i eller om användaren skriver I", utan snarare "om användaren skriver bokstaven I, oavsett skiftläge". Därför föreslår jag istället följande:

switch (toupper(val)) { case 'I': // Hantera insättning ... }

(Observera att detta ej ändrar värdet på val, utan det enda jag gör är att jag väljer case baserat på toupper(val) istället för val. Variabeln val kommer alltså även i fortsättningen representera exakt vad användaren skrev in.)

Visa signatur

Skrivet med hjälp av Better SweClockers

Permalänk
Medlem

@k9797tt @Alling: Tråden är två år gammal...

Permalänk
99:e percentilen
Skrivet av perost:

@k9797tt @Alling: Tråden är två år gammal...

Oj, det såg jag inte. Men då får alla som läser den från och med nu ett bra tips.

Visa signatur

Skrivet med hjälp av Better SweClockers

Permalänk
Medlem

@perost: Jag vet att det är 2 år gammal. Men de som söker svaret kan de behöva.
Tack för tipsen!
Om jag skriver switch (toupper(menySelection))
{..} då funkar inte programet. Fotfarande behövs att skriva case 'i' och case'I'.... annars programet skriver ut Du har gjort ett fel val.
Don't reapet yourself, jag fattar vad du mennar. Det kan vara skönt om det inte skriver ut Meny varje gång. HAr du eller/någon annan tips?

Permalänk
99:e percentilen
Skrivet av k9797tt:

Om jag skriver switch (toupper(menySelection))
{..} då funkar inte programet. Fotfarande behövs att skriva case 'i' och case'I'.... annars programet skriver ut Du har gjort ett fel val.

Problemet är att dina case-uttryck fortfarande är 'i', 'u' osv. Du måste välja ett av två sätt:

toupper och 'I'

switch (toupper(val)) { case 'I': // Hantera insättning // … }

tolower och 'i'

switch (tolower(val)) { case 'i': // Hantera insättning // … }

Om du blandar de två sätten som jag förstår att du gjort i din kod kommer inget case någonsin att matcha: 'i' kan aldrig matcha toupper(x), vad x än är.

Tänk för övrigt på att slå in kod i [code]-taggar på forumet, annars blir det svårt att läsa den. Exempel:

[code]
int a = 1;
[/code]

Visa signatur

Skrivet med hjälp av Better SweClockers

Permalänk
Medlem

@Alling: Tack för tipsen!