Gå till innehållet

Kapitel 6 - Array

Introduktion till kapitlet

Hittills så har vi skapat och gett varje variabel som vi har använt ett helt eget namn. Detta blir väldigt osmidigt om man vill ha många variabler, bara att skapa variablerna kommer ta mycket kod. Vi ska i detta kapitlet se hur man kan använda en array för att snabbt och enkelt skapa många variabler av samma typ och ge dem ett gemensamt namn. Man kan säga att en array fungerar som en lista som kan innehålla många variabler av samma typ som man kommer åt med hjälp av listans namn och ett tal som anger vilken variabel i listan man vill ha. De är dessutom väldigt användbara tillsammans med loopar.

Array på svenska

På svenska används ibland ordet fält istället för array, array används alltid på engelska. I just C# så finns det ett annat begrepp som heter field på engelska vilket direkt översatt blir fält och därför har vi valt att använda ordet array i denna bok istället för fält.

Skapa och använda en array

En array är som en lista av variabler av samma typ. För att deklarera en array-variabel så lägger man till hakparenteser efter att man skrivit den variabeltyp som arrayen ska innehålla. En array har alltid en fast storlek, man kan alltså inte ändra storlek på en array efter att man har skapat den. Storleken som en array ska ha kan anges på olika sätt. I exemplet nedan så skapas tre olika arrayer på totalt två olika sätt.

// Namnen på tre grekiska öar
string[] grekiskaÖar = new string[3];
grekiskaÖar[0] = "Syros";
grekiskaÖar[1] = "Amorgos";
grekiskaÖar[2] = "Naxos";
Console.WriteLine($"En grekisk ö: {grekiskaÖar[0]}");

// Namnen på fyra svenska landskap
string[] svenskaLandskap = { "Småland", "Närke", "Skåne", "Halland" };
// Skriver ut landskapet med index 1, det vill säga Närke
Console.WriteLine($"Ett landskap: {svenskaLandskap[1]}");

// Låt användaren skriva in tre årtal
int[] årtal = new int[3];
Console.WriteLine("Skriv in tre årtal du tycker är viktiga");
årtal[0] = int.Parse(Console.ReadLine());
årtal[1] = int.Parse(Console.ReadLine());
årtal[2] = int.Parse(Console.ReadLine());
Console.WriteLine($"Ett av årtalen du skrev in är {årtal[0]}");

Console.ReadKey();

Programmets första array, grekiskaÖar, skapas med hjälp av ordet new. Vid skapandet av arrayen så anges att dess längd ska vara 3, det innebär att grekiskaÖar är som en lista som kan innehålla 3 strängar. Precis som vid numreringen av index i en sträng så börjar numreringen av arrayen på 0. Numreringen av en array kallas faktiskt också för index, så de tre index som arrayen grekiskaÖar har är 0, 1 och 2. Exemplet visar sedan hur man gör dels för att tilldela de tre strängarna i grekiskaÖar var sitt värde och dels hur man kan komma åt värdet i en av strängarna i arrayen.

Hämta värde från array

Om du försöker att hämta ett värde från en array för ett index som inte finns i arrayen så kommer ditt program att krascha.

Innan vi går igenom resten av exemplet kan det vara bra att känna till ett nytt begrepp: element. Element är ett allmänt namn för det som en array består av. Arrayen grekiskaÖar består av tre strängar, man kan också säga att den består av tre element. Arrayen svenskaLandskap som vi snart ska kolla mer på består av fyra strängar, alltså fyra element, medan exemplets sista array årtal består av tre int-variabler, det vill säga tre element. En arrays storlek eller längd är detsamma som antalet element som arrayen består av. Med hjälp av begreppet element kan man prata om en array på ett lättare sätt utan att veta vilken variabeltyp som den innehåller.

Nästa del av exemplet handlar om arrayen svenskaLandskap. Den visar att man kan tilldela värden till en arrays element direkt genom att använda klamrar och lista alla element inuti klamrarna separerade med kommatecken. Arrayens längd blir detsamma som antalet element som skrivs mellan klamrarna, i detta fall innebär det att svenskaLandskap får längden 4.

Den sista delen av exemplet skapar en array för heltal. Användaren får själv skriva in de tre årtalen när programmet körs. Notera att de tre raderna där användaren får skriva in årtal ser nästan likadana ut, det enda som skiljer är arrayens index. Man kan låta en variabel ange vilket index som man vill använda eller komma åt och så i detta fall hade det varit smidigt att använda en loop, då hade vi bara behövt skriva int.Parse(Console.ReadLine()) en gång. I nästa avsnitt kommer du får se hur man kan göra detta.

Notera att arrayer alltid brukar namnges i plural eftersom de kan innehålla mer än ett element.

Uppgift 6.1

Skapa ett program som innehåller en array som ska innehålla namnen på tre svenska städer. Skriv in två av namnen i programmets kod men låt användaren få skriva in namnet på den tredje staden. Skriv avslutningsvis ut alla stadsnamnen på samma rad.

Lösningsförslag 6.1

Använda array tillsammans med loopar

Det är väldigt vanligt att man använder loopar tillsammans med arrayer, t.ex. använder man ofta en for-loop där man låter loopens räknarvariabel användas när man anger vilket element man vill komma åt. I detta exempel så får du se en omgjord version av årtalsdelen från tidigare i kapitlet där en loop används för att mata in årtalen till exemplets array. Efter att alla årtal har matats in så används en ny for-loop för att skriva ut alla årtal som är sparade i arrayen. I båda looparna används egenskapen Length som varje array har som alltså anger hur många element som arrayen har.

int[] årtal = new int[3];

Console.WriteLine("Du ska nu få skriva in 3 årtal");
// Läs in tre årtal från användaren
for (int i = 0; i < årtal.Length; i++)
{
    Console.WriteLine($"Skriv in årtal nummer {i+1}");
    årtal[i] = int.Parse(Console.ReadLine());
}

// Skriv ut årtalen till användaren igen
for (int i = 0; i < årtal.Length; i++)
{
    Console.WriteLine($"Årtal {i+1}: {årtal[i]}");
}

Console.ReadKey();

Notera att båda looparnas villkor för att fortsätta köra är i < årtal.Length. I detta exempel så är årtal.Length lika med 3 och därmed blir det största värdet som i kommer att ha 2, vilket är det största indexet som finns i arrayen. Vi hade kunnat skriva talet 3 istället för årtal.Length i båda looparna utan att det hade ändrat programmets körning, men genom att använda årtal.Length behöver vi bara ändra storleken på arrayen längst upp i programmet om vi vill att användaren ska skriva in fler tal. Man ska alltid sträva efter att ett program ska kräva så få ändringar som möjligt om man själv vill att det ska fungera på ett annat sätt.

Det är inte bara indexet för en array som kan anges med en variabel, man kan också ange storleken för en array med en variabel när arrayen ska skapas. Detta görs i det följande exemplet där användaren får skriva in ett valfritt antal artistnamn som sparas i en array. När användaren har skrivit in alla namn går en loop igenom hela arrayen och skriver ut längden av varje artistnamn samt beräknar summan av alla artistnamnens längd med hjälp av egenskapen Length som varje string har.

Console.WriteLine("I detta program får du skriva in dina favoritartiser");
Console.WriteLine("Hur många favoritartister vill du skriva in?");
int antalArtister = int.Parse(Console.ReadLine());
string[] favoritartister = new string[antalArtister];

// Läs in alla artister
for (int i = 0; i < antalArtister; i++)
{
    Console.WriteLine($"Skriv in namnet på artist {i+1} av {antalArtister}");
    favoritartister[i] = Console.ReadLine();
}
Console.WriteLine();

Console.WriteLine("Artistnamnens längder kommer nu att listas");

// Skriv ut och räkna ut artistnamnens totala längd
int totaltAntalTecken = 0;
for (int i = 0; i < favoritartister.Length; i++)
{
    Console.WriteLine(favoritartister[i].Length);
    totaltAntalTecken += favoritartister[i].Length;
}

Console.WriteLine($"Namnen innehåller totalt {totaltAntalTecken} tecken.");
Console.ReadKey();

Vi ska kika på ytterligare ett exempel som använder en loop tillsammans med en array. I detta exempel så går en loop igenom en array som innehåller ett antal löner. Varje lön skrivs ut och läggs till en variabel som håller koll på summan av lönerna likt hur det totala antalet tecken i artistnamnen beräknades i det förra exemplet. Därefter så beräknas medellönen av de löner som fanns i arrayen.

int[] löner = { 32000, 25000, 27400, 60000, 49000, 21450 };

int löneSumma = 0;

Console.WriteLine("Här kan du se några personers löner.");
for (int i = 0; i < löner.Length; i++)
{
    Console.WriteLine(löner[i]);
    löneSumma += löner[i];
}

double medellön = (double)löneSumma / löner.Length;

Console.WriteLine($"Medellönen är {medellön}");

Console.ReadKey();

Vid beräkningen av meddellönen så summan av alla lönerna till en double innan den divideras med antalet löner genom att skriva (double)löneSumma. Anledningen till detta är att beräkningar med enbart int-variabler enbart kan ge en int som svar vilket inte passar detta exempel eftersom medellönen skulle kunna bli ett decimaltal. Genom att omvandla ett av talen i divisionen till en double så kommer division att ge en double som svar istället för en int.

Uppgift 6.2

Skapa ett program där användaren ska få skriva in en lista över alla sporter som hen har testat. Fråga först användaren hur många sporter hen vill skriva in. Därefter ska sporterna skrivas in, en efter en, på var sin rad. Slutligen ska programmet skriva ut namnen på alla sporterna som användaren skrev in.

Lösningsförslag 6.2

Uppgift 6.3

Skapa ett program som innehåller en array med fem olika namn. Skriv ut alla namnen på samma rad med hjälp av en loop.

Lösningsförslag 6.3

Uppgift 6.4

Skapa ett program som innehåller en array med minst 5 årtal, minst ett av årtalen ska finnas med två gånger. Användaren ska få skriva in ett årtal när programmet körs. Programmet ska skriva ut alla index som detta årtal finns på i arrayen. Om årtalet inte fanns på någon plats så ska programmet skriva "Årtalet kunde inte hittas".

Lösningstips 6.4

Använd en bool-variabel för att hålla koll på om det sökta årtalet har hittats eller ej.

Lösningsförslag 6.4

Uppgift 6.5

Skapa ett program som innehåller en array med minst 8 heltal. Gå igenom arrayen med hjälp av en loop och hitta det största och det minsta talet i arrayen.

Lösningstips 6.5

Skapa två variabler som du kallar för min och max och ge dessa samma värde som det första talet i arrayen. Jämför de andra talen i arrayen med min och max med hjälp av en loop.

Lösningsförslag 6.5

foreach-loopen

Detta kapitel handlar egentligen inte om loopar, men det finns en loop som man behöver använda tillsammans med arrayer och därför har vi inte kunnat kolla på den tidigare. Denna loop heter foreach vilket på svenska blir ”för varje”, och den används när man vill göra något ”för varje element i en array”. I exemplet nedan så skapas en array som innehåller namnen på några länder, därefter skrivs alla länder ut två gånger. Den första utskrivningen sker med hjälp av en for-loop som vi har använt tidigare i kapitlet, den andra loopen är en foreach-loop som ger precis samma resultat som for-loopen.

string[] länder = { "Sverige", "Norge", "Finland", "Danmark", "Island" };

// Skriv ut alla länder med en for-loop
for (int i = 0; i < länder.Length; i++)
{
    Console.WriteLine(länder[i]);
}

Console.WriteLine();

// Skriv ut alla länder med en foreach-loop
foreach (string land in länder)
{
    Console.WriteLine(land);
}

Console.ReadKey();

Man ska i detta fall tänka att foreach loopen gör någonting “för varje sträng i arrayen länder, i denna loop kallar vi varje sträng för land”. Man skriver alltså först variabeltypen, därefter namnet som man vill att varje element ska ha just i denna loop, därefter ordet in och slutligen namnet på den array man vill gå igenom.

Ändringar i foreach

Man kan inte ändra värdet av den variabel som används i foreach-loopen, behöver man göra detta så ska man använda en for-loop.

Man bör använda foreach-loopen istället för for-loopen när man vill göra något för varje element i en array, t.ex. skriva ut ut varje element. Det är dock inte möjligt att ändra variabeln som är sparad i arrayen inuti en foreach-loop, vill man ändra variabeln i arrayen får man använda en for-loop istället.

Uppgift 6.6

Skapa ett program där användaren får skriva in 5 städer som ska sparas i en array. Skriv ut alla namn på var sin rad med hjälp av en foreach-loop.

Lösningsförslag 6.6

Uppgift 6.7

Skapa ett program som innehåller en array med minst 5 heltal. Beräkna summan av alla heltal i arrayen med hjälp av en foreach-loop.

Lösningsförslag 6.7

Lösningstips 6.7

Skapa en variabel som du kallar summa innan loopen, ge den startvärdet 0. Öka summan inuti loopen.

Strängar och arrayer

Det finns några metoder som är användbara när man jobbar med arrayer där elementen är strängar eller när man jobbar med en sträng som man vill skapa en array av. Dessa metoder heter Split och Join. Metoden Split används för att dela upp en sträng till en array genom att man anger ett tecken som fungerar som avgränsare för var strängen ska delas upp. I exemplet nedan används tecknet mellanslag tillsammans med Split för att dela upp en sträng vid alla mellanslag till en array. Notera att det är ett tecken som anger var strängen ska delas upp och inte en sträng, därför skrivs tecknet med det enkla citationstecknet ' istället för ".

Det går också att slå samman en sträng till en array med metoden Join vilket kan vara användbart. Man anger så vilken array man vill slå samman till en sträng samt vad som ska skilja elementen i arrayen åt när de sätts in i strängen.

string städer = "Göteborg Malmö Stockholm Uppsala Lund";
// Delar upp strängen städer i en array, dela vid mellanslag
string[] städerArray = städer.Split(' ');

// Skriv ut städerna i städerArray
for (int i = 0; i < städerArray.Length; i++)
{
    Console.WriteLine($"Stad {i}: {städerArray[i]}");
}
Console.WriteLine();

string[] landskapsArray = { "Småland", "Uppland", "Närke" };
// Sätt ihop elementen i arrayen till en sträng åtskilda av ", "
string landskap = string.Join(", ", landskapsArray);
Console.WriteLine($"Några landskap i Sverige är {landskap}");

Console.ReadKey();

Split och Join är skapade för att användas med strängar, men det går att använda dem tillsammans med tal om man själv genomför omvandlingen från tal till sträng.

Array vs lista

I exemplet ovan så hade man vi kunna kalla vår array för stadLista istället för städerArray. Det finns en annan sak i C# som kallas för List, eller lista på svenska, och därför valde vi att använda array i variabelnamnet istället. Du kommer att lära dig om listor, som fungerar som en lite annorlunda och bättre typ av array, senare i boken.

I nästa exempel så får användaren skriva in hur många tal hen vill på en rad, talen ska vara separerade av mellanslag, t.ex. ”512 3 -3123 995223”. Programmet kommer därefter att berätta vilket av talen som skrevs in som var störst.

Console.WriteLine("Skriv in så många tal du vill åtskilda av mellanslag");
string inmatadeTal = Console.ReadLine();
string[] separeradeTal = inmatadeTal.Split(' ');

int störstaTalet = int.MinValue;
foreach (string talSträng in separeradeTal)
{
    int tal = int.Parse(talSträng);
    if (tal > störstaTalet)
    {
        störstaTalet = tal;
    }
}

Console.WriteLine($"Det största av talen du skrev in är {störstaTalet}");

Console.ReadKey();

Variabeln störstaTalet ska innehålla det största talet som användaren skrev in. Det ges till att börja med värdet int.MinValue som är minsta värde en int kan ha, ungefär minus två miljarder. En loop går sedan igenom talen som användaren skrev in, ett efter ett, och undersöker om detta tal är större än det nuvarande värdet i störstaTalet. Om detta är fallet så ändras värdet av störstaTalet till det nuvarande talets värde.

Uppgift 6.8

Skapa ett program där användaren får skriva in en mening. Skapa en array där varje ord i meningen blir ett element i arrayen. Skriv därefter ut varje ord i meningen på en egen rad.

Lösningsförslag 6.8

Uppgift 6.9

Skapa ett program där användaren får skriva in en rad med tal separerade med plustecken +. Programmet ska beräkna summan av alla talen.

Lösningstips 6.9

Använd Split('+') för att få en lista med strängar som innehåller talen. Konvertera strängarna till tal inuti en loop.

Lösningsförslag 6.9

Flerdimensionella arrayer

Vi har hittills kollat på arrayer som endast har haft ett index för att ange vilken del av arrayen som man vill komma åt. Arrayer som har ett index kallas för endimensionella arrayer. Det är möjligt att skapa och använda arrayer som har två eller fler index och dessa kallas för flerdimensionella arrayer.

Vi ska i ett exempel ser hur man kan skapa en array med två index, en tvådimensionell array, på några olika sätt och sedan använda information i en sådan array. Tvådimensionella arrayer är lämpliga att använda om man har information som är tvådimensionell, t.ex. hur en karta ser hur. Flerdimensionella arrayer används ofta tillsammans med nästlade loopar.

// Skapa en "karta" med 6 tal
int[,] talkarta = new int[2, 3];
talkarta[0, 0] = 1;
talkarta[0, 1] = 2;
talkarta[0, 2] = 3;
talkarta[1, 0] = 4;
talkarta[1, 1] = 5;
talkarta[1, 2] = 6;

// Talet 5 kommer att skrivas ut
Console.WriteLine(talkarta[1, 1]);

// Skapa en karta med strängar
string[,] karta = new string[3, 3];
karta[0, 0] = "A";
karta[1, 0] = "B";
karta[2, 0] = "C";
karta[0, 1] = "D";
karta[1, 1] = "E";
karta[2, 1] = "F";
karta[0, 2] = "G";
karta[1, 2] = "H";
karta[2, 2] = "I";

// Skriv ut innehållet i kartan med strängar
for (int y = 0; y < 3; y++)
{
    for (int x = 0; x < 3; x++)
    {
        Console.Write(karta[x, y]);
    }
    Console.WriteLine();
}

Console.ReadKey();

I exemplet så skapas två olika tvådimensionella arrayer, en som innehåller tal och en som innehåller strängar. Båda dessa arrayer får två index. För den första arrayen, talkarta, så kan det första indexet man skriver in kan vara 0 eller 1 och det andra indexet som man skriver in kan vara 0, 1 eller 2. Indexen separeras med ett kommatecken, både när man skapar arrayen och när man vill komma åt dess element. Eftersom längden av den första arrayen är 2 för det ena indexet och 3 för det andra så blir det totala antalet element man kan ha i arrayen 2x3 = 6 eftersom det är så många olika sätt man kan kombinera de båda indexen på.

Tvådimensionella arrayer och loopar

Precis som i vårt exempel så används ofta tvådimensionella arrayer tillsammans med nästlade loopar.

När den tvådimensionella arrayen med strängar skapas så ges den storleken 3 för varje index vilket gör att den kan ha total 3x3 = 9 element. Senare i programmet skrivs alla element i denna array ut med en nästlad for-loop och då kan man se det som att arrayens index är en x-koordinat och en y-koordinat. Vi låter det första indexet representera x-koordinaten för kartan och det andra får representera y-indexet. I datorgrafik är det vanligt att x-koordinater ökar i värde när man går åt höger precis som i ett matematiskt koordinatsystem. Däremot så brukar y-koordinaten öka när man går neråt istället för uppåt och så kommer vi även göra i vårt program.

Programmet kommer att skriva ut denna tvådimensionella array som

ABC
DEF
GHI

och då känns det lämpligt att ge arrayen dessa värden i bokstavsordning. Eftersom bokstäverna ABC skrivs på samma rad så ska de ha samma y-koordinat men olika x-koordinater. Här visas en tabell som visar vilka koordinater de olika bokstäverna kommer att ha.

y \ x012
0ABC
2DEF
3GHI

Exemplet avslutas med att den nästlade loopen går igenom arrayen med strängar och skriver ut alla element som finns där.

Uppgift 6.10

Skriv ut elementen i talkartan i exemplet i minskande ordning med hjälp av en nästlad loop.

Lösningsförslag 6.10

Uppgift 6.11

Skapa ett program som innehåller en tvådimensionell array av strängar likt arrayen karta i exemplet innan, låt den innehålla 16 strängar med bokstäverna A – P i en karta med storleken 4x4. Skapa två variabler, x och y, som anger vilka ”koordinater” användaren befinner sig på i kartan just nu. Användaren ska kunna gå runt på kartan genom att skriva upp, ner höger eller vänster ända tills hen inte vill gå runt på kartan mer. Efter att användaren har flyttat på sig ska du skriva ut vilka x- och y-koordinater som användaren står på just nu samt vilken bokstav som är på denna plats. Användaren ska inte kunna gå ut utanför arrayens gränser.

Lösningstips 6.11

Gör programmet som ett menyprogram och låt alternativen vara de olika rörelseriktningarna.

Lösningsförslag 6.11

Blandade uppgifter till kapitel 6

Uppgift 6.12

Skapa ett program som innehåller en array med strängar där varje sträng är en mening. Skriv ut varje mening med hjälp av en loop, gör så att varje mening hamnar i ett eget stycke, det ska alltså vara en tom rad mellan varje mening.

Lösningsförslag 6.12

Uppgift 6.13

Skapa ett program som fungerar som leksaken ”Magic 8-ball”. Användaren ska få ställa hur många frågor hen vill till programmet som ska svara med slumpmässigt valt svar av 10 möjliga. Spara de 10 möjliga svaren i en array med strängar. Om användaren skriver in ”a” när hen ska ställa en fråga ska programmet avslutas.

Lösningsförslag 6.13

Uppgift 6.14

Skapa ett program som innehåller en array med minst 5 namn. Använd en loop för att gå igenom arrayen och sedan skriva ut de namn som kommer först och sist i bokstavsordning.

Lösningstips 6.14

Denna uppgift är ganska lik uppgiften där du ska hitta det största och minsta talet i en array. Använd metoden CompareTo för att jämföra två strängar med varandra.

Lösningsförslag 6.14

Uppgift 6.15

Skapa ett program där användaren själv ska få välja hur många heltal hen vill skriva in i en array. Efter att användaren har skrivit in alla tal ska programmet välja ett av talen som skrevs in slumpvis och därefter skriva ut detta tal samt vilket index detta tal hade i arrayen.

Lösningsförslag 6.15

Uppgift 6.16

Skapa ett program som innehåller två arrayer med 4 element var, den ena arrayen ska heta frågor och den andra ska heta svar. Programmet ska fungera som ett frågesportprogram. När programmet körs ska en slumpvis vald fråga visas för användaren som ska få svara på frågan. Programmet ska ange om användaren svarade rätt eller fel. Spara frågorna och svaren i de arrayer som programmet innehåller, svaret till frågan som finns på index 0 i frågor-arrayen ska finnas på index 0 i svar-arrayen.

Lösningsförslag 6.16

Uppgift 6.17

Skapa ett program där användaren får skriva in en rad med tal separerade med asterisker *. Programmet ska beräkna produkten av alla talen, d.v.s. vad alla talen multiplicerade med varandra blir. Programmet ska klara av att man skriver in minst 5 stycken fyrsiffriga tal.

Lösningstips 6.11

Använd Split('*') i programmet. Eftersom programmet ska klara av 5 stycken fyrsiffriga tal kan du inte använda en int för produkten, använd en double istället.

Lösningsförslag 6.17

Uppgift 6.18

Utöka programmet från uppgift 6.12 så att det använder Thread.Sleep för att ta en kort paus mellan varje tecken som skrivs ut. Programmet ska ta en längre paus mellan varje stycke.

Lösningsförslag 6.18

Uppgift 6.19

Skapa ett program som ska simulera tärningskast i Yatzy. När programmet börjar ska 5 tärningar kastas, tärningarna ska vara numrerade från 1 till 5. Programmet ska skriva ut vad tärningkasten blev, därefter ska användaren få bestämma vilka tärningar som ska låsas och därmed aldrig kastas igen. Numret för de tärningar som ska låsas ska skrivas in på en rad sepererade med mellanslag. Därefter ska programmet kasta om alla tärningar som inte är låsta kastas om igen, därefter bestämmer användaren vilka tärningar som ska låsas o.s.v. Programmet ska inte avslutas förrän användaren har låst alla tärningarna. Det ska finnas variabler längst upp i programmets kod som bestämmer antalet tärningar som finns och hur många sidor tärningarna har.

Lösningstips 6.19

Skapa en array med bool-variabler som håller koll på vilka tärningar som är låsta, arrayen ska alltså innehålla en bool per tärning.

Lösningsförslag 6.19

Kommentarer