Gå till innehållet

Kapitel 2 - Inmatning, variabler och konvertering

Introduktion till kapitlet

Program som inte kan påverkas av användaren är oftast ganska tråkiga så i detta kapitel kommer du att få lära dig om inmatning, d.v.s. hur användaren kan skriva in tal och text som du sedan kan använda. Du kommer lära dig hur du sparar information i datorns minne med hjälp av variabler och om några av de mest vanliga variabeltyperna som finns i C#. Talen som användaren skriver in kommer du att kunna använda i beräkningar och texten som hen skriver kommer du att lära dig att manipulera och konvertera på olika sätt. Slutligen så kommer du lära dig hur man kan formatera text, både din egen och användarens, så att den skrivs ut i kolumner så att din utmatning liknar en tabell.

Inmatning och variabler för text

Du har nu fått lära dig hur du skriver ut text till användaren, men om användaren inte kan påverka programmet när det körs så finns det inte särskilt mycket som det kan göra. Vi ska nu se hur vi kan låta användaren skriva in text som vi sedan sparar i programmet. För att spara information i programmet när det körs så använder vi oss av variabler. En variabel är något värde som vi vill spara (t.ex. användarens namn eller ålder) och det kallas variabel för att värdet kan variera, alltså ändras senare i programmet om vi vill. Det finns olika typer av variabler som används för att spara olika sorters värden, t.ex. så finns det en typ som används för text och en annan typ för heltal. Vi börjar med att kolla på hur man använder variabler som innehåller text, och i programmering så brukar den typen av variabel kallas för en sträng (eller string på engelska).

Först så kollar vi hur man skapar variabler (vilket brukar kallas att deklarera variabler) samt hur man ger en variabel ett värde och sedan använder värdet.

// Deklarera tre variabler och ge dem värden
string meddelande = "Hej!";
string namn = "John Johnsson";
string yrke = "Programmerare";

// Skriv ut text till användaren
Console.WriteLine(meddelande);
Console.WriteLine("Jag heter " + namn + ", mitt yrke är " + yrke);

// Ändra värdet på variabeln meddelande
meddelande = "Hej då!";

Console.WriteLine(meddelande); 

För att deklarera en variabel så skriver man först vilken typ variabeln ska ha följt av variabelns namn. Alla de variabler som deklareras i detta program är av typen string, så värdet av dessa variabler måste vara text (texten kan bestå av siffror och andra specialtecken, men den räknas alltid som en text). Alla variablerna tilldelas ett värde på samma rad som de deklareras. Varje gång ett likhetstecken används så kommer det som är till höger om likhetstecknet att sparas i variabeln som är till vänster om likhetstecknet. Om man på detta sätt vill läsa ut vad den första raden i programmet gör så skulle man kan läsa det som ta texten ”Hej!” och spara i variabeln meddelande som är av typen string. En variabels namn måste börja med en bokstav eller ett understreck, men resten av namnet kan även innehålla siffror.

Man kan antingen skriva ut värdet av en variabel själv med hjälp av Console.WriteLine, eller så kan man binda samman variabler med varandra eller med annan text med hjälp av plustecken. Om man vill ändra värdet på en variabel så ska man inte deklarera den igen. Det går inte att deklarera en ny variabel med samma namn som en annan variabel, och det är därför man inte skriver string framför meddelande när värdet på den variabeln ändras. När variabeln meddelande skrivs ut den andra gången så skrivs det nya värdet ut vilket är ett exempel på varför variabler heter just variabler: de kan variera.

Ska man ge variablerna svenska eller engelska namn?

I vårt exempel så har vi namngivit variablerna till meddelande, namn och yrke istället för message, name och occupation. Man kan även använda de svenska bokstäverna å, ä och ö i sina variabelnamn om man vill.

Det är vanligt att använda enbart engelska namn när man programmerar eftersom detta är en förutsättning om man t.ex. vill be om hjälp på internet av andra programmerare som inte kan svenska.

I denna bok är variabelnamnen alltid på svenska av anledningen att ingen som läser den ska få problem med att förstå något exempel på grund av svåra engelska ord. Om du känner dig säker på engelska så rekommenderas du dock att använda engelska variabelnamn i dina egna program.

Men det är inte så roligt om man själv måste bestämma värdet av alla variabler innan programmet körs, så nu ska vi se hur man kan få programmet att bli interaktivt med hjälp av Console.ReadLine().

Console.WriteLine("Skriv ditt namn"); 

// Läs in användarens namn
string namn = Console.ReadLine(); 
Console.WriteLine("Hej " + namn);

När programmet kommer till raden med Console.ReadLine() så kommer det att stanna där och vänta på att användaren skriver in någonting och sedan trycker på enter. När användaren har gjort detta kommer värdet av Console.ReadLine() att bli detsamma som användaren skrev in och programmet fortsätter att köra.

Uppgift 2.1

Skapa ett program som först frågar användaren vilken stad som hen kommer ifrån. Fråga sedan vilket som är användarens drömresmål. Slutligen ska programmet skriva ut följande hälsning där ordet stads-bo ska ersättas med staden som användaren kommer ifrån och resmål ska ersättas med användarens drömresmål.

Hej stads-bo. Jag hoppas att du får resa till resmål.

Lösningstips 2.1

Använd Console.ReadLine() två gånger (på var sin rad) för att spara namnet användarens hemstad och drömresemål i var sin string-variabel.

Lösningsförslag 2.1

Andra typer av variabler och konvertering

Text är inte det enda som man vill spara i variabler; någonting som är väldigt viktigt i nästan alla program är användingen av tal. Tal kan i och för sig sparas i en string-variabel som text, men det går inte att räkna med talen om de inte är sparade i variabler som är avsedda för tal. Det finns flera olika typer av variabler för tal, några av de vanligaste visas här. I tabellen visas också hur många bytes som används i datorns minne för att spara variabeln. Byte är den vanligaste enheten för minne i datorsammanhang och en byte består av 8 bits, d.v.s. 8 stycken ettor/nollor.

Typ Användning Minnesanvändning i bytes
int Sparar heltalsvärden (int står för integer som är engelska för heltal). Kan ha heltalsvärden mellan -2 147 483 648 och 2 147 483 647. 4
double Sparar decimaltal. Kan innehålla väldigt små och stora tal men bara upp till en viss precision, upp till 15 siffrors noggrannhet. 8

Det finns fler variabeltyper som används för heltal (som antingen har fler eller färre möjliga värden, men också tar mer eller mindre plats i datorns minne), men int är den absolut vanligaste typen för heltal.

Det finns inga inbyggda sätt i C# att läsa in tal från användaren. Det man istället får göra är att läsa in text från användaren och sedan konvertera texten till ett tal.

Console.WriteLine("Hej! Hur gammal är du?");

// Läs in åldern och konvertera till int
string ålderText = Console.ReadLine();
int ålder = int.Parse(ålderText);

// Beräkna hur gammal personen är om 5 år
int ålderOmFemÅr = ålder + 5;
Console.WriteLine("Om 5 år är du " + ålderOmFemÅr + " år gammal");

// Läs in användarens längd i meter
Console.WriteLine("Hur lång är du? Svar i meter.");
string längdText = Console.ReadLine();
double längd = double.Parse(längdText);

// Beräkna hur lång personen vore om hen var 10 cm längre
double ökadLängd = längd + 0.1;
Console.WriteLine("Om du var 10 cm längre skulle du vara " + ökadLängd + " m.");

Efter inläsningen av talen i textform konverteras de till tal med int.Parse och double.Parse, texten som ska konverteras skrivs i parentesen. Notera att decimaltal i C#-kod skrivs med punkt och inte kommatecken vilket är fallet i engelsktalande länder, men när du skriver in decimaltal som användare av programmet så använder du kommatecken om din dators språkinställning är svenska.

Varning

Ett vanligt misstag är att använda kommatecken istället för punkt som decimaltecken.

Det förra exemplet visade hur man kan konvertera text till heltal och decimaltal. Om man någon gång behöver konvertera ett heltal till ett decimaltal (d.v.s. spara värdet av en int-variabel i en double-variabel) så behöver man inte skriva någonting särskilt, men däremot behöver man göra det för att omvandla ett decimaltal till heltal.

int a = 4;
int b = 7;
double c = 5.61;

// Konvertering från double till int
a = (int)c;

// Konvertering från int till double sker automatiskt
c = a;

Även om man inte behöver uttrycka att ett heltal ska tolkas som en double om det ska sparas i en double så gör man det ibland vid beräkningar som du kommer att se längre fram.

Lite senare i boken kommer även följande variabeltyper att användas.

Typ Användning Minnesanvändning i bytes
float Sparar decimaltal. Har en lägre precision än double men tar inte upp lika mycket plats i datorns minne (double har ungefär dubbelt så bra precision och tar dubbelt så mycket plats i minnet). Har 7 siffrors noggrannhet. 4
bool En bool kan antingen ha värdet true eller värdet false, det finns alltså endast två möjliga alternativ. 1
char Sparar ett enskilt tecken (bokstav, siffra, specialtecken). 2

Uppgift 2.2

Skapa ett program som frågar användaren vilket årtal det är i år. Programmet ska sedan skriva ut vilket årtal det är om 20 år.

Lösningsförslag 2.2

Uppgift 2.3

Skapa ett program som frågar användaren vilket hur högt hen kan hoppa i höjdhopp mätt i meter. Berätta för användaren hur mycket högre världsrekordet i höjdhopp är (världsrekordet i höjdhopp är 2,45 meter).

Lösningstips 2.3

Använd double-variabler så att användaren kan skriva in decimaltal. För att beräkna skillnaden mellan 2,45 och användarens tal så använder du minustecknet -.

Lösningsförslag 2.3

Operatorer för tal

Något du redan har fått se exempel på är att man kan addera tal med varandra med hjälp av plustecknet. Plustecknet är en operator, ett tecken som anger att programmet ska göra något med de variabler som står vid det (i detta fall att talen ska adderas). Även resten av de fyra räknesätten går att använda med både int-variabler och double-variabler.

int a = 7;
int b = 4;

// c får värdet 11
int c = a + b;

// d får värdet 3
int d = a - b;

// e får värdet 28
int e = a * b;

// f får värdet 1. 
// Egentligen är 7 / 4 = 1,75 men alla
// decimaler "huggs bort" vid heltalsberäkningar
int f = a / b;

Beräkning med enbart heltal ger heltal som svar

Om du utför en beräkning, t.ex. en division, med enbart heltal så kommer svaret att vara ett heltal även om det egentligen borde vara ett decimaltal. Följande stycke och exempel visar detta i större detalj.

I exemplet så används operatorerna med int-variabler, men det går alltså lika bra att använda dem för värden som man skriver in direkt i koden och för double-variabler. Notera vad som händer vid division av två heltal: svaret blir också ett heltal oavsett om det egentligen borde vara ett decimaltal. Vid divisionen ovan så är 7/4 = 1,75 men decimalerna ”huggs av” och resultatet av divisionen blir 1. Om något av talen vid division är en double så kommer resultatet att bli en double också och inga decimaler försvinner. Man kan konvertera ett heltal till en double på ett liknande sätt som när man konverterar double till int.

// a får värdet 1
double a = 7 / 4;

// b får värdet 1.75;
double b = 7.0 / 4;

// c får värdet 1.75
double c = (double)7 / 4;
Det går bra att använda parenteser vid uträkningar på samma sätt som i matematiken för att ändra i vilken ordning beräkningarna sker.

Beräkningar i Console.WriteLine

Du måste inte spara resultat av varje beräkning du gör i en variabel om du bara vill skriva ut svaret till användaren. Det går bra att skriva beräkningar i Console.WriteLine, det är oftast lättare att se vilken beräkning som görs ifall man sätter den inuti en parentes.

int tal1 = 10;
int tal2 = 7;

// Alternativ 1
int svar = tal1 - tal2;
Console.WriteLine("Svaret är " + svar);

// Alternativ 2
Console.WriteLine("Svaret är " + (tal1 - tal2));

Något som också är väldigt vanligt är att öka eller minska värdet av en variabel med 1. Man kan då använda ++ eller -- och skriva det direkt efter namnet på variabeln som ska ändras, t.ex.

// a får värdet 1
int a = 5;

a++;
// Nu är a = 6

a--;
// Nu är a = 5 igen

Vi sammanfattar de operatorer som vi har sett i följande tabell.

Operator Betydelse
+ Addition
- Subtraktion
* Multiplikation
/ Division
++ Ökning med 1
-- Minskning med 1

Inmatning av tal på en rad

När du vill läsa in ett tal från användaren måste man först läsa in texten användaren skriver och sedan omvandla den till ett tal. Det går bra att göra både inläsningen av texten och konverteringen till tal på samma kodrad. Istället för att skriva

string text = Console.ReadLine();
int tal = int.Parse(text);
så skriver man
int tal = int.Parse(Console.ReadLine());
Använd detta sätt att läsa in tal från och med nu, bokens exempel kommer också att göra det.

Uppgift 2.4

Skapa ett program som frågar användaren efter två tal. Programmet ska sedan beräkna och skriva ut summan av talen och därefter produkten av talen.

Lösningsförslag 2.4

Uppgift 2.5

Skapa ett program som frågar användaren vilket år det är, därefter ska programmet säga hur många år det är kvar till år 2100.

Lösningsförslag 2.5

Uppgift 2.6

Skapa ett program där användaren får skriva in två tal. Beräkna talens medelvärde och skriv ut det.

Lösningstips 2.6

Kom ihåg att beräkningar med enbart heltal kommer att ge ett heltal som svar. Om du läser in talen från användaren som två int-variabler och sedan delar svaret med 2 så blir svaret ett heltal även om det borde vara ett decimaltal. Om du istället delar med 2.0 så blir svaret ett decimaltal. Ett annat alternativ är att läsa in talen från användaren som två double-variabler.

Lösningsförslag 2.6

Index och bearbetning av text

Med operatorerna från de förra avsnittet så kan man jobba med tal, men med undantag av plustecknet så fungerar de inte med strängar. Vi ska i detta avsnitt se hur man kan bearbeta strängar, och det första vi ska se är hur tecknen i en sträng numreras. Platsen som ett tecken har i en sträng kallas för tecknets index och är helt enkelt tecknets plats i nummerordning där det första tecknet har index 0. I tabellen nedan kan du se vilket index som alla tecken i ordet "Programmering" får.

TeckenProgrammering
Index0123456789101112

Ordet programmering är 13 tecken långt och därför blir ordets tecken numrerade med index från 0 till 12.

Index börjar på 0

Innan man har programmerat ett tag känns det ofta onaturligt att man börjar räkna på 0 istället för 1 i många programmeringssammanhang. Kom ihåg att index alltid börjar på 0 och att det högsta indexet i en sträng är 1 mindre än antalet tecken i strängen, annars kan det leda till att ditt program kraschar.

Med hjälp av vad som kallas för en range på engelska, ungefär intervall eller område på svenska, så kan man klippa ut en del av en sträng. I exemplet nedan visas hur man kan skapa en ny sträng av en range på 3 olika sätt. Notera att den ursprungliga variabeln text inte påverkas av att man skapar nya strängar av den.

string text = "Programmering";

// Klipp ut en ny text från index 2 och 3
string delAvText = text[2..4];

Console.WriteLine(delAvText);

// Skriv ut variabeln text från index 5 till slutet
Console.WriteLine(text[5..]);

// Skriv ut variabeln text från index 0 till 6, alltså de första 7 tecknen
Console.WriteLine(text[..7]);

För att skapa en kopia av en del av variabeln text så skriver man alltså text[a..b] där a är det första index som ska tas med i kopian och b är det första indexet som INTE ska vara med. Båda a och b är valfria att ta med vilket visas av text[5..] och text[..7]. Om både a och b utelämnas kopieras hela strängen.

Med hjälp av det vi nu vet om range och index ska vi ser hur vi kan skapa ett program där användaren skriver in sitt förnamn och efternamn på samma rad, t.ex. "Anna Andersson", och hur vi sedan kan klippa ut för- och efternamn till var sin variabel. För att åstadkomma detta använder programmet också en metod som kan användas med strängar som heter IndexOf och letar reda på den första förekomsten av ett tecken eller sträng inuti en annan sträng.

Console.WriteLine("Vänligen skriv in ditt förnamn och efternamn");
string helaNamnet = Console.ReadLine();

// Hitta mellanslaget i namnet
int mellanslagsIndex = helaNamnet.IndexOf(" ");

// Ta reda på förnamn och efternamn
string förnamn = helaNamnet[..mellanslagsIndex];
string efternamn = helaNamnet[(mellanslagsIndex + 1)..];

Console.WriteLine("Ditt förnamn är " + förnamn + ".");
Console.WriteLine("Ditt efternamn är " + efternamn + ".");

Anta att en person som heter "Anna Andersson" kör detta program. I exemplet sparas vilket index det första mellanslaget finns på i den sträng som användaren skriver in, och för Annas del blir det på index 4 eftersom mellanslaget är det femte tecknet i hennes fullständiga namn. Därmed får variabeln mellanslagsIndex värdet 4. Förnamnet är delen av texten som är helaNamnet[..mellanslagsIndex], vilket blir detsamma som helaNamnet[..4]. Efternamnet är den del av texten som är helaNamnet[(mellanslagsIndex + 1)..], vilket blir detsamma som helaNamnet[5..]. Notera att mellanslaget som är på index 4 inte kommer att kopieras med i varken för- eller efternamnet.

Det går att använda IndexOf-metoden på ett annorlunda sätt än det som visades i det första exemplet, man kan nämligen ange vilket index som man ska börja söka efter en viss sträng på. Detta visas i följande exempel.

string mening = "Här finns flera mellanslag";

int indexFörFörstaMellanslaget = mening.IndexOf(" ");
int indexFörAndraMellanslaget = mening.IndexOf(" ", indexFörFörstaMellanslaget + 1);

Console.WriteLine(indexFörFörstaMellanslaget);
Console.WriteLine(indexFörAndraMellanslaget);

När programmet körs så letas först indexet för det första mellanslaget upp, i detta fall är det på index 3. När det andra mellanslaget ska hittas så anges vilket index som sökningen ska börja på, det kommer att börja på 1 mer än index för det första mellanslaget. Det innebär att sökningen kommer att börja först på index 4 och det första index som har ett mellanslag från index 4 och framåt är index 9. Man anger alltså vilket startindex som sökningen ska ha efter man angett den sträng som man söker efter, notera att man skriver ett kommatecken mellan den sträng man söker efter och vilket startindex sökningen har.

Uppgift 2.7

Skapa ett program där användaren får skriva in en mening (utan punkt) som består av två ord. Skriv ut orden till användaren i omvänd ordning.

Lösningsförslag 2.7

Uppgift 2.8

Skapa ett program där användaren på endast en rad ska skriva in en addition av två heltal som ska utföras . Användaren ska inte skriva några mellanslag, t.ex. kan hen skriva 4+3 eller 10+27. Beräkna svaret och skriv ut det.

Lösningstips 2.8

Använd IndexOf för att hitta indexet för +-tecknet och dela därefter upp strängen som användaren skrev in med hjälp av range. Då kan du sedan omvandla de tal som användaren skrev in med hjälp av int.Parse.

Lösningsförslag 2.8

Ett annat sätt att kombinera text och variabler

Det är möjligt att skriva ut värdet av en variabel tillsammans med text utan att behöva använda plustecken mellan texten och variabeln som vi har gjort tidigare. Man kan istället skriva ut variabelns namn inuti två klammerparenteser. För att man kunna sätta in en variabel i en text med hjälp av klammerparenteser så måste man skriva ett dollartecken innan det första citationstecknet.

Console.WriteLine("Vad heter du i förnamn?");
string förnamn = Console.ReadLine();
Console.WriteLine("Vad heter du i efternamn?");
string efternamn = Console.ReadLine();

// Plusteckensättet
Console.WriteLine("Ditt förnamn är " + förnamn);
Console.WriteLine("Ditt efternamn är " + efternamn);
Console.WriteLine("Du heter " + förnamn + " " + efternamn);

// Dollarteckensättet
Console.WriteLine($"Ditt förnamn är {förnamn}");
Console.WriteLine($"Ditt efternamn är {efternamn}");
Console.WriteLine($"Du heter {förnamn} {efternamn}");

Detta sätt att kombinera text och variabler kan man använda när man vill, det behöver inte vara just när man skriver ut någonting med Console.WriteLine. Ett exempel är följande kod.

string förnamn = "Clara";
string efternamn = "Eklöf";
string utskrift = $"Du heter {förnamn} {efternamn}";

Vilket av sätten man gillar mest är såklart en smaksak, men många brukar tycka att dollarteckensättet är lite mer lättläst när man väl har vant sig vid det jämfört med plusteckensättet som vi hittills har använt. Man har också möjlighet att formatera texten man skriver ut när man dollarteckensättet som du kommer att se i nästa avsnitt så därför kommer dollarteckensättet att användas istället för plusteckensättet i nästan alla program i resten av boken.

Försök alltså att använda detta sätt för att binda samman text och variabler i fortsättningen istället för att använda plustecken.

$ fungerar på andra ställen än Console.WriteLine

Det går bra att använda $ för att koppla ihop variabler när man vill, inte enbart i Console.WriteLine. Här är ett exempel på hur man kan göra detta.

string förnamn = "Jan";
string efternamn = "Björk";
// heltNamn blir "Jan Björk"
string heltNamn = $"{förnamn} {efternamn}";

Uppgift 2.9

Skapa ett program som frågar användaren vad hen heter. Skriv ut användarens namn och en hälsning, använd det nya sättet för att koppla ihop text och variabler, det sätt som börjar med ett dollartecken.

Lösningsförslag 2.9

Blandade uppgifter till kapitel 2

Ny metod

Använd det nya sättet att kombinera text och variabler från och med nu, det som börjar med ett dollartecken!

Uppgift 2.10

Skapa ett program som frågar användaren vilken favoritbok hen har. Skriv därefter ut namnet på denna bok.

Lösningsförslag 2.10

Uppgift 2.11

I en längdhoppstävling så hoppade Elin längre än Alma. Skriv ett program som frågar hur långt Elin och Alma hoppade mätt i meter. Skriv därefter ut hur mycket längre som Elin hoppade.

Lösningsförslag 2.11

Uppgift 2.12

Skapa ett program som ska hjälpa användaren att beräkna kostnaden för att hyra bil hos en biluthyrningsfirma. Startavgiften för att hyra bilen är 300 kr, därefter så kostar det ytterligare 1 krona per kilometer man kör och 500 kronor för varje extra dag man vill hyra den förutom den första. Programmet ska fråga användaren hur många dagar hen vill hyra bilen och hur många kilometer som hen ska köra, därefter ska den totala hyran skrivas ut.

Lösningstips 2.12

Kostnaden kommer att beräknas med formeln 300 + (antalDagar - 1) * 500 + antalKilometer.

Lösningsförslag 2.12

Uppgift 2.13

Skapa ett program där användaren ska mata in lönen för 3 anställda på ett företag. Beräkna medellönen för personalen.

Lösningstips 2.13

Kom ihåg att om alla tal i en beräkning är heltal så kommer svaret att bli ett heltal. Dela summan av de tre talen med 3.0 istället för 3 eller så kan du läsa in talen som double istället för int.

Lösningsförslag 2.13

Uppgift 2.14

Skapa ett program där användaren ska skriva in en beräkning innehållande två decimaltal och ett gångertecken på samma rad, t.ex. 5,2*3,8. Programmet ska utföra beräkningen och berätta vad svaret är.

Lösningstips 2.14

Använd IndexOf för att hitta indexet för *-tecknet och dela därefter upp strängen som användaren skrev in med hjälp av range. Då kan du sedan omvandla de tal som användaren skrev in med hjälp av double.Parse.

Lösningsförslag 2.14

Uppgift 2.15

Skapa ett program där användaren ska skriva in en mening med tre ord, meningen ska avslutas med en punkt. Skriv ut orden till användaren i omvänd ordning, det ska vara en punkt i slutet.

Lösningstips 2.15

Använd IndexOf och range flera gånger. Börja med att leta efter ett mellanslag så du kan ta reda på det första ordet. Skapa en sträng som består av det som är efter det första mellanslaget och leta efter ett mellanslag i denna sträng. Fortsätt att använda IndexOf och range för att få varje ord i en egen sträng.

Lösningsförslag 2.15