Forumdelen sponsras av

Hjälp med C# kodning, har jag missat något?

Trädvy Permalänk
Medlem
Registrerad
Maj 2012

Hjälp med C# kodning, har jag missat något?

Hej, har gjort ett litet program här nedan där man skall gissa på ett tal som slumpats fram.

Skulle vara väldigt tacksam om någon kunde guida mig i rätt riktning, är ny inom programmering och känner mig lite lost. Programmet nedan är testat och fungerar som det ska, men jag undrar vad man skulle kunna snygga till?

* Struktur i koden - Vad i koden är onödigt, hur kan man korta ned och snygga till koden? Känns som att den blev lite lång.
(Gärna länktips mer djupgående tips om varför ett visst sätt är att föredra.)

* Eventuella kommentarer - Av min uppfattning är det främst för att hitta tillbaka i koden, samt för att visa förståelse för de olika datatyperna, loopar, m.m.? Anses det vara nödvändigt i detta program?

* Skulle man kunna skapa detta program med flera klasser, metoder m.m. eller vad är att föredra?

Console.WriteLine("Välkommen till gissa-numret."); Random randomerare = new Random(); int rand_num = randomerare.Next(1, 101), guesses = 1; Console.WriteLine("Gissa på ett tal mellan 1 och 100"); string input = Console.ReadLine(); int num = Convert.ToInt32(input); if (num != rand_num) { Console.WriteLine("Fel, gissa igen!"); } else if(num > 100 || num < 0) { Console.WriteLine("Du gissade på ett ogiltigt tal, gränsen är 1-100!"); } do { input = Console.ReadLine(); num = Convert.ToInt32(input); guesses++; if (num > 100 || num < 0) { Console.WriteLine("Du gissade på ett ogiltigt tal, gränsen är 1-100!"); } else if (num < rand_num) { Console.WriteLine("Talet är större!"); } else if(num > rand_num) { Console.WriteLine("Talet är mindre!"); } } while (num != rand_num); Console.WriteLine("Grattis, du gissade rätt!"); Console.WriteLine("Du gissade " + guesses + " gånger totalt, bra jobbat!"); Console.ReadKey();

Dold text
Trädvy Permalänk
Medlem
Plats
Helsingborg
Registrerad
Jan 2015

Eftersom du använder en do-while så kommer du alltid köra loopen minst en gång, och kan därmed plocka bort dessa rader:

string input = Console.ReadLine(); int num = Convert.ToInt32(input); if (num != rand_num) { Console.WriteLine("Fel, gissa igen!"); } else if(num > 100 || num < 0) { Console.WriteLine("Du gissade på ett ogiltigt tal, gränsen är 1-100!"); }

Visst skulle man kunna göra en variant med klasser, men jag har iaf. lärt man att man ska inte göra saker för komplicerade bara för att man kan. Ju enklare lösning med så få rader kod som möjligt är alltid att föredra. Det finns grejer objektorienterad programmering är bra för, men även grejer det är rätt dåligt för.

Kommentera sin kod är främst för att andra som ska jobba med din kod snabbt kan få en förståelse för hur du har tänkt, och vad de olika metoderna/klasserna gör. Inte helt fel att åtminstone lägga en kommentar per klass, och eventuellt någon liten rad på de större metoderna.

Trädvy Permalänk
Medlem
Registrerad
Maj 2012
Skrivet av elBenko:

Underbart, stort tack för hjälpen.

Okej, så en kommentar vid klasshuvudet i stil med detta bör räcka?

"Programmet slumpar fram ett tal och ber användaren att gissa inom ett visst intervall."
"När användaren gissar rätt så stannar programmet och en textsträng skickas ut på skärmen med gratulationer och besked om antalet gissningar."

Trädvy Permalänk
Medlem
Plats
Helsingborg
Registrerad
Jan 2015

@Mattiays: Ja typ så, behöver inte ens vara så propert och utförligt beskrivet. Vad som är viktigt för andra att veta om dina metoder/klasser är i princip:
1. vilka värden behövs skickas in, dvs. värdetyp, värdeintervall osv
2. kortfattat vad din metod/klass gör med datan. (beräkning? sortering? konvertering?) etc.
3. vilka värden returneras, dvs. värdetyp osv.

Efterhand som du börjar "låna" in andras metoder/klasser i dina egna projekt så kommer du få en rätt bra hum om vad kommentaren bör innehålla, eftersom du kommer ha frågor i huvudet om hur du ska använda de olika metoderna/klasserna. Ibland saknas dokumentation och då får man helt enkelt gå igenom källkoden själv och se vad den gör för att få en förståelse.

Trädvy Permalänk
Medlem
Plats
#Archlinux
Registrerad
Jun 2007

Värt att nämna är att använda doc taggar ovanför metoder/klasser för att förklara respektive metod/klass.

C# använder exempelvis:
du skriver /// ovanför funktionen så kommer nedanstående som du kan fylla in sen.

/// <summary> /// Le Function /// </summary> /// <param name="value">Object Age</param> /// <param name="obj">ClientObj</param> /// <returns>if success</returns> private bool myFunction(int value, object obj)

Använder man någorlunda bra IDE så brukar dessa läsa detta och visa en liten popup (med det du skrivit och vilka variabler den tar in och vad den returnerar) när du försöker anropa en metod eller använda en klass.

Mycket smidigt om man sitter och skall dela funktioner/klasser och slippa hoppa in i koden för att förstå vad den gör eller om man vill exportera sedan dokumentation på koden till en egen fil, detta är enligt mig programmering 101.

Sedan lägga in korta kommentarer lite här och var är mest för att du om 5, 12, 36 månader senare skall hoppa in i koden och förstå den utan att börja granska rad för rad, speciellt när man har underbarn som sätter int värden för olika "typer" istället för enums och man hoppar in i koden flera månader senare och bara kliar sig i huvudet vad int 36 betyder i just detta sammanhanget.

+exempel

Arch - Makepkg, not war -||- Asus Crosshair Hero VI -||- GSkill 16GiB DDR4 15-15-15-35-1T 3600Mhz -||- AMD 1600x @ 4.1GHz -||- nVidia MSI 970 Gaming -||- Samsung 850 Pro -||- EVEGA G2 750W -||- Corsair 570x -||- Asus Xonar Essence STX -||- Sennheiser HD-650 -||
Arch Linux, one hell of a distribution.

Trädvy Permalänk
Moderator
Registrerad
Aug 2007
Skrivet av Mattiays:

Underbart, stort tack för hjälpen.

Okej, så en kommentar vid klasshuvudet i stil med detta bör räcka?

"Programmet slumpar fram ett tal och ber användaren att gissa inom ett visst intervall."
"När användaren gissar rätt så stannar programmet och en textsträng skickas ut på skärmen med gratulationer och besked om antalet gissningar."

Använd en standard för att lägga in beskrivande kommentarer. Ställ dig på raden ovanför det du vill beskriva och skriv ///. Du bör få en template att fylla i. Gör du så kan olika program läsa dina kommentarer på ett strukturerat sätt och samla ihop dem till dokumentation, använda dem som inline hjälp osv.

Använd gilla för att markera nyttiga inlägg!

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Jan 2004
Skrivet av Mattiays:

[code]
if (num > 100 || num < 0)
{
Console.WriteLine("Du gissade på ett ogiltigt tal, gränsen är 1-100!");
}

Ett litet påpekande. Ovanstående påstående/kod är felaktigt. Du kan gissa "0" utan att få felmeddelandet.

Trädvy Permalänk
Medlem
Registrerad
Maj 2012
Skrivet av iXam:

Ett litet påpekande. Ovanstående påstående/kod är felaktigt. Du kan gissa "0" utan att få felmeddelandet.

Snyggt, satt precis med den uppe och kunde åtgärda det. Tusen tack!!

Skrivet av elBenko:

@Mattiays: Ja typ så, behöver inte ens vara så propert och utförligt beskrivet. Vad som är viktigt för andra att veta om dina metoder/klasser är i princip:
1. vilka värden behövs skickas in, dvs. värdetyp, värdeintervall osv
2. kortfattat vad din metod/klass gör med datan. (beräkning? sortering? konvertering?) etc.
3. vilka värden returneras, dvs. värdetyp osv.

Efterhand som du börjar "låna" in andras metoder/klasser i dina egna projekt så kommer du få en rätt bra hum om vad kommentaren bör innehålla, eftersom du kommer ha frågor i huvudet om hur du ska använda de olika metoderna/klasserna. Ibland saknas dokumentation och då får man helt enkelt gå igenom källkoden själv och se vad den gör för att få en förståelse.

Skrivet av Commander:

Värt att nämna är att använda doc taggar ovanför metoder/klasser för att förklara respektive metod/klass.

C# använder exempelvis:
du skriver /// ovanför funktionen så kommer nedanstående som du kan fylla in sen.

/// <summary> /// Le Function /// </summary> /// <param name="value">Object Age</param> /// <param name="obj">ClientObj</param> /// <returns>if success</returns> private bool myFunction(int value, object obj)

Använder man någorlunda bra IDE så brukar dessa läsa detta och visa en liten popup (med det du skrivit och vilka variabler den tar in och vad den returnerar) när du försöker anropa en metod eller använda en klass.

Har du någon länk med mer djupgående information kring detta?

Skrivet av giplet:

Använd en standard för att lägga in beskrivande kommentarer. Ställ dig på raden ovanför det du vill beskriva och skriv ///. Du bör få en template att fylla i. Gör du så kan olika program läsa dina kommentarer på ett strukturerat sätt och samla ihop dem till dokumentation, använda dem som inline hjälp osv.

Jag känner mig riktigt lost i det här med kommentarer i koden, jag testar att lägga upp de tre program jag skrivit för tillfället, inklusive kommentarer så får ni gärna hjälpa mig på spåret!

Slumptalet:

//Initiation av variabler samt lokal variabel.

Console.WriteLine("Välkommen till gissa-numret."); Random randomerare = new Random(); int rand_num = randomerare.Next(1, 101), guesses = 0, num; Console.WriteLine("Gissa på ett tal mellan 1 och 100");

Dold text

//kontroll av tal mot slumptal

do { num = Convert.ToInt32(Console.ReadLine()); guesses++; if (num > 100 || num <= 0) { Console.WriteLine("Du gissade på ett ogiltigt tal, gränsen är 1-100!"); } else if (num < rand_num) { Console.WriteLine("Talet är större!"); } else if (num > rand_num) { Console.WriteLine("Talet är mindre!"); } } while (num != rand_num);

Dold text

//Kontroll av antalet gissningar. Samt avslut av program.

if (guesses < 5) { Console.WriteLine("Grattis, du gissade rätt! Du belönas med en osynlig guldmedalj!!"); Console.WriteLine("Du gissade " + guesses + " gånger. Mycket bra jobbat!!"); } else if(guesses >= 5 && guesses <= 10) { Console.WriteLine("Grattis, du gissade rätt! Du belönas med en osynlig silvermedalj!"); Console.WriteLine("Du gissade " + guesses + " gånger totalt, bra jobbat!"); } else { Console.WriteLine("Grattis, du gissade rätt! Du belönas med en osynlig bronsmedalj!"); Console.WriteLine("Du gissade " + guesses + " gånger totalt, bra jobbat!"); } Console.ReadKey();

Dold text
Dold text

Pensionskollen:

/// Krav: inmatning av namn, efternamn samt ålder.

Console.WriteLine("Välkommen till pensionskollen!"); Console.Write("Mata in ditt förnamn: "); string name = Console.ReadLine(); //förnamn sparas ned i variabel name Console.Write("Mata in ditt efternamn: "); string lastName = Console.ReadLine(); //efternamn sparas ned i variabel lastName Console.Clear(); int retAge = 65; //fräscha upp konsollen. Console.WriteLine("Hej " + name + " " + lastName + ", hur gammal är du? "); int age = int.Parse(Console.ReadLine()); int sum = retAge - age; // beräkning av ålder kvar till pension. Console.Clear();

Dold text

// Ålder kontrolleras mot villkoren för pension samt trovärdighet av inmatad ålder.

if (age >= 3 && age < 65) //villkor 1 { Console.WriteLine(name + " " + lastName + ", du har " + sum + " år kvar till pensionen."); } else if (age >= 65 && age <= 112) //villkor 2 { Console.WriteLine(name + " " + lastName + ", du gick i pension för cirka " + (-sum) + " år sedan."); } else if (age < 0 || age >= 113) //villkor 3 (ogiltigt val). { Console.WriteLine("Det verkar som att du matat in ett ogiltigt värde."); Console.WriteLine("Den äldsta människan i världshistorien, fransyskan Jeanne Calment, blev drygt 122 år gammal!"); Console.WriteLine("Den äldsta människan i svensk historia, Astrid Zachrison, blev 113 år och dog på sin födelsedag."); Console.WriteLine("Antingen har du matat in ett värde över 113 år, eller ett värde som understiger åldern 0 år."); Console.WriteLine("Jag kan inte hantera dessa värden. Försök igen!"); } Console.ReadKey();

Dold text
Dold text

Avrundaren:

double num; int decAmount; Console.WriteLine("Mata in ett krångligt decimaltal: "); num = Convert.ToDouble(Console.ReadLine()); //Endast siffror kan matas in. Console.WriteLine("Hur många decimaler vill du att jag avrundar till? (Max 15 decimaler)"); decAmount = Convert.ToInt32(Console.ReadLine()); //Endast heltal kan matas in. Console.Clear(); //Som det står, så töms konsollen. //Utskrift av valt decimaltal, valt antal decimaler, samt automatiskt avrundat till två decimaler. Console.WriteLine("Du matade in talet: " + num + "."); Console.WriteLine("Du valde att avrunda till " + decAmount + " decimaler."); Console.WriteLine("Då blir det: " + Math.Round(num, decAmount)); Console.WriteLine("Automatiskt avrundat till: " + Math.Round(num, 2)); Console.ReadKey();

Dold text
Trädvy Permalänk
Entusiast
Testpilot
Plats
Chalmers
Registrerad
Aug 2011
Skrivet av Mattiays:

if (age >= 3 && age < 65) //villkor 1 { Console.WriteLine(name + " " + lastName + ", du har " + sum + " år kvar till pensionen."); } else if (age >= 65 && age <= 112) //villkor 2 { Console.WriteLine(name + " " + lastName + ", du gick i pension för cirka " + (-sum) + " år sedan."); } else if (age < 0 || age >= 113) //villkor 3 (ogiltigt val). { Console.WriteLine("Det verkar som att du matat in ett ogiltigt värde."); Console.WriteLine("Den äldsta människan i världshistorien, fransyskan Jeanne Calment, blev drygt 122 år gammal!"); Console.WriteLine("Den äldsta människan i svensk historia, Astrid Zachrison, blev 113 år och dog på sin födelsedag."); Console.WriteLine("Antingen har du matat in ett värde över 113 år, eller ett värde som understiger åldern 0 år."); Console.WriteLine("Jag kan inte hantera dessa värden. Försök igen!"); } Console.ReadKey();

Jag kan ge dig alldeles fantastiska tips och råd.

  1. Vad händer i din kod om age == 2 till exempel? Och varför jämför du med 3 överhuvudtaget? Vilket för oss vidare till …

  2. … magiska tal. Varför dyker 3, 65 och 113 – för att inte tala om 112 – upp helt plötsligt? Varifrån kommer de; vad har de för betydelse och syfte? (0 är uppenbar, så den är OK.) Detta är också starkt relaterat till …

  3. … upprepad data. Vilka ändringar behöver du göra om pensionsåldern ändras till 70 år eller om det blir vanligt att bli äldre än 113? Kan du vara säker på att du i den situationen ändrar alla 65 till 70? Kan du vara säker på att du ändrar 112 till 115 om du ändrar 113 till 116? Kanske finns det till och med ett 112 eller 113 som inte ska ändras, för att det inte har något att göra med maxåldern. Jag har rödmarkerat några uttryck ovan. Dem bör du lägga i konstanter högst upp i filen eller så, kanske vid namn i stil med RETIREMENT_AGE och MAX_AGE. DRY är en väldigt viktig princip inom programmering.

  4. Tänk på vad du egentligen menar när du skriver kod. Du har skrivit age <= 112, men det du menar är ju age < 113. (Och det borde som sagt vara age < MAX_AGE eller dylikt, enligt ovan.)

Alla mina tips är direkt sprungna ur att jag själv begått precis de misstagen, och det är helt naturligt att man gör det under sin utveckling som programmerare. Det viktiga är att man inte struntar i dem när man väl får lära sig att de finns.

5930K • Corsair DP 32 GiB • EVGA GTX 980 • 2x Swift PG278Q
Better SweClockersDisplayPort över USB-C

Köp processor för framtiden™, men inte grafikkort.

Trädvy Permalänk
Medlem
Registrerad
Maj 2012
Skrivet av Alling:

Jag kan ge dig alldeles fantastiska tips och råd.

  1. Vad händer i din kod om age == 2 till exempel? Och varför jämför du med 3 överhuvudtaget? Vilket för oss vidare till …

  2. … magiska tal. Varför dyker 3, 65 och 113 – för att inte tala om 112 – upp helt plötsligt? Varifrån kommer de; vad har de för betydelse och syfte? (0 är uppenbar, så den är OK.) Detta är också starkt relaterat till …

  3. … upprepad data. Vilka ändringar behöver du göra om pensionsåldern ändras till 70 år eller om det blir vanligt att bli äldre än 113? Kan du vara säker på att du i den situationen ändrar alla 65 till 70? Kan du vara säker på att du ändrar 112 till 115 om du ändrar 113 till 116? Kanske finns det till och med ett 112 eller 113 som inte ska ändras, för att det inte har något att göra med maxåldern. Jag har rödmarkerat några uttryck ovan. Dem bör du lägga i konstanter högst upp i filen eller så, kanske vid namn i stil med RETIREMENT_AGE och MAX_AGE. DRY är en väldigt viktig princip inom programmering.

  4. Tänk på vad du egentligen menar när du skriver kod. Du har skrivit age <= 112, men det du menar är ju age < 113. (Och det borde som sagt vara age < MAX_AGE eller dylikt, enligt ovan.)

Alla mina tips är direkt sprungna ur att jag själv begått precis de misstagen, och det är helt naturligt att man gör det under sin utveckling som programmerare. Det viktiga är att man inte struntar i dem när man väl får lära sig att de finns.

Ovärderligt svar, riktigt bra tips! Håller med dig till fullo, en ny häst anslöts till stallet så att säga! Hade helt klart blivit ett helvete att ändra om varje liten variabel till ett nytt eventuellt värde. Jag snyggade till det nu med dina tips, och initierade variabler längst upp i koden vilket bör göra det smidigt att justera vid, som du säger, eventuella förändringar av verkliga värden.

Del 1 - Pensionen //Bör det adderas någon kommentar i denna kod? Alt. tas bort någon kanske?

int RETIREMENT_AGE, MAX_AGE, MIN_AGE; RETIREMENT_AGE = 65; MAX_AGE = 112; MIN_AGE = 0; Console.WriteLine("Välkommen till pensionskollen!"); Console.Write("Mata in ditt förnamn: "); string NAME = Console.ReadLine(); //förnamn sparas ned i variabel name Console.Write("Mata in ditt efternamn: "); string LAST_NAME = Console.ReadLine(); //efternamn sparas ned i variabel lastName Console.Clear(); //fräscha upp konsollen.

Dold text

Del 2 - Pensionen //Onödiga kommentarer/avsaknad av rimliga kommentarer?

Console.WriteLine("Hej " + NAME + " " + LAST_NAME + ", hur gammal är du? "); int AGE = int.Parse(Console.ReadLine()); int SUM = RETIREMENT_AGE - AGE; // beräkning av ålder kvar till pension. Console.Clear(); if (AGE >= MIN_AGE && AGE < RETIREMENT_AGE) //villkor 1 { Console.WriteLine(NAME + " " + LAST_NAME + ", du har " + SUM + " år kvar till pensionen."); } else if(AGE == RETIREMENT_AGE) { Console.WriteLine(NAME + " " + LAST_NAME + ", i år gick du förmodligen i pension."); } else if (AGE > RETIREMENT_AGE && AGE <= MAX_AGE) //villkor 2 { Console.WriteLine(NAME + " " + LAST_NAME + ", för cirka " + (-SUM) + " år sedan gick du i pension."); } else if (AGE < MIN_AGE || AGE >= MAX_AGE) //villkor 3 (ogiltigt val). { Console.WriteLine("Det verkar som att du matat in ett ogiltigt värde."); Console.WriteLine("Den äldsta människan i världshistorien, fransyskan Jeanne Calment, blev drygt 122 år gammal!"); Console.WriteLine("Den äldsta människan i svensk historia, Astrid Zachrison, blev 113 år och dog på sin födelsedag."); Console.WriteLine("Antingen har du matat in ett värde över 113 år, eller ett värde som understiger åldern 0 år."); Console.WriteLine("Jag kan inte hantera dessa värden. Försök igen!"); } Console.ReadKey();

Dold text
Dold text
Trädvy Permalänk
Entusiast
Testpilot
Plats
Chalmers
Registrerad
Aug 2011
Skrivet av Mattiays:

Ovärderligt svar, riktigt bra tips! Håller med dig till fullo, en ny häst anslöts till stallet så att säga! Hade helt klart blivit ett helvete att ändra om varje liten variabel till ett nytt eventuellt värde. Jag snyggade till det nu med dina tips, och initierade variabler längst upp i koden vilket bör göra det smidigt att justera vid, som du säger, eventuella förändringar av verkliga värden.

int RETIREMENT_AGE, MAX_AGE, MIN_AGE; RETIREMENT_AGE = 65; MAX_AGE = 112; MIN_AGE = 0; Console.WriteLine("Välkommen till pensionskollen!"); Console.Write("Mata in ditt förnamn: "); string NAME = Console.ReadLine(); //förnamn sparas ned i variabel name Console.Write("Mata in ditt efternamn: "); string LAST_NAME = Console.ReadLine(); //efternamn sparas ned i variabel lastName Console.Clear(); //fräscha upp konsollen. Console.WriteLine("Hej " + NAME + " " + LAST_NAME + ", hur gammal är du? "); int AGE = int.Parse(Console.ReadLine()); int SUM = RETIREMENT_AGE - AGE; // beräkning av ålder kvar till pension. Console.Clear(); if (AGE >= MIN_AGE && AGE < RETIREMENT_AGE) //villkor 1 { Console.WriteLine(NAME + " " + LAST_NAME + ", du har " + SUM + " år kvar till pensionen."); } else if(AGE == RETIREMENT_AGE) { Console.WriteLine(NAME + " " + LAST_NAME + ", i år gick du förmodligen i pension."); } else if (AGE > RETIREMENT_AGE && AGE <= MAX_AGE) //villkor 2 { Console.WriteLine(NAME + " " + LAST_NAME + ", för cirka " + (-SUM) + " år sedan gick du i pension."); } else if (AGE < MIN_AGE || AGE >= MAX_AGE) //villkor 3 (ogiltigt val). { Console.WriteLine("Det verkar som att du matat in ett ogiltigt värde."); Console.WriteLine("Den äldsta människan i världshistorien, fransyskan Jeanne Calment, blev drygt 122 år gammal!"); Console.WriteLine("Den äldsta människan i svensk historia, Astrid Zachrison, blev 113 år och dog på sin födelsedag."); Console.WriteLine("Antingen har du matat in ett värde över 113 år, eller ett värde som understiger åldern 0 år."); Console.WriteLine("Jag kan inte hantera dessa värden. Försök igen!"); } Console.ReadKey();

Mycket bättre!

Ett par saker till:

  1. Versaler brukar bara användas till konstanter som "är en del av själva programmet" – sådana som programmeraren definierar istället för hårdkodade magiska tal (eller strängar etc) för att göra koden begriplig och maintainable. "Vanliga variabler", som name, age och sum, bör skrivas med små bokstäver.

  2. Det är alltid bra att fundera över logik man skrivit. Är den verkligen korrekt? Är den redundant*? En varningsflagga i det här fallet är att det inte finns en ren else-sats i slutet av dina if … else if …, trots att samtliga möjliga värden på age borde resultera i någon form av output. Antingen finns det ett fall som inte matchas av någon av if-satserna eller så finns det redundant logik någonstans.

  3. Du glömde ett 113.

* Här är ett enkelt exempel på redundant logik:

if (x > 5) { // ... } else if (x <= 5) { // ... }

5930K • Corsair DP 32 GiB • EVGA GTX 980 • 2x Swift PG278Q
Better SweClockersDisplayPort över USB-C

Köp processor för framtiden™, men inte grafikkort.

Trädvy Permalänk
Medlem
Registrerad
Maj 2012
Skrivet av Alling:

Mycket bättre!

Ett par saker till:

  1. Versaler brukar bara användas till konstanter som "är en del av själva programmet" – sådana som programmeraren definierar istället för hårdkodade magiska tal (eller strängar etc) för att göra koden begriplig och maintainable. "Vanliga variabler", som name, age och sum, bör skrivas med små bokstäver.

  2. Det är alltid bra att fundera över logik man skrivit. Är den redundant*? En varningsflagga i det här fallet är att det inte finns en ren else-sats i slutet av dina if … else if …, trots att samtliga möjliga värden på age borde resultera i någon form av output. Antingen finns det ett fall som inte matchas av någon av if-satserna eller så finns det redundant logik någonstans.

  3. Du glömde ett 113.

* Här är ett enkelt exempel på redundant logik:

if (x > 5) { // ... } else if (x <= 5) { // ... }

1. Fixade till det nu!
2. Vet inte om jag hängde på detta, men jag antar att du ansåg att "else if(age == retAge)" är väldigt redundant, så jag flyttade den till else-satsen. Det kändes som att den passar in bättre där.

Slänger in mina tankegångar kring if-satsen här i koden, är det i rätt riktning?

Del 2 - Pension

Här kan det anses redundant, om jag tolkar dig rätt, med större/lika med 0, men utan det så hoppar värdet 0 till villkor 2. Samt 65 är inte tillåtet här.

if (age >= minAge && age < retirementAge) //villkor 1 { Console.WriteLine(name + " " + lastName + ", du har " + sum + " år kvar till pensionen."); }

Dold text

Här tänker jag att jag inte tillåter värden under 65 år, samt värden över 113 år.

else if (age > retirementAge && age < maxAge) //villkor 2 { Console.WriteLine(name + " " + lastName + ", för cirka " + (-sum) + " år sedan gick du i pension."); }

Dold text

Här tänker jag att jag inte tillåter värden under 0 år, samt värden över 113 år.

else if(age < minAge || age > maxAge) //villkor 3 (ogiltigt val). { Console.WriteLine("Det verkar som att du matat in ett ogiltigt värde."); Console.WriteLine("Den äldsta människan i världshistorien, fransyskan Jeanne Calment, blev drygt 122 år gammal!"); Console.WriteLine("Den äldsta människan i svensk historia, Astrid Zachrison, blev 113 år och dog på sin födelsedag."); Console.WriteLine("Antingen har du matat in ett värde över 113 år, eller ett värde som understiger åldern 0 år."); Console.WriteLine("Jag kan inte hantera dessa värden. Försök igen!"); } else { Console.WriteLine(name + " " + lastName + ", du gick förmodligen i pension i år. Gratulerar, njut av en frihet utan dess like."); }

Dold text

Console.ReadKey();

Dold text
Trädvy Permalänk
Entusiast
Testpilot
Plats
Chalmers
Registrerad
Aug 2011
Skrivet av Mattiays:

1. Fixade till det nu!
2. Vet inte om jag hängde på detta, men jag antar att du ansåg att "else if(age == retAge)" är väldigt redundant, så jag flyttade den till else-satsen. Det kändes som att den passar in bättre där.

Slänger in mina tankegångar kring if-satsen här i koden, är det i rätt riktning?

Del 2 - Pension

Här kan det anses redundant, om jag tolkar dig rätt, med större/lika med 0, men utan det så hoppar värdet 0 till villkor 2. Samt 65 är inte tillåtet här.

if (age >= minAge && age < retirementAge) //villkor 1 { Console.WriteLine(name + " " + lastName + ", du har " + sum + " år kvar till pensionen."); }

Dold text

Här tänker jag att jag inte tillåter värden under 65 år, samt värden över 113 år.

else if (age > retirementAge && age < maxAge) //villkor 2 { Console.WriteLine(name + " " + lastName + ", för cirka " + (-sum) + " år sedan gick du i pension."); }

Dold text

Här tänker jag att jag inte tillåter värden under 0 år, samt värden över 113 år.

else if(age < minAge || age > maxAge) //villkor 3 (ogiltigt val). { Console.WriteLine("Det verkar som att du matat in ett ogiltigt värde."); Console.WriteLine("Den äldsta människan i världshistorien, fransyskan Jeanne Calment, blev drygt 122 år gammal!"); Console.WriteLine("Den äldsta människan i svensk historia, Astrid Zachrison, blev 113 år och dog på sin födelsedag."); Console.WriteLine("Antingen har du matat in ett värde över 113 år, eller ett värde som understiger åldern 0 år."); Console.WriteLine("Jag kan inte hantera dessa värden. Försök igen!"); } else { Console.WriteLine(name + " " + lastName + ", du gick förmodligen i pension i år. Gratulerar, njut av en frihet utan dess like."); }

Dold text

Console.ReadKey();

Dold text

age == RETIREMENT_AGE är i sig inte redundant att ha som villkor i en if-sats; jag tycker tvärtom att det är helt rimligt. Redundant logik kollar sånt som redan är känt:

if (x > 5) {} else if (x <= 5) {}

innehåller redundant logik: Om x inte är större än 5 vet vi automatiskt att det är mindre än eller lika med 5. Vi behöver inte kolla något vi redan vet.

if (x > 5) {} else {}

har precis samma semantik (betydelse), men innehåller ingen redundant logik.

För mig faller det sig mest naturligt att låta en avslutande else-sats representera felaktig data i ditt fall: Man har då försökt med alla sätt som datan kan vara korrekt på, och inget av dem matchade. Därmed är datan felaktig. I din kod ovan har du blandat fallen lite konstigt: rätt, rätt, fel, rätt. Hellre rätt, rätt, rätt, fel, skulle jag säga.

(I andra sammanhang kan det vara tvärtom: Först kollar man alla sätt datan kan vara felaktig på, och om inget av dem matchar är datan korrekt. Så är mer naturligt att göra då det finns flera olika felaktiga fall, men inga distinkt olika korrekta fall.)

Slutligen ska jag säga att du nog borde skippa [spoiler] för att dela in koden. Det blir mycket klickande och svårt att få överblick. Däremot ska du absolut fortsätta infoga dina tankegångar i form av kommentarer i koden, som ovan, när du frågar om hjälp.

5930K • Corsair DP 32 GiB • EVGA GTX 980 • 2x Swift PG278Q
Better SweClockersDisplayPort över USB-C

Köp processor för framtiden™, men inte grafikkort.

Trädvy Permalänk
Medlem
Plats
gbg
Registrerad
Jun 2011

I de flesta språk, C# inkluderat, anses det god stil att använda all caps och understreck för konstanter som är väldigt konstanta. Olika varianter av icke-caps används för mer lokala variabler som kan anta olika värden beroende på input till programmet och så. Till exempel, i ett spel kanske man har nåt i stil med:

public class Player { const double JUMP_SPEED = 30; // pixels per frame const double GRAVITY = 20; // pixels per frame^2 ... Vec2 vel; Vec2 pos; ... // `Update` is called at 60hz void Update() { // Handle input if (JumpButtonPressed()) { vel.y = -JUMP_SPEED; } // Apply acceleration to current velocity vel.y += GRAVITY; // Apply velocity to current position pos += vel; } ... }

Kort och gott, använd `const` för att ge ett konstant värde ett namn, och använd ALL_CAPS vid namngivning av dessa konstanter. För variabler som har ett på något sätt okänt värde vid tillfället du skriver koden, använd "camelCase", "snake_case", "kebab-case", eller vad som nu är lämpligt med avseende på språk, projekt, din egen preferens, etc.

A: Arch Linux - i5 2500 - RX 480 - 12G ram
B: Arch Linux - 2 x Xeon X5770 - R9 280X - 16G ram

Trädvy Permalänk
Medlem
Registrerad
Maj 2012
Skrivet av Alling:

Okej, tack för förklaring.
Har nu ändrat om lite, och satt konstant värde för MIN_AGE och MAX_AGE, samt ändrat om så att ogiltiga värden sätts under den avslutande else-satsen. Känner mig relativt nöjd med kodblocken för if-satsen, hur ser du på kommentarerna?

if (age >= MIN_AGE && age < retirementAge) //villkor 1 { Console.WriteLine(name + " " + lastName + ", du har " + sum + " år kvar till pensionen."); } else if (age > retirementAge && age < MAX_AGE) //villkor 2 { Console.WriteLine(name + " " + lastName + ", för cirka " + (-sum) + " år sedan gick du i pension."); } else if(age == retirementAge) //villkor 3 { Console.WriteLine(name + " " + lastName + ", du gick förmodligen i pension i år. Gratulerar, njut av en frihet utan dess like."); } else { Console.WriteLine("Det verkar som att du matat in ett ogiltigt värde."); Console.WriteLine("Den äldsta människan i världshistorien, fransyskan Jeanne Calment, blev drygt 122 år gammal!"); Console.WriteLine("Den äldsta människan i svensk historia, Astrid Zachrison, blev 113 år och dog på sin födelsedag."); Console.WriteLine("Antingen har du matat in ett värde över 113 år, eller ett värde som understiger åldern 0 år."); Console.WriteLine("Jag kan inte hantera dessa värden. Försök igen!"); } Console.ReadKey();

Skrivet av Bryal:

Tänker du dig något i den här stilen?

int retirementAge = 65; /*ELLER*/ int retirementAge; retirementAge = 65; const double MAX_AGE = 113; const double MIN_AGE = 0;

Trädvy Permalänk
Entusiast
Testpilot
Plats
Chalmers
Registrerad
Aug 2011
Skrivet av Mattiays:

Okej, tack för förklaring.
Har nu ändrat om lite, och satt konstant värde för MIN_AGE och MAX_AGE, samt ändrat om så att ogiltiga värden sätts under den avslutande else-satsen. Känner mig relativt nöjd med kodblocken för if-satsen, hur ser du på kommentarerna?

if (age >= MIN_AGE && age < retirementAge) //villkor 1 { Console.WriteLine(name + " " + lastName + ", du har " + sum + " år kvar till pensionen."); } else if (age > retirementAge && age < MAX_AGE) //villkor 2 { Console.WriteLine(name + " " + lastName + ", för cirka " + (-sum) + " år sedan gick du i pension."); } else if(age == retirementAge) //villkor 3 { Console.WriteLine(name + " " + lastName + ", du gick förmodligen i pension i år. Gratulerar, njut av en frihet utan dess like."); } else { Console.WriteLine("Det verkar som att du matat in ett ogiltigt värde."); Console.WriteLine("Den äldsta människan i världshistorien, fransyskan Jeanne Calment, blev drygt 122 år gammal!"); Console.WriteLine("Den äldsta människan i svensk historia, Astrid Zachrison, blev 113 år och dog på sin födelsedag."); Console.WriteLine("Antingen har du matat in ett värde över 113 år, eller ett värde som understiger åldern 0 år."); Console.WriteLine("Jag kan inte hantera dessa värden. Försök igen!"); } Console.ReadKey();

Kommentarerna borde nog tas bort. De tillför ingenting, utan beskriver bara precis vad som redan står i koden, fast i mycket mindre specifika ordalag. Alla som kan förstå koden förstår den precis lika bra utan de kommentarerna. Hade kommentarerna varit i stil med user is not yet retired hade de kunnat anses fylla ett syfte, men villkor 1 säger i ärlighetens namn ingenting.

Det kanske viktigaste användningsområdet för kommentarer är att lägga in förtydliganden där det inte är uppenbart varför koden ser ut som den gör. Detta bland annat för att förhindra att man själv eller någon annan, kanske flera år senare, ändrar koden på ett sätt som vid en första anblick verkar bra men som i själva verket är dåligt.

Citat:

Tänker du dig något i den här stilen?

int retirementAge = 65; /*ELLER*/ int retirementAge; retirementAge = 65; const double MAX_AGE = 113; const double MIN_AGE = 0;

const int RETIREMENT_AGE borde det vara. Det är ju en konstant som är en del av programmet.

5930K • Corsair DP 32 GiB • EVGA GTX 980 • 2x Swift PG278Q
Better SweClockersDisplayPort över USB-C

Köp processor för framtiden™, men inte grafikkort.

Trädvy Permalänk
Medlem
Registrerad
Maj 2012
Skrivet av Alling:

Okej, om man ser till helheten för koden, skulle det behövas kommentarer överhuvudtaget? För jag kan hålla med dig på punkten att den som förstår kod, kommer förstå alldeles utmärkt vad programmet fyller för syfte. Däremot funderar jag på om jag skall lägga in en kort beskrivning i början av all kod, som sammanfattat beskriver koden i sin helhet?

Hur menar du kring villkor 1? Bör jag skriva om det villkoret?
Snyggt! Ändrade ret_age till const int nu, tackar!

const int RETIREMENT_AGE = 65; const double MAX_AGE = 113; const double MIN_AGE = 0; Console.WriteLine("Välkommen till pensionskollen!"); Console.Write("Mata in ditt förnamn: "); string name = Console.ReadLine(); Console.Write("Mata in ditt efternamn: "); string lastName = Console.ReadLine(); Console.Clear(); Console.WriteLine("Hej " + name + " " + lastName + ", hur gammal är du? "); int age = int.Parse(Console.ReadLine()); int sum = RETIREMENT_AGE - age; Console.Clear(); if (age >= MIN_AGE && age < RETIREMENT_AGE) { Console.WriteLine(name + " " + lastName + ", du har " + sum + " år kvar till pensionen."); } else if (age > RETIREMENT_AGE && age < MAX_AGE) { Console.WriteLine(name + " " + lastName + ", för cirka " + (-sum) + " år sedan gick du i pension."); } else if(age == RETIREMENT_AGE) { Console.WriteLine(name + " " + lastName + ", du gick förmodligen i pension i år. Gratulerar, njut av en frihet utan dess like."); } else { Console.WriteLine("Det verkar som att du matat in ett ogiltigt värde."); Console.WriteLine("Den äldsta människan i världshistorien, fransyskan Jeanne Calment, blev drygt 122 år gammal!"); Console.WriteLine("Den äldsta människan i svensk historia, Astrid Zachrison, blev 113 år och dog på sin födelsedag."); Console.WriteLine("Antingen har du matat in ett värde över 113 år, eller ett värde som understiger åldern 0 år."); Console.WriteLine("Jag kan inte hantera dessa värden. Försök igen!"); } Console.ReadKey();

Trädvy Permalänk
Medlem
Plats
gbg
Registrerad
Jun 2011
Skrivet av Mattiays:

Okej, om man ser till helheten för koden, skulle det behövas kommentarer överhuvudtaget? För jag kan hålla med dig på punkten att den som förstår kod, kommer förstå alldeles utmärkt vad programmet fyller för syfte. Däremot funderar jag på om jag skall lägga in en kort beskrivning i början av all kod, som sammanfattat beskriver koden i sin helhet?

Hur menar du kring villkor 1? Bör jag skriva om det villkoret?
Snyggt! Ändrade ret_age till const int nu, tackar!

const int RETIREMENT_AGE = 65; const double MAX_AGE = 113; const double MIN_AGE = 0; Console.WriteLine("Välkommen till pensionskollen!"); Console.Write("Mata in ditt förnamn: "); string name = Console.ReadLine(); Console.Write("Mata in ditt efternamn: "); string lastName = Console.ReadLine(); Console.Clear(); Console.WriteLine("Hej " + name + " " + lastName + ", hur gammal är du? "); int age = int.Parse(Console.ReadLine()); int sum = RETIREMENT_AGE - age; Console.Clear(); if (age >= MIN_AGE && age < RETIREMENT_AGE) { Console.WriteLine(name + " " + lastName + ", du har " + sum + " år kvar till pensionen."); } else if (age > RETIREMENT_AGE && age < MAX_AGE) { Console.WriteLine(name + " " + lastName + ", för cirka " + (-sum) + " år sedan gick du i pension."); } else if(age == RETIREMENT_AGE) { Console.WriteLine(name + " " + lastName + ", du gick förmodligen i pension i år. Gratulerar, njut av en frihet utan dess like."); } else { Console.WriteLine("Det verkar som att du matat in ett ogiltigt värde."); Console.WriteLine("Den äldsta människan i världshistorien, fransyskan Jeanne Calment, blev drygt 122 år gammal!"); Console.WriteLine("Den äldsta människan i svensk historia, Astrid Zachrison, blev 113 år och dog på sin födelsedag."); Console.WriteLine("Antingen har du matat in ett värde över 113 år, eller ett värde som understiger åldern 0 år."); Console.WriteLine("Jag kan inte hantera dessa värden. Försök igen!"); } Console.ReadKey();

Jag tycket inte att några kommentarer INNOM metoden är justifierade i just det här fallet. Det är snarare när man håller på med lurigare logik; har kod som ser onödig ut, men som faktiskt fyller ett viktigt syfte; eller behöver sammanfatta ett koncept för att ge förkunskap inför ett komplicerat stycke kod (inte helt olikt a) ); som kommentarer innom en metod är lämpliga. Väl designad kod har sällan metoder som är längre än 30-40 rader (förutom Main och andra inherent imperativa metoder), och korta metoder är ofta så översiktliga att kommentarer inom metoden blir överflödiga för förståelse. I ditt fall agerar ju även alla `Console.WriteLine`s mer eller mindre som dokumentation för logikpredikaten.

En dokumentationskommentar för hela klassen (programmet) som beskriver sammanfattat vad programmet gör hade inte suttit fel dock. Det gör det praktiskt för framtida läsare att snabbt få en överblick över vad klassen handlar om, om inte filnamnet gör det uppenbart.

A: Arch Linux - i5 2500 - RX 480 - 12G ram
B: Arch Linux - 2 x Xeon X5770 - R9 280X - 16G ram

Trädvy Permalänk
Entusiast
Testpilot
Plats
Chalmers
Registrerad
Aug 2011
Skrivet av Mattiays:

Okej, om man ser till helheten för koden, skulle det behövas kommentarer överhuvudtaget? För jag kan hålla med dig på punkten att den som förstår kod, kommer förstå alldeles utmärkt vad programmet fyller för syfte. Däremot funderar jag på om jag skall lägga in en kort beskrivning i början av all kod, som sammanfattat beskriver koden i sin helhet?

Jag håller med @Bryal.

Citat:

Hur menar du kring villkor 1? Bör jag skriva om det villkoret?

Det var inget fel på villkoret. Kommentaren villkor 1 var däremot helt intetsägande.

5930K • Corsair DP 32 GiB • EVGA GTX 980 • 2x Swift PG278Q
Better SweClockersDisplayPort över USB-C

Köp processor för framtiden™, men inte grafikkort.

Trädvy Permalänk
Medlem
Registrerad
Maj 2012
Skrivet av Bryal:

Jag tycket inte att några kommentarer INNOM metoden är justifierade i just det här fallet. Det är snarare när man håller på med lurigare logik; har kod som ser onödig ut, men som faktiskt fyller ett viktigt syfte; eller behöver sammanfatta ett koncept för att ge förkunskap inför ett komplicerat stycke kod (inte helt olikt a) ); som kommentarer innom en metod är lämpliga. Väl designad kod har sällan metoder som är längre än 30-40 rader (förutom Main och andra inherent imperativa metoder), och korta metoder är ofta så översiktliga att kommentarer inom metoden blir överflödiga för förståelse. I ditt fall agerar ju även alla `Console.WriteLine`s mer eller mindre som dokumentation för logikpredikaten.

En dokumentationskommentar för hela klassen (programmet) som beskriver sammanfattat vad programmet gör hade inte suttit fel dock. Det gör det praktiskt för framtida läsare att snabbt få en överblick över vad klassen handlar om, om inte filnamnet gör det uppenbart.

Skrivet av Alling:

Jag håller med @Bryal.

Det var inget fel på villkoret. Kommentaren villkor 1 var däremot helt intetsägande.

Okej toppen, då är jag med på banan igen! Tänkte att du menade det men var tvungen att dubbelkolla, väldigt mycket mystik inom programmering i min hjärna just nu!

Eftersom ni är så schysta med hjälpen tänkte jag kolla med er hur följande kod tolkas:

/// <summary> /// Le Function /// </summary> /// <param name="value">Object Age</param> /// <param name="obj">ClientObj</param> /// <returns>if success</returns> private bool myFunction(int value, object obj)

Vart är denna text relevant att infoga? Är den relevant för min kod?

Såhär ser min kommentar ut just nu:

static void Main(string[] args) { /* Krav: Inmatning av förnamn, efternamn samt ålder. * Programmet: Sparar ned inmatade värden i deklarerade variabler. * Programmet2: Kontrollerar sparade värden mot villkor i en if-sats. * Programmet2: Uppfylls vilkor matas en textsträng ut på skärmen. * Programmet2: Om villkor ej uppfylls, matas en textsträng ut med info om ogiltigt värde. */ Kod.......

Det känns som att jag inte riktigt förstår hur man ska använda kommentarer, men skulle en sammanfattning likt ovan anses onödig?

Trädvy Permalänk
Medlem
Plats
gbg
Registrerad
Jun 2011
Skrivet av Mattiays:

/// <summary> /// Le Function /// </summary> /// <param name="value">Object Age</param> /// <param name="obj">ClientObj</param> /// <returns>if success</returns> private bool myFunction(int value, object obj)

Vart är denna text relevant att infoga? Är den relevant för min kod?

För just din kod är det inte relevant, men om du i framtiden skriver ett större projekt med många metoder kan det vara bra att veta att dokumentationskommentarer finns. Att de kan användas för att generera e.g. HTML dokumentation tycker jag sällan är speciellt intressant, men som @Commander skrev tidigare i tråden kan de även utnyttjas av många texteditorer och IDEer för att ge popups och sådant när du håller över ett anrop till metoden till exempel.

För en verklig metod kan de se ut ungefär såhär:

/// <summary> /// Writes a text string to a file </summary> /// <param name="text"> /// The text to write to the file </param> /// <param name="filename"> /// The name of the file to write the text to </param> /// <remarks> /// If no file exists with the name <paramref name="filename"/>, /// a new file with that name is created /// <returns> /// Whether the write operation succeeded </returns> public bool WriteTextToFile(string text, string filename) { ...; }

Jag tycker ofta att dessa kommentarer blir onödigt långa och verbosa, och brukar föredra att bara utnyttja trippel-slash, ///, för att editorer ska förstå att det är dokumentation, men sedan skippa alla XML taggar i förmån för mer flytande text. De flesta editorer/IDEer kan visa sådana här dokumentationskommentarer med (i popups och sånt), utan problem.

/// Writes a text string to the file with name `filename`. /// If no file exists with that name, a new file with that name is created. /// /// Returns whether the write operation succeeded public bool WriteTextToFile(string text, string filename) { ...; }

Skrivet av Mattiays:

Såhär ser min kommentar ut just nu:

static void Main(string[] args) { /* Krav: Inmatning av förnamn, efternamn samt ålder. * Programmet: Sparar ned inmatade värden i deklarerade variabler. * Programmet2: Kontrollerar sparade värden mot villkor i en if-sats. * Programmet2: Uppfylls vilkor matas en textsträng ut på skärmen. * Programmet2: Om villkor ej uppfylls, matas en textsträng ut med info om ogiltigt värde. */ Kod.......

Det känns som att jag inte riktigt förstår hur man ska använda kommentarer, men skulle en sammanfattning likt ovan anses onödig?

Du har skrivit en kommentar som beskriver så kallade implementationsdetaljer. Dessa är, likt kommentarer innom en metod, sällan intressanta. För en utbildad/kunnig programmerare tillför denna information väldigt lite. Att inmatade värden sparas i deklarerade variabler är uppenbart från koden, och tämligen ointressant att veta. Likaså att värden används i villkor etc.

Jag var otydlig när jag bara föreslog en "sammanfattning". Vad jag menade var inte en sammanfattning av hur koden ser ut, utan snarare en sammanfattning av vad koden gör och vad den är till för. I allmänhet har du tre sorters kommentarer

/// KLASSKOMMENTAR class KlassFoo { /// METODKOMMENTAR double MetodBar(int baz) { // KODKOMMENTAR / IMPLEMENTATIONSKOMMENTAR return quux(baz); } }

Klasskommentarer brukar skrivas som dokumentationskommentarer och ger en översikt över vad klassen är till för. I metodkommentarer brukar man beskriva kort vad metoden gör. Inte så mycket hur koden ser ut, utan snarare helhetligt vad den gör. Kodkommentarer brukar det vara mer snålt med, men de kan användas för att förklara implementationsdetaljer. Exempel på hur de kan användas

/// Utility class to write text to files public class FileWriter { /// Writes a text string to the file with name `filename`. /// If no file exists with that name, a new file with that name is created. /// /// Returns whether the write operation succeeded public bool WriteTextToFile(string text, string filename) { var code = CoolFileLib.WriteFile(text, filename); // If the return code is positive, the write succeeded. Negative values are error codes. return code >= 0; } }

För ditt program tror jag att en kommentar mer i stil med

/// Interaktiv kommandoradsapplikation som skriver ut hur /// användarens ålder relaterar till Sveriges pensionsålder. public class PensionsKollen { static void Main(string[] args) { Kod.......; } }

hade varit lagom.

A: Arch Linux - i5 2500 - RX 480 - 12G ram
B: Arch Linux - 2 x Xeon X5770 - R9 280X - 16G ram

Trädvy Permalänk
Medlem
Registrerad
Maj 2012
Skrivet av Bryal:

Först och främst, stort tack för att du tar dig tid att bringa klarhet i summerings-koden.
"///" metoden var helt klart smidigast i mina ögon, och jag körde på den. Är nöjd med koden för det projektet nu. Det funkar som jag tänkt! Stort tack än en gång.

Har antagit ett nytt projekt nu:
Fick ordning på try & catch, samt slumpa fram en temperatur.
Jag tänker mig att man slumpar i intervallet 73-77, som är max/low temperature för behaglig bastu.

Har ni några synpunkter på koden? Tips tas emot med öppna armar.

public static double FahrToCels(int tempFahr) { double tempDeg = Convert.ToDouble((tempFahr - 32)) * 5 / 9; return Math.Round(tempDeg, 1); } public static void Main(string[] args) { const double LOWEST_TEMP = 73; const double HIGHEST_TEMP = 77; double celsius; Console.WriteLine("Welcome to the sauna."); Console.Write("Input prefered temperature in Fahrenheit degrees: "); do { try { int fahrenheit = int.Parse(Console.ReadLine()); celsius = FahrToCels(fahrenheit); } catch (Exception) { Console.Clear(); Console.WriteLine("ERROR!"); Console.Write("Try to input the temperature in Fahrenheit degrees again: "); int fahrenheit = int.Parse(Console.ReadLine()); celsius = FahrToCels(fahrenheit); } if (celsius < HIGHEST_TEMP && celsius > LOWEST_TEMP) { Console.WriteLine("The sauna is ready.."); Console.WriteLine("The temperature was set to: " + celsius + " Celsius degrees."); Console.WriteLine("Press any key to close the program . . . ."); } else if(celsius > HIGHEST_TEMP) { Console.WriteLine("Temperature was set to: " + celsius + " Celsius degrees."); Console.Write("The temperature is too high, please enter a lower temperature: "); } else if(celsius < LOWEST_TEMP && celsius > -17.7) //För att inte störa nästa villkor. Tips på snyggare lösning? { Console.WriteLine("Temperature was set to: " + celsius + " Celsius degrees."); Console.Write("The temperature is too low, please enter a higher temperature: "); } else if(celsius == -17.8) // -17.8 Celsius konverteras till 0 Fahrenheit. Om användaren trycker in 0 F så slumpas temp. { Random randomerare = new Random(); double rand_temp = randomerare.Next(73, 77); Console.WriteLine("Temperature was set to: " + rand_temp + " Celsius degrees."); Console.WriteLine("Press any key to close the program . . . ."); break; } } while (celsius > HIGHEST_TEMP || celsius < LOWEST_TEMP); Console.ReadKey();

Trädvy Permalänk
Entusiast
Testpilot
Plats
Chalmers
Registrerad
Aug 2011
Skrivet av Mattiays:

Har antagit ett nytt projekt nu:
Fick ordning på try & catch, samt slumpa fram en temperatur.
Jag tänker mig att man slumpar i intervallet 73-77, som är max/low temperature för behaglig bastu.

Har ni några synpunkter på koden? Tips tas emot med öppna armar.

public static double FahrToCels(int tempFahr) { double tempDeg = Convert.ToDouble((tempFahr - 32)) * 5 / 9; return Math.Round(tempDeg, 1); } public static void Main(string[] args) { const double LOWEST_TEMP = 73; const double HIGHEST_TEMP = 77; double celsius; Console.WriteLine("Welcome to the sauna."); Console.Write("Input prefered temperature in Fahrenheit degrees: "); do { try { int fahrenheit = int.Parse(Console.ReadLine()); celsius = FahrToCels(fahrenheit); } catch (Exception) { Console.Clear(); Console.WriteLine("ERROR!"); Console.Write("Try to input the temperature in Fahrenheit degrees again: "); int fahrenheit = int.Parse(Console.ReadLine()); celsius = FahrToCels(fahrenheit); } if (celsius < HIGHEST_TEMP && celsius > LOWEST_TEMP) { Console.WriteLine("The sauna is ready.."); Console.WriteLine("The temperature was set to: " + celsius + " Celsius degrees."); Console.WriteLine("Press any key to close the program . . . ."); } else if(celsius > HIGHEST_TEMP) { Console.WriteLine("Temperature was set to: " + celsius + " Celsius degrees."); Console.Write("The temperature is too high, please enter a lower temperature: "); } else if(celsius < LOWEST_TEMP && celsius > -17.7) //För att inte störa nästa villkor. Tips på snyggare lösning? { Console.WriteLine("Temperature was set to: " + celsius + " Celsius degrees."); Console.Write("The temperature is too low, please enter a higher temperature: "); } else if(celsius == -17.8) // -17.8 Celsius konverteras till 0 Fahrenheit. Om användaren trycker in 0 F så slumpas temp. { Random randomerare = new Random(); double rand_temp = randomerare.Next(73, 77); Console.WriteLine("Temperature was set to: " + rand_temp + " Celsius degrees."); Console.WriteLine("Press any key to close the program . . . ."); break; } } while (celsius > HIGHEST_TEMP || celsius < LOWEST_TEMP); Console.ReadKey();

Nu har du använt kommentarer på ett bra sätt. Hade du inte förklarat vad de två sista villkoren höll på med hade man kliat sig i huvudet och undrat vad i hela världen -17.7 och -17.8 gör mitt i koden.

Du efterfrågar en snyggare lösning. Det är bra, för den är lite konstig i nuläget. Varför gör du en strikt större än-jämförelse med -17.7 och inte med -17.8? Och vad händer om du till exempel ändrar 1 till 2 i Math.round-uttrycket i FahrToCels?

Är det rimligt att 0 ska betyda slumpad temperatur? Om du kommer fram till att du faktiskt tycker det, borde nog jämförelsen vara fahrenheit == 0 snarare än celsius == -17.8. Tänk på vad du egentligen menar när du skriver kod.

Du har även 73 och 77 på ett ställe mitt i koden, där det istället borde vara LOWEST_TEMP och HIGHEST_TEMP. Ser att du använt konstanter på ett bra sätt i övrigt, så du har säkert bara missat det.

En annan DRY-förbättring du kan göra är att observera att du har samma meddelande på flera ställen (till exempel "Temperature was set to: " + celsius + " Celsius degrees."). Om du vill ändra det meddelandet måste du ändra på flera ställen. Det vill du undvika. Bygg hellre en funktion (precis som din FahrToCels) som tar in en temperatur och ger tillbaka ett meddelande, så att du istället för nämnda stränguttryck kan skriva typ Message_TemperatureSet(celsius).

Slutligen ska du nog inte döpa en slumpgenerator till randomerare, utan till randomizer.

5930K • Corsair DP 32 GiB • EVGA GTX 980 • 2x Swift PG278Q
Better SweClockersDisplayPort över USB-C

Köp processor för framtiden™, men inte grafikkort.

Trädvy Permalänk
Medlem
Registrerad
Maj 2012
Skrivet av Alling:

Sjukt värdefulla tips, gång efter gång.
Känns väldigt kyligt i hjärnan ibland, särskilt när man inte är bekant med språket! Du reder ut väldigt mycket för mig.
Stort stort tack.

Slängde in lite olika metoder som anropas i koden, så man slipper upprepande strängar.
Jag tycker det ser bättre ut, håller du med mig?

Problem i koden just nu:
Om man matar in exempelvis: '"#(!"¤()="#, så kraschar programmet om användaren upprepar felaktig inmatning.
Kan jag åtgärda detta i try&catch på ett smidigt sätt? Tänker lite om jag ska kasta in en loop? Som kör igenom val 1 och 2 på felaktig inmatning innanför try&catch.

Så här ser det ut nu:

public static double FahrToCels(int tempFahr) { double tempDeg = Convert.ToDouble((tempFahr - 32)) * 5 / 9; return Math.Round(tempDeg, 1); } public static void TempSet(double celsius) { Console.WriteLine("Temperature was automatically set to: " + celsius + " Celsius degrees."); } public static void TempSet2(double celsius) { Console.WriteLine("Temperature was set to: " + celsius + " Celsius degrees."); } public static void StartSauna() { Console.WriteLine("Press any key to start the sauna. . . ."); } public static void Main(string[] args) { const double LOWEST_TEMP = 73; const double HIGHEST_TEMP = 77; const double FREEZE_TEMP = -10; const double DEADLY_TEMP = 110; double celsius; Console.WriteLine("Welcome to the sauna."); Console.Write("Please input prefered temperature: "); do { try { int fahrenheit = int.Parse(Console.ReadLine()); celsius = FahrToCels(fahrenheit); } catch (Exception) { Console.Clear(); Console.WriteLine("ERROR! I can only handle digits/numbers."); //If user input anything else than digits.. Console.Write("Try to input the temperature again: "); int fahrenheit = int.Parse(Console.ReadLine()); celsius = FahrToCels(fahrenheit); } if (celsius < HIGHEST_TEMP && celsius > LOWEST_TEMP) { TempSet2(celsius); StartSauna(); } else if (celsius > HIGHEST_TEMP && celsius < DEADLY_TEMP) { TempSet2(celsius); Console.Write("The temperature is too high, please enter a lower temperature: "); } else if (celsius < LOWEST_TEMP && celsius > FREEZE_TEMP) //If temperature is way lower than normal sauna temperature... { TempSet2(celsius); Console.Write("The temperature is too low, please enter a higher temperature: "); } else if (celsius < FREEZE_TEMP || celsius > DEADLY_TEMP) // Freezeing cold input, user gets a random, comfortable temperature... { Random randomizer = new Random(); double rand_temp = randomizer.Next(Convert.ToInt32(LOWEST_TEMP), Convert.ToInt32(HIGHEST_TEMP)); if(rand_temp >= LOWEST_TEMP && rand_temp <= HIGHEST_TEMP) { TempSet(rand_temp); StartSauna(); } break; } } while (celsius > HIGHEST_TEMP || celsius < LOWEST_TEMP); Console.ReadKey();

Hade en liten idé tidigare idag som jag inte lyckades implementera.
Tanken var att på ogiltig input så får användaren två val, antingen slumpas en temperature inom "comfortable temperature",
eller så får användaren försöka på nytt. Det kanske är överflödigt/onödigt dock?

Console.WriteLine("ERROR! I can only handle numbers."); Console.WriteLine("Choose one of the choses: "); Console.WriteLine("Press [1] for a random temperature: "); input = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("Press [2] to retry input."); input2 = Convert.ToInt32(Console.ReadLine()); if (input == 1) { Random randomerare = new Random(); double rand_temp = randomerare.Next(73, 77); Console.WriteLine("The temperature was automatically set to: " + rand_temp + "Celsius degrees."); } else if(input2 == 2){ celsius = FahrToCels(fahrenheit); Console.WriteLine("The temperature was set to: " + celsius + " Celsius degrees."); } //Här behöver jag någon else-sats, kanske lägga if-satsen i en loop? Har brainfreeze här just nu.

Dold text
Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2007
Skrivet av Mattiays:

Om man matar in exempelvis: '"#(!"¤()="#, så kraschar programmet om användaren upprepar felaktig inmatning.
Kan jag åtgärda detta i try&catch på ett smidigt sätt? Tänker lite om jag ska kasta in en loop? Som kör igenom val 1 och 2 på felaktig inmatning innanför try&catch.

Orsaken att det kraschar vid upprepad felaktiv inmatning är som du kanske märkt p.g.a. du gör den andra inläsningen innuti catch-delen, så när Parse kastar ett exception där så finns inget som fångar den. En loop är en utmärkt idé, det enklaste är att bara omsluta hela try-catch:en i en loop och enbart ha inläsning på ett ställe, d.v.s. i try-delen.

Skrivet av Mattiays:

Hade en liten idé tidigare idag som jag inte lyckades implementera.
Tanken var att på ogiltig input så får användaren två val, antingen slumpas en temperature inom "comfortable temperature",
eller så får användaren försöka på nytt. Det kanske är överflödigt/onödigt dock?

Som nybörjare är det aldrig överflödigt eller onödigt att implementera dina egna idéer. Tanken är ju inte att du ska implementera det bästa bastu-programmet någonsin, utan att du ska lära dig att programmera. Och det gör du genom att just programmera.

Trädvy Permalänk
Medlem
Registrerad
Maj 2012
Skrivet av perost:

En loop är en utmärkt idé, det enklaste är att bara omsluta hela try-catch:en i en loop och enbart ha inläsning på ett ställe, d.v.s. i try-delen.

Okej låter bra, skulle du kunna visa ett exempel på detta? Förstår inte riktigt hur jag ska lösa det i min kod.
Så här blir det för mig:

do { bool loop = true; do { try { int fahrenheit = int.Parse(Console.ReadLine()); celsius = FahrToCels(fahrenheit); loop = false; } catch (Exception) { Console.Clear(); Console.WriteLine("ERROR! I can only handle digits/numbers."); Console.Write("Try to input the temperature again: "); } } while (loop); if (celsius < HIGHEST_TEMP && celsius > LOWEST_TEMP) //"Use of unassigned local variable 'celsius'

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2007
Skrivet av Mattiays:

Okej låter bra, skulle du kunna visa ett exempel på detta? Förstår inte riktigt hur jag ska lösa det i min kod.

Det var precis så jag menade. Det enda problemet verkar vara att C# är lite överkänslig, och tillåter inte att lokala variabler används förrän de tilldelats ett värde. I just det här fallet kommer celsius garanterat tilldelas ett värde innan variabeln används, eftersom loopen inte avslutas förrän dess, men det är inte så lätt för kompilatorn att klura ut det.

Lösningen bör alltså vara att helt enkelt ge celsius ett värde direkt när du deklarerar variabeln, typ double celsius = 0;.

Trädvy Permalänk
Medlem
Registrerad
Apr 2012
Skrivet av Mattiays:

int retirementAge = 65; /*ELLER*/ int retirementAge; retirementAge = 65; const double MAX_AGE = 113; const double MIN_AGE = 0;

Ville bara påpeka att du bör tänka på vilka variabeltyper du väljer. T ex i det här fallet så varför har du double på en variabel som endast har varit heltal tidigare? Behöver du flyttals precision för dina två konstanter där? Om man ska vara super petnoga så tar double upp 8 bytes medan en int endast tar upp 4 bytes. Det viktiga är att du förstår varför du har valt din variabel typ, t ex i ditt temperatur program så behöver du använda flyttal, men med ålder så har du inte använt det tidigare så jag skulle byta dem mot int.
Ett bra exempel på detta som många nybörjare gör är vid sparandet av telefonnummer, de är siffror så numeriska värden känns vettigt, men skulle string gå lika bra, eller t o m vara bättre?
Att förstå vilka variabler du bör använda i vilka situationer är nyttig kunskap och det kommer med tiden (och i det här fallet är det inte alls kritiskt).

Trädvy Permalänk
Medlem
Registrerad
Maj 2012
Skrivet av perost:

Tack, nu funkar det perfekt!

Skrivet av NFRS:

Wow den missade jag fullkomligt, och självklart, är det väldigt lustigt att använda en double där. Ska definitivt tänka på det i mina koder framöver, tack för tipset.

Trädvy Permalänk
Medlem
Registrerad
Maj 2012

Fått in det jag vill ha med i koden nu, stort tack för hjälpen!!
Tänkte höra om någon kunde ge lite kritik och förbättringstips?

Här kommer koden:

private static double FahrToCels(int tempFahr) { double celsius = Convert.ToDouble((tempFahr - 32)) * 5 / 9; return Math.Round(celsius, 1); } public static void TempSet(double celsius) { Console.WriteLine("Temperature was automatically set to: " + celsius + " degrees Celsius."); } public static void TempSet2(double celsius) { Console.WriteLine("The temperature was set to: " + celsius + " degrees Celsius."); } public static void LowTemp() { Console.Clear(); Console.WriteLine("The input value was set to a very low temperature, let me help you to set an comfortable temperature."); } public static void HighTemp() { Console.Clear(); Console.WriteLine("The input value was set to a very high temperature, let me help you to set an comfortable temperature."); } public static void StartSauna() { Console.WriteLine("Press any key to start the sauna. . . ."); } public static void Main(string[] args) { const double LOWEST_TEMP = 73; const double HIGHEST_TEMP = 77; const double COLD_TEMP = 20; const double DEADLY_TEMP = 110; double celsius = 0; int count = 0; Console.WriteLine("Welcome to the sauna."); Console.Write("Please input prefered temperature: "); do { bool loop = true; do { try { int fahrenheit = int.Parse(Console.ReadLine()); celsius = FahrToCels(fahrenheit); loop = false; } catch (Exception) { Console.Clear(); Console.WriteLine("ERROR! I can only handle digits/numbers."); Console.Write("Please input the temperature again: "); } } while (loop); if (celsius < HIGHEST_TEMP && celsius > LOWEST_TEMP) { Console.Clear(); TempSet2(celsius); StartSauna(); } else if (celsius > HIGHEST_TEMP && celsius < DEADLY_TEMP) { TempSet2(celsius); Console.Write("It's too high temperature, please enter a lower temperature: "); } else if (celsius < LOWEST_TEMP && celsius > COLD_TEMP) { TempSet2(celsius); Console.Write("It's too low temperature, please enter a higher temperature: "); } else { Random randomizer = new Random(); double rand_temp = randomizer.Next(Convert.ToInt32(LOWEST_TEMP), Convert.ToInt32(HIGHEST_TEMP)); if (celsius < COLD_TEMP) { LowTemp(); TempSet(rand_temp); StartSauna(); } else { HighTemp(); TempSet(rand_temp); StartSauna(); } break; } } while (celsius > HIGHEST_TEMP || celsius < LOWEST_TEMP); Console.ReadKey();

Dold text