C# Objektorienterad programmering och listor

Permalänk

C# Objektorienterad programmering och listor

Hej, sitter lite i knipa här med objektorienterad programmering i C#. Har inte riktigt lossnat för mig. Hur går jag tillväga i följande uppgift?
Jag vill interagera med en listas element för att kunna skriva ut alla temperaturer i listan och dela det med antalet element i listan.

Sen måste jag också komma åt det högsta och lägsta temperaturen. Känner mig vilsen. Har kommenterat nedanför där jag har stött på problem.

class Program { static void Main(string[] args) { List<City> citys = new List<City>(); while (true) { System.Console.WriteLine("====VÄDERLEKEN===="); System.Console.WriteLine("1: Ange ny stad "); System.Console.WriteLine("2: Se temperatur för samtliga städer"); System.Console.WriteLine("3: Se medeltemperatur för samtliga städer"); System.Console.WriteLine("4: Se vilken stad som är kallast & vart det är varmast"); int input = System.Convert.ToInt32(System.Console.ReadLine()); switch (input) { case 1: { System.Console.Write("Stadens namn: "); string names = System.Console.ReadLine(); System.Console.Write("Ange temperatur: "); int degrees = System.Convert.ToInt32(System.Console.ReadLine()); City city = new City(names,degrees); citys.Add(city); break; } case 2: { System.Console.WriteLine("Temperatur för samtliga städer är: "); foreach(var item in citys) { System.Console.WriteLine(item.name + ": " + item.degrees); } break; } case 3: { System.Console.Write("Medeltemperatur för samtliga städer är: "); foreach(var item in citys) { System.Console.WriteLine(); //Hur adderar man elementen i en lista? } break; } case 4: { System.Console.WriteLine("Lägst temperatur är det i: " + " Varmast är det i: "); //Hur kommer jag åt listans index? break; } } } } } class City { public string name; public int degrees; public City(string name, int degrees) { this.name = name; this.degrees = degrees; } }

Permalänk
Medlem

Hej!

Vill du gå igenom alla object i en lista är foreach bra.

Jag tycker dotnetperls.com förklarar saker bra:
https://www.dotnetperls.com/foreach

Permalänk

För case 3 så vill du alltså summera alla temperaturer och dela summan med antalet städer i listan. Mitt förslag är att du skapar en variabel av typen int som du exempelvis döper till sum. Till denna variabel adderar du sedan värdet av item.degrees i varje iteration av din foreach. Sen tror jag att du kan få ut antalet objekt från en lista med Count? (Har ej arbetat med C# så går utifrån det jag hittar online). Resultatet får du sedan från sum/count

För case 4 vill du få ut högsta och lägsta temperaturen i städerna du har i listan. Du kan sortera listan när du lägger in ett nytt värde, så staden med lägst temperatur ligger först men det kan nog vara lite överkurs.
Eller så går du igenom listan som du gör med din foreach. Du skapar temporära variabler för staden med lägst respektive högst temperatur. När du hämtar ett nytt element från listan så jämför du om temperaturen är lägre/högre än de temporära variablerna, i så fall skriver du över dessa. I slutet bör du kunna skriva ut variablernas värden.

Hoppas detta ger lite klarhet, jag vill helst inte börja skicka kodförslag innan du gör en ansats själv för att lösa uppgiften. Lycka till!

Permalänk
Medlem

Japp. Om du kan använda foreach och if så är det skitenkelt att göra case 4 (läs inlägget ovan från That Maniac).

Gällande case 3 så kan du skapa en lista inne i kodblocket (men ovanför foreach blocket! hehe) där du adderar alla temperaturer. Sen gör du räknegrejen efter foreach-blocket.

Ett tips som jag har för nybörjare är att ta fram penna och papper. Där du skissar ner steg för steg om HUR du ska GÖRA för att LÖSA problemet. Tänk inte på hur du ska programmera. Sen programmerar du utifrån stegen, fastnar du vid något steg, googla.

Visa signatur

| Mobo: Gigabyte X570 GAMING X | CPU: AMD Ryzen 9 3900X + Dark Rock 4 | RAM: 32GB @ 3000MHz | GPU: Gigabyte RTX 3080 OC | PSU: Seasonic GX 850W | Chassi: NZXT S340 Elite Matte Black | M.2: Samsung 970 Evo 500GB & 1000GB | HDD: 4TB | Monitors: Acer Predator X34 GS & Acer XB270HU |

Permalänk

Jag fixade case 3 nu. Tack för tipsen, googla har jag gjort hela dagen, men känns som att det finns 1000 olika sätt att göra detta på.
Försökte precis med denna metoden, jag har ingen aning om vad jag håller på med haha... Det funkade inte.

case 4: { citys.Sort(); System.Console.WriteLine("Den kallaste staden är: "+citys.First() +" & den varmaste staden är: "+ citys.Last()); break; }

Permalänk
Medlem
Skrivet av Zero_Digits:

Försökte precis med denna metoden, jag har ingen aning om vad jag håller på med haha... Det funkade inte.

Där har vi problemet. Du testar dig fram på olika lösningar på måfå och när du väl hittat en förstår du fortfarande inte vad den gör. Mycket vanligt bland nya programmerare. Därav mitt tips om penna och papper

Fråga dig själv: Vad exakt sorterar .Sort()?

Visa signatur

| Mobo: Gigabyte X570 GAMING X | CPU: AMD Ryzen 9 3900X + Dark Rock 4 | RAM: 32GB @ 3000MHz | GPU: Gigabyte RTX 3080 OC | PSU: Seasonic GX 850W | Chassi: NZXT S340 Elite Matte Black | M.2: Samsung 970 Evo 500GB & 1000GB | HDD: 4TB | Monitors: Acer Predator X34 GS & Acer XB270HU |

Permalänk

@Dave1080: Jag har fått sorteringen att funka nu. Det enda jag behöver nu är ett sätt att skriva ut det första och det sista elementet i listan. Har testat flera olika sätt som "ska" funka. Men konsolen skriver bara ut klass namnen. Vad gör jag för fel?

Jag har testat med: var last = citys[citys.count-1]; för att få ut det sista elementet. Men det skrivs bara ut Väderleken.City

case 4: { citys.Sort(delegate (City c1, City c2) { return c1.degrees.CompareTo(c2.degrees); }); foreach (var element in citys) { System.Console.WriteLine(); } break; }

Permalänk
Medlem
Skrivet av Zero_Digits:

@Dave1080: Jag har fått sorteringen att funka nu. Det enda jag behöver nu är ett sätt att skriva ut det första och det sista elementet i listan. Har testat flera olika sätt som "ska" funka. Men konsolen skriver bara ut klass namnen. Vad gör jag för fel?

Du ville ha det sista elementet från listan och det fick du. Datorn kan inte läsa dina tankar, du måste alltid vara specifik i programmeringen. Jag förmodar att du vill ha stadens namn?

Testa:
var last = citys[citys.count-1];
string name = last.name;

System.Console.WriteLine(name);

Visa signatur

| Mobo: Gigabyte X570 GAMING X | CPU: AMD Ryzen 9 3900X + Dark Rock 4 | RAM: 32GB @ 3000MHz | GPU: Gigabyte RTX 3080 OC | PSU: Seasonic GX 850W | Chassi: NZXT S340 Elite Matte Black | M.2: Samsung 970 Evo 500GB & 1000GB | HDD: 4TB | Monitors: Acer Predator X34 GS & Acer XB270HU |

Permalänk

@Dave1080: Nu lossnade en hel del, tack! Det är ju givet att man måste deklarera till en variabel innan man kan skriva ut det... Har suttit och stirrat på detta sedan klockan 9 imorse..

Permalänk
Medlem
Skrivet av Zero_Digits:

@Dave1080: Jag har fått sorteringen att funka nu. Det enda jag behöver nu är ett sätt att skriva ut det första och det sista elementet i listan. Har testat flera olika sätt som "ska" funka. Men konsolen skriver bara ut klass namnen. Vad gör jag för fel?

Jag har testat med: var last = citys[citys.count-1]; för att få ut det sista elementet. Men det skrivs bara ut Väderleken.City

case 4: { citys.Sort(delegate (City c1, City c2) { return c1.degrees.CompareTo(c2.degrees); }); foreach (var element in citys) { System.Console.WriteLine(); } break; }

Anledningen till att den skriver ut Väderleken.City är för att om du stoppar in ett objekt i Console.WriteLine() så kommer den anropa City.ToString(), som kommer från klassen Object.

Antingen så får du plocka ut attributen du vill skriva ut, alltså City.name, eller så får du skapa en override av funktionen ToString() i din City klass.

public class City { public override string ToString() { // Här skapar du en sträng som representerar objektet City } }

Exempel: https://stackoverflow.com/questions/18200427/override-tostrin...

Visa signatur

| EVGA Z170 FTW | i7 6700k | ASUS RTX 3070 | 16GB DDR4 3200MHz | Cooler Master V850 | Samsung 840 Evo 250GB + 2x WD Black 500GB + Seagate 2TB SSHD + Samsung 970 Evo M.2 500GB |

Permalänk
Medlem
Skrivet av Zero_Digits:

Jag har fått sorteringen att funka nu.

Du får tänka på att det inte är säkert att du får godkänt för en sån lösning, eftersom det sannolikt inte är det sättet som det är tänkt att du ska lösa uppgiften på. Om du använder såna lösningar så får du vara beredd på följdfrågor från läraren, för att kontrollera att du faktiskt löst uppgiften själv och inte bara googlat fram något. Skulle du t.ex. kunna förklara för läraren varför du valt att använda en föråldrad delegate-funktion istället för en lambda-funktion som man normalt brukar använda i modern C#?

Sättet som du troligtvis förväntas lösa det på är att gå igenom listan, t.ex. med foreach, och hålla reda på vilket som är det minsta och största elementet. D.v.s. om du kommer till ett element som är mindre än det tidigare minsta så blir det elementet det nya minsta, o.s.v.

Skrivet av Zero_Digits:

@Dave1080: Nu lossnade en hel del, tack! Det är ju givet att man måste deklarera till en variabel innan man kan skriva ut det... Har suttit och stirrat på detta sedan klockan 9 imorse..

Du behöver inte deklarera en variabel för att hålla namnet, du kan plocka ut det direkt och skriva ut om du vill. D.v.s.:

System.Console.WriteLine(citys[citys.Count - 1].name);

Men det kan bli rörigt om man gör allt för mycket på en rad, så att dela upp det genom att tilldela delresultat till variabler kan ibland vara en bra idé.

Permalänk
Medlem
Skrivet av perost:

Men det kan bli rörigt om man gör allt för mycket på en rad, så att dela upp det genom att tilldela delresultat till variabler kan ibland vara en bra idé.

Exakt. En bra övning är att deklarera i princip allt, för att tillämpa "steg-för-steg" tänkandet. När man sedan är varm i byxorna kan man refaktorisera på det sättet du just gjorde.

Bra text angående ifrågasättande lärare förresten.

Visa signatur

| Mobo: Gigabyte X570 GAMING X | CPU: AMD Ryzen 9 3900X + Dark Rock 4 | RAM: 32GB @ 3000MHz | GPU: Gigabyte RTX 3080 OC | PSU: Seasonic GX 850W | Chassi: NZXT S340 Elite Matte Black | M.2: Samsung 970 Evo 500GB & 1000GB | HDD: 4TB | Monitors: Acer Predator X34 GS & Acer XB270HU |

Permalänk

@perost: Jag håller med fullständigt och tackar för kritiken. Det svåra med programmering för mig är just det du tar upp med vad man hittar på nätet. Studiemedel och lärare hänvisar ofta till att man som programmerare måste lära sig att hitta lösningar på nätet. Samtidigt som att man inte ska sno vad någon annan gjort. I detta fallet hittar jag inte "rätt" lösning isåfall. Eftersom jag inte har en aning om att delegate är föråldrad eller att man ska använda lambda istället. Hur man loopar igenom en foreach loop och håller kvar det lägsta värdet är något jag heller inte vet hur man gör tyvärr. Men det får jag väl bli bättre på att googla mig till

Permalänk
Medlem
Skrivet av Zero_Digits:

@perost: Jag håller med fullständigt och tackar för kritiken. Det svåra med programmering för mig är just det du tar upp med vad man hittar på nätet. Studiemedel och lärare hänvisar ofta till att man som programmerare måste lära sig att hitta lösningar på nätet. Samtidigt som att man inte ska sno vad någon annan gjort. I detta fallet hittar jag inte "rätt" lösning isåfall. Eftersom jag inte har en aning om att delegate är föråldrad eller att man ska använda lambda istället. Hur man loopar igenom en foreach loop och håller kvar det lägsta värdet är något jag heller inte vet hur man gör tyvärr. Men det får jag väl bli bättre på att googla mig till

Något man gör dagligen som programmerare är att googla och du kommer även att använda "färdig kod", varför uppfinna hjulet igenom det finns ett färdigt redan. Det viktiga är dock att förstå det man använder och hur man kan använda det i sitt program.
Det är skillnad på att använda ett färdigt library eller package och bara kopiera en lösning rakt av för ett problem, utan att läsa vad koden gör.

Ju mer du kodar ju bättre kommer du att bli på att googla. Oftast har man idé om vad man vill göra men är osäker på syntax eller i vilken ordning man ska göra det. Men man googlar t.ex. inte "projektnamn solution" utan är mer "How to do x to get y with Linq C#".

Här har du ett exempel på hur du kan hålla kvar det lägsta värdet i en loop. Du får helt enkelt spara värdet för första indexet utanför loopen och sedan jämföra det mot alla variabler i loopen.

int[] values = new int[]{8,5,8,10,1,2,6}; int lowestVal = values[0]; foreach(var val in values) { if(val < lowestVal) { lowestVal = val; } } Console.WriteLine(lowestVal); // 1

Ett ännu enklare är att använda LINQ och skriva
values.Min(); // 1

Delegates är väl inte riktigt föråldrat skulle jag säga. Tycker det är bra att du använder och förstår vad de gör, så man inte bara ser lambda som "magic". Du skickar kort och gott in en metod som reference i en annan metod.

Permalänk
Medlem
Skrivet av Zero_Digits:

Det svåra med programmering för mig är just det du tar upp med vad man hittar på nätet. Studiemedel och lärare hänvisar ofta till att man som programmerare måste lära sig att hitta lösningar på nätet.

Absolut, att hitta informationen man behöver för att lösa en uppgift är en väldigt viktig kunskap för en programmerare. Men när det handlar om en skoluppgift så är tanken oftast att testa vad ni lärt er i kursen, så det blir lite av en röd flagga för läraren om du använder tekniker som (troligtvis) inte behandlas i kursen.

Skrivet av Zero_Digits:

Hur man loopar igenom en foreach loop och håller kvar det lägsta värdet är något jag heller inte vet hur man gör tyvärr. Men det får jag väl bli bättre på att googla mig till

Att loopa igenom en lista med en foreach gör du redan flera gånger i din kod, och att hålla kvar värden handlar bara om att tilldela en variabel. Här är algoritmen skriven som pseudokod så kanske den blir enklare att greppa:

lägsta_temperatur = ∞°C // Börjar som ett så stort värde som möjligt. högsta_temperatur = -∞°C // Börjar som ett så litet värde som möjligt. för varje stad i listan: om stadens temperatur är lägre än lägsta_temperatur: lägsta_temperatur = stadens temperatur om stadens temperatur är högre än högsta_temperatur: högsta_temperatur = stadens temperatur

Som startvärden för högsta och lägsta temperatur kan du använda t.ex. Int32.MinValue och Int32.MaxValue, det minsta och största värdet en 32-bit int kan vara.

Permalänk
Medlem
Skrivet av Zero_Digits:

Hur man loopar igenom en foreach loop och håller kvar det lägsta värdet är något jag heller inte vet hur man gör tyvärr. Men det får jag väl bli bättre på att googla mig till

Det där känns som något du "borde" kunna klura fram själv, i och med att du redan använder foreach. Du vet att du går genom för varje element i listan. Du vet att man kan deklarera siffror i variabler. Du vet vad en if-statement är för något.

Du skapar int variabler innan foreachen:
int highestValue = Int32.MinValue; // minsta möjliga int värde
int lowestValue = Int32.MaxValue; // högsta möjliga int värde

För varje loop kontrollerar du följande:
OM (if) den aktiva staden i loopens temperatur överskrider highestValue = deklarerar du temperaturen i fråga till highestValue.
OM (if) den aktiva staden i loopens temperatur underskrider lowestValue = deklarerar du temperaturen i fråga till lowestValue.

foreach(var element in cities) { if (element.temperature > highestValue) { highestValue = element.temperature; } if (element.temperature < lowestValue) { lowestValue = element.temperature; } }

Visa signatur

| Mobo: Gigabyte X570 GAMING X | CPU: AMD Ryzen 9 3900X + Dark Rock 4 | RAM: 32GB @ 3000MHz | GPU: Gigabyte RTX 3080 OC | PSU: Seasonic GX 850W | Chassi: NZXT S340 Elite Matte Black | M.2: Samsung 970 Evo 500GB & 1000GB | HDD: 4TB | Monitors: Acer Predator X34 GS & Acer XB270HU |

Permalänk

@Dave1080: Såhär långt har jag kommit:

case 4: case 4: { int min = int.MinValue; int max = int.MaxValue; string c1; string c2; foreach (var element in citys) { if (element.degrees > min) { min = element.degrees; c1 = element.name; } if (element.degrees < max) { max = element.degrees; c2 = element.name; // Varför kan jag inte ta med mig namnet på detta sättet? } System.Console.WriteLine(); break;

Permalänk
Medlem
Skrivet av Zero_Digits:

@Dave1080: Såhär långt har jag kommit:

case 4: case 4: { int min = int.MinValue; int max = int.MaxValue; string c1; string c2; foreach (var element in citys) { if (element.degrees > min) { min = element.degrees; c1 = element.name; } if (element.degrees < max) { max = element.degrees; c2 = element.name; // Varför kan jag inte ta med mig namnet på detta sättet? } System.Console.WriteLine(); break;

Du har inte stängt din IF-sats. Det saknas ett "}"

Nu har jag inte använt C# så mycket men jag antar att du får felmeddelande när du ens försöker köra din kod? Titta vad det står för nåt där, vilken rad i koden det förekommer på osv, och försök förstå felet innan du vänder dig till hjälp online. Vi hjälper ju dig förstås gärna men programmering handlar om förståelse och det bästa sättet att lära sig är att förstå vad som händer i varje rad du skriver.

Permalänk

Löste det med följande metod. Tack för all hjälp. Vet att jag har vart lite besvärlig, tackar för att ni stod ut

case 4: { City min = citys[0]; City max = citys[0]; foreach (var element in citys) { if (element.degrees > min.degrees) { min = element; } if (element.degrees < max.degrees) { max = element; } } System.Console.WriteLine("Kallast är det i " + max.name + ": " + max.degrees + " varmast är det i : " + min.name + ": " + min.degrees); break; } }

Permalänk
Medlem
Skrivet av Zero_Digits:

Löste det med följande metod. Tack för all hjälp. Vet att jag har vart lite besvärlig, tackar för att ni stod ut

case 4: { City min = citys[0]; City max = citys[0]; foreach (var element in citys) { if (element.degrees > min.degrees) { min = element; } if (element.degrees < max.degrees) { max = element; } } System.Console.WriteLine("Kallast är det i " + max.name + ": " + max.degrees + " varmast är det i : " + min.name + ": " + min.degrees); break; } }

Ser vettigt ut

Pedanten i mig vill att du döper om dina variabler så att de matchar vad de faktiskt är dvs. max är staden med högst temperatur etc.

Visa signatur

| EVGA Z170 FTW | i7 6700k | ASUS RTX 3070 | 16GB DDR4 3200MHz | Cooler Master V850 | Samsung 840 Evo 250GB + 2x WD Black 500GB + Seagate 2TB SSHD + Samsung 970 Evo M.2 500GB |

Permalänk

@BrutalSwede: Tack för feedbacken och ja, det ska jag självklart göra . Är bara helt slut i huvudet efter denna uppgiften, objekt orienterad programmering har verkligen vart mitt största hinder hittils i min 2 månader långa programmerings karriär.. haha

Permalänk
99:e percentilen
Skrivet av Zero_Digits:

Löste det med följande metod. Tack för all hjälp. Vet att jag har vart lite besvärlig, tackar för att ni stod ut

City min = citys[0]; City max = citys[0]; foreach (var element in citys) { if (element.degrees > min.degrees) { min = element; } if (element.degrees < max.degrees) { max = element; } } System.Console.WriteLine("Kallast är det i " + max.name + ": " + max.degrees + " varmast är det i : " + min.name + ": " + min.degrees);

Tänk på att namngivning är viktigt, för variabelnamn är dokumentation. Jag fick tänka både en och två gånger för att förstå den här koden; det är bättre om det känns helt naturligt när man läser den.

Tänker specifikt på att du låtit min representera den varmaste staden och max den kallaste. Det är helt tvärtemot vad min hjärna tycker känns naturligt.

Ett exempel som till viss grad illustrerar vikten av namngivning:

A a = c[0]; A b = c[0]; foreach (var d in c) { if (d.e > a.e) { a = d; } if (d.e < b.e) { b = d; } }

Visa signatur

Skrivet med hjälp av Better SweClockers

Permalänk
99:e percentilen
Skrivet av Zero_Digits:

Är bara helt slut i huvudet efter denna uppgiften, objekt orienterad programmering har verkligen vart mitt största hinder hittils i min 2 månader långa programmerings karriär.. haha

Du är inte ensam. Objektorienterad programmering kan vara det mest överskattade paradigmet av dem alla.

Visa signatur

Skrivet med hjälp av Better SweClockers

Permalänk
Medlem
Skrivet av Zero_Digits:

Löste det med följande metod.

case 4: { City min = citys[0]; City max = citys[0]; foreach (var element in citys) { if (element.degrees > min.degrees) { min = element; } if (element.degrees < max.degrees) { max = element; } } System.Console.WriteLine("Kallast är det i " + max.name + ": " + max.degrees + " varmast är det i : " + min.name + ": " + min.degrees); break; } }

Snyggt! Det är nu jag kan berätta för att dig finns superlätta funktioner som automatiskt kan plocka ut minsta och största värdet i en lista

Exempelvis:

// "temperaturer" är en lista av olika temperaturer (en array av int) int maxtemp = temperaturer.Max();

Just i ditt fall använder du en lista av objekt istället för int's, så du skulle behöva lägga till litegrann för att det ska funka.
Exempelvis:

using System.Linq; int maxtemp = citys.Max(city => city.degrees); // Du får direkt max-temperatur