Föreläsning 1: Momstabellen i C++

Relevanta dokument
TDIU01 (725G67) - Programmering i C++, grundkurs

C++ - En introduktion

Exempel på ett litet Ada-program

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p

TDIU01 - Programmering i C++, grundkurs

TDDC76 - Programmering och Datastrukturer

C++ - En introduktion

5 Grundläggande in- och utmatning

TDIU01 - Programmering i C++, grundkurs

Introduktionslaboration

Föreläsning 4: Poster

Föreläsning 0: Introduktion av Ada

Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

Programmeringsteknik med C och Matlab

Linköpings Tekniska Högskola Instutitionen för Datavetenskap (IDA) Torbjörn Jonsson, Erik Nilsson Lab 2: Underprogram

Introduktionslaboration

Grunderna i C++ T A. Skapad av Matz Johansson BergströmLIMY

TDIU01 - Programmering i C++, grundkurs

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

Introduktion till MATLAB, med utgångspunkt från Ada

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

Klassdeklaration. Metoddeklaration. Parameteröverföring

Programmering i C++ EDA623 Strömmar och filer. EDA623 (Föreläsning 9) HT / 19

Uttryck, satser och strömhantering

kl Tentaupplägg

C++ Funktioner 1. int summa( int a, int b) //funktionshuvud { return a+b; //funktionskropp } Värmdö Gymnasium Programmering B ++ Datainstitutionen

OBS! All teori i detta och följande dokument kompletteras med genomgångar på lektionerna. Så det är viktigt att närvara och göra egna anteckningar.

LÖSNINGSFÖRSLAG TILL Tentamen i objektorienterad programmering i C++ I

C++ Lektion Tecken och teckenfält

Variabler och konstanter

kl Tentaupplägg

Övningsuppgifter till föreläsning 2 Variabler och uttryck

Tentamen Grundläggande programmering

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Muddy cards. Slingor

kl Tentaupplägg

Objektorienterad Programmering (TDDC77)

I Skapa Hej.java och skriv programmet. I Kompilera med javac Hej.java. I Rätta fel och repetera tills du lyckas kompilera ditt program

Uppgift 1a (Aktiekurser utan poster)

Prova på-laboration i Ada

C++ Slumptalsfunktioner + switch-satsen

Enkla datatyper minne

F4. programmeringsteknik och Matlab

kl Tentaupplägg

Föreläsning 5: Introduktion av pekare

PROGRAMMERING 2 GRUNDLÄGGANDE SEMANTIK 4

En villkorssats är den konstruktion som finns i C++ för att göra en selektion av två alternativa sekvenser. Formen för if satsen är

FÖRSLAG TILL LÖSNING AV Tentamen i Objektorienterad programmering C++ I

Uppgift 1 (grundläggande konstruktioner)

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Felsökning. Datatyper. Referenstyper. Metoder / funktioner

Uppgift 1 ( Betyg 3 uppgift )

Föreläsning 3: Typomvandling, villkor och val, samt textsträngar

Föreläsning 2 Programmeringsteknik och C DD1316. Mikael Djurfeldt

Det finns många flaggor till g++,

TDIU01 - Programmering i C++, grundkurs

Pascal. reserverade ord fördefinierade funktioner och procedurer egendefinierade funktioner, procedurer och objekt

1 Funktioner och procedurell abstraktion

Datatyper och kontrollstrukturer. Skansholm: Kapitel 2) De åtta primitiva typerna. Typ Innehåll Defaultvärde Storlek

kl Tentaupplägg

Funktionens deklaration

Avrundning och manipulatorer

Föreläsning 2. Variabler, tilldelning och kodblock{} if-satsen Logiska operatorer Andra operatorer Att programmera

Dagens föreläsning. Repetition. Repetition - Programmering i C. Repetition - Vad C består av. Repetition Ett första C-program

Uppgift 1 ( Betyg 3 uppgift )

Pascal... Pascal. Pascal... Pascal...

kl Tentaupplägg

Objektorienterad Programmering (TDDC77)

System.out.println("Jaså du har "+ antalhusdjur+ " husdjur"); if ( antalhusdjur > 5 ) System.out.println("Oj det var många);

Planering Programmering grundkurs HI1024 HT TIDAA

Beräkningsvetenskap föreläsning 2

Föreläsning 10 Datalogi 1 DA2001. Utskrift på skärmen. Syntax. print( Hej ) Hur är det? Hej. print( Hej,end= ) print( Hur är det? ) HejHur är det?

Uppgift 1 (Sorterade heltal som är OK)

Visual Basic, en snabbgenomgång

Föreläsning 6: Introduktion av listor

Programmering i C++ EDAF hp. EDAF30 (Föreläsning 2) HT / 18

TDDE10 TDDE11, 725G90. Gemensam kurswebsida på:

MMA132: Laboration 2 Matriser i MATLAB

TENTAMEN TDDB53. Programmering i Ada för MI (provkod TEN2) den 7 april 2010 kl Institutionen för datavetenskap, IDA Olle Willén mars 2010

Programmering i C, 7,5 hp

kl Tentaupplägg

Backcode. Jonathan Crusoe TDP019 Projekt: Datorspråk Linköpings universitet

Sockets: server. with Ada.Command_Line; use Ada.Command_Line; with Ada.Exceptions; use Ada.Exceptions; with Ada.Text_IO; use Ada.

Python. Python är, som Scheme, ett interpreterat språk men det finns kompilatorer för Python.

Användarhandledning Version 1.2

EDAf30: Programmering i C++, 7.5 hp. EDAf30: Programmering i C++, 7.5 hp Administration. EDAf30: Programmering i C++, 7.5 hp Obligatoriska moment

kl Tentaupplägg

Python. Python är, som Scheme, ett interpreterat språk men det finns kompilatorer för Python.

Föreläsning 3-4 Innehåll. Diskutera. Metod. Programexempel med metod

TUTORIAL: KLASSER & OBJEKT

Introduktion till algoritmer - L0 - Grunder i C++ Matematikgymnasiet, Läsåret L0 - Grunder i C++

Planering Programmering grundkurs HI1024 HT data

Uppgift 1 (vadå sortering?)

Grundläggande programmering med C# 7,5 högskolepoäng

Uppgift 1 ( Betyg 3 uppgift )

Föreläsning 3-4 Innehåll

Planering Programmering grundkurs HI1024 HT 2014

Lektion 1 - Steg 1. Introduktion. Hello World

Operatorer Tilldelning Kodblock { } if satsen Logiska uttryck Att programmera

Programmering för språkteknologer I, VT2012. Rum

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Strukturdiagram. Styra. Algoritmer. Val

Parameteröverföring. Exempel. Exempel. Metodkropp

Transkript:

Nu sätter vi igång med C++! Föreläsning 1: Momstabellen i C++ På den här föreläsningen skall jag ta ett stort exempel och ett par små och med dessa hoppas jag att täcka in mycket av det som är grundläggande. Idag är tanken att vi skall hinna med hur man skriver ett litet c++-program, hur satser (tilldelning, if-satser, loopar, m.m.) ser ut i c++ och en del annat. I det första exemplet skall vi ta ett gammalt välkänt problem som vi redan har löst och titta på övergången mellan Ada och c++. Här är problemet: Skriv ett program som låter användaren mata in två priser och ett steg (realla tal) och som sedan skriver ut en momstabell. Momssatsen är alltid 25%. Programmet skall göra rimlighetskontroller på indatat. Körexempel: Mata in första pris (mellan 0 och 100): 10 Mata in sista pris (minst första pris): 12 Mata in steglängd: 0.3 MOMSTABELL (mini) 10.00 2.50 12.50 10.30 2.58 12.88 10.60 2.65 13.25 10.90 2.73 13.62 11.20 2.80 14.00 11.50 2.88 14.38 11.80 2.95 14.75 Detta känner vi igen, det är ju vår gamla lab 1 (i princip). Vi rotar fram koden och modifierar lite, då får vi (lämplig att dela ut, eller köra på OH) mom.adb:

1 with Ada.Text_IO; use Ada.Text_IO; 2 with Ada.Float_Text_IO; use Ada.Float_Text_IO; 3 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; 4 5 procedure Mom is 6 7 Fp : Float; 8 Lp : Float; 9 S : Float; 10 M : Float; 11 12 N : Integer; 13 14 begin 15 Put("Mata in första pris (mellan 0 och 100): "); 16 Get(Fp); 17 while Fp < 0.0 or Fp > 100.0 loop 18 Put("ERROR: Mata in första pris igen: "); 19 Get(Fp); 20 end loop; 21 22 loop 23 Put("Mata in sista pris (minst första pris): "); 24 Get(Lp); 25 if Lp >= Fp then 26 exit; 27 end if; 28 end loop; 29 30 Put("Mata in steglängd: "); 31 loop 32 Get(S); 33 exit when S > 0.0; 34 Put("ERROR: Mata in steglängd igen: "); 35 end loop; 36 37 M := 25.0; Svensk normalmoms (för kläder) 38 39 N := Integer(Float'Floor((Lp fp) / S + 1.0)); 40 41 Put_Line("MOMSTABELL (mini)"); 42 for I in 0.. N 1 loop 43 Put(Fp + Float(I) * S, 44 Fore => 5, Aft => 2, Exp => 0); 45 46 Put((Fp + Float(I) * S) * M / 100.0, 47 Fore => 7, Aft => 2, Exp => 0); 48 49 Put((Fp + Float(I) * S) * (1.0 + M / 100.0), 50 Fore => 7, Aft => 2, Exp => 0); 51 52 New_Line; 53 end loop; 54 end Mom; 55

Ett par korta kommentarer om detta program: Vi har ett par olika varianter på rimlighetskontrollerna. Detta för att vi skall få se lite olika skrivsätt när vi går över till c++. Många brukar lösa den här laborationsuppgiften med en while för själva tabellutskriften. I detta exempel har jag valt att använda en for (egentligen är detta bättre) och helt enkelt räkna ut hur många varv som loopen skall gå. Vi sätter igång på direkten. I den här kursen kommer ni att fortsätta att programmera i emacs (eller vad ni nu har använt tidigare) så det är precis samma som när vi skulle skapa ett ada-program. Vi skapar en ny fil som vi kallar för mom.cpp. Vad skriver vi nu i denna? Jo vi börjar, precis som i ada, med själva programskellettet, vilket är ganska simpelt: 1 int main() 2 { 3 4 return 0; 5 } Vad innebär nu detta? Från Ada är vi vana vid att kunna döpa vårt huvudprogram till vad vi vill, eller snarare att huvudprogrammet heter ju som filen. I C++ heter huvudprogrammet alltid main. Parenteserna efter main är en parameterlista. Man kan alltså lägga till parametrar till huvudprogrammet. Vi kommer senare att se att det är här man kan lägga till saker om man vill ha kommandoradsargument till sitt program, vi hoppar över det så länge. Klamrarna (eller måsvingarna, eller vad man nu vill kalla dem) markerar att här börjar ett block, vi kan tänka på det som "begin" och "end" från ada. Alla konstruktioner som spänner över flera satser kommer behöva sådana block (t.ex. if-satser och loopar). Dessa talar alltså om vilka satser som hör till huvudprogrammet. Ordet "int" precis innan main beskriver returtypen för funktionen. Funktionen? Jajemän i c++ är även ditt huvudprogram en funktion precis som alla andra underprogram (det finns inga procedurer). Detta hänger alltså ihop med att vi returnerar ett tal längst ner i programmet. Varför skall man returnera ett heltal då? Jo, egentligen är det så att program bör returnera ett tal som talar om hur de avslutades. Att returnera 0 betyder att programmet avslutades normalt, allting annat kommer betyda att något gick fel under körning. Ett program kan på ett sådant sätt returnera "felkoder". Vi kommer inte jobba jättemycket med det. Skulle man glömma att göra "return 0;" i sitt program så kommer faktiskt kompilatorn lägga till det åt dig, men man skall ha "int" som returntyp för sitt huvudprogram i c++. Innan vi går vidare så kan jag bara säga något om hur vi kompilerar. Vi kommer att använda kompilatorn g++ (en del av gcc, precis som gnatmake). För att kompilera detta skulle vi alltså skriva: g++ mom.cpp Om det blir kompileringsfel eller varningar så kommer g++ att beskriva dessa. Nu vill jag varna er lite, g++ är inte alls lika snäll som gnatmake. Ta det därför lugnt i början och kompilera ofta så att ni slipper många fel samtidigt. Det är också så att g++ inte varnar på lika mycket som t.ex. gnatmake gjorde, för att få det beteendet måste man själv lägga till varningsflaggor t.ex. -Wall och -Wextra. Så här: g++ Wall Wextra mom.cpp Om ni kompileringen gick bra så kommer man få den körbara filen a.out (den heter alltid så). Vill man att den körbara filen skall heta något annat så kan man lägga till flaggan -o och sedan namnet: g++ mom.cpp o mitt_program Nu skulle alltså den körbara filen heta mitt_program. På vår hemsida kommer vi ha en liten "kom igång"- sida länkad vid laborationerna om vilka flaggor som kan vara bra att använda, och lite andra justa tips.

Nu tittar vi tillbaka i mom.adb. Vad gjorde vi där? Jo först så deklarerade vi lite variabler. Ett c++-program är inte uppdelat i en deklarationsdel och en satsdel. Man får alltså deklarera variabler vart man vill i sin kod, vi måste inte deklarera dem i början. Vi kan ju börja med ett par stycken, så här deklarerar jag variabler: 1 int main() 2 { 3 double fp; 4 double lp, s; 5 6 return 0; 7 } Man skriver alltså datatypen först och sedan namnet på sin variabel. Här är det "double" som är datatypen. I c++ finns float också, men vill man representera realla tal så används vanligtvis double eftersom den har mer precision. Precis som i Ada kan jag deklarera två variabler samtidigt (rad 4). Värt att nämna också är att c++ skiljer på stora och små bokstäver, så kompilatorn kommer inte att förstå om vi senare t.ex. skriver "FP". Här är lite andra datatyper i c++ (och motsvarigheten i Ada): Ada Float Integer Character Boolean String C++ float (double används oftast) int char bool string Vad är nästa sak som skall ske? Jo vi skall skriva ut lite text. I C++ använder vi cout till detta. cout är en utmatningsström som skriver ut till standard out d.v.s. till terminalen. Precis som i ada finns den inte i språkets "kärna" utan vi måste lägga till något, biblioteket iostream, detta gör vi med preprocessorkommandot #include. Detta talar om för preprocessorn (något som körs innan kompilatorn) att den även skall ta med rutinerna i iostream innan vi kompilerar. Man kan tänka på detta som "with" i Ada, fast i c++ är det mer att vi "klipper och klistrar" med koden. Precis som i Ada så kan man nu göra något ytterligare för att vi sedan bara ska behöva skriva cout. Ni kom väl ihåg när vi började och var tvugna att skriva Ada.Text_IO.Put hela tiden? Det är samma sak nu. Gör vi nu inget mer så måste vi skriva std::cout varje gång vi vill använda cout. Gör vi inte det så kommer kompilatorn bråka om att cout inte är deklarerad. "std" är nämligen den namnrymd som cout tillhör. Om vi då skriver till using namespace std; är det sedan fritt fram att bara säga cout. Namnrymder kan (till skillnad från att göra "use" på ett paket i Ada) spänna över flera bibliotek. Allt som allt får vi: 1 #include <iostream> 2 3 using namespace std; 4 5 int main() 6 { 7 double fp; 8 double lp, s; 9 10 cout << "Mata in första pris (mellan 0 och 100): "; 11 Just "<<" är en operator för "formaterad utmatning", mer om det senare. För tillfället kan vi se detta som att vi skickar strängen till cout, detta motsvarar alltså Put i Ada. Nu vill vi låta användaren mata in ett första pris. Inmatning gör man med couts motsvarighet, cin, som läser från standard in d.v.s. tangentbordet. Hur ser detta ut, jo så här:

12 cin >> fp; Detta motsvarar alltså Get (för flyttal) i Ada. ">>" är operatorn för "formaterad inmatning" vad detta innebär vet ni egentligen redan från hur Get beter sig i Ada. D.v.s. läs bort inledande vita tecken, läs sedan in något som kan tolkas som ett flyttal, t.ex. 10.0. Om vi nu tittar i Ada-koden så ser vi att vi vill ha en while-loop. Att göra detta i c++ blir mycket likt: 13 while (fp < 0.0 fp > 100.0) 14 { 15 cout << "ERROR: Mata in första pris igen: "; 16 cin >> fp; 17 } 18 Skillnaderna är som sakt mycket små. Det är den logiska operatorn "or" som har bytts mot " ". Vi har inget ord "loop" eller "end loop", vi använder klamrarna istället. Det går att skippa klamrarna om man bara har en sats i loopen (samma med if-satser) men gör inte det, ha alltid med dem. Det blir så lätt fel om man senare går tillbaka och lägger till en till sats. Jag vill passa på att säga att vita tecken inte har någon betydelse, precis som i Ada (om man inte råkar slå ihop två ord eller bryta isär t.ex. while till whi le). Exakt vart man sätter sina radbrytningar och hur många mellanslag man vill ha bestämmer man alltså lite själv. Givetvis är det bra att följa någon sorts kodstil. Vi på kursen (och i följande kurser) kommer t.ex. alltid sätta klamrarna på egen rad, i indenteringsnivå med den sats de tillhör. Nu tittar vi på nästa loop (d.v.s den som börjar på rad 22 i Ada-koden). Detta är ju någon form av loop med ett villkor, precis som while, fast kontrollen av villkoret är i slutet. I Ada finns det ingen sådan inbygd loop så man har här använt den vanliga "loop" och satt en if-sats med en "exit" sist. I c++ och c-relaterade språk finns det dock just en sådan loop som vi vill ha, den heter do-while: 19 do 20 { 21 cout << "Mata in sista pris (minst första pris): "; 22 cin >> lp; 23 } 24 while (lp < fp); Eftersom villkoret nu talar om när loopen skall fortsätta, snarare än när loopen skall avbrytas måste vi nu vända på villkoret. Det fanns alltså en sats i c++ som inte fanns i Ada! Språk är olika helt enkelt. Det är inte så att vissa språk är "bättre" än andra, utan de är "bättre" i vissa givna situationer. I vårt fall såg vi att det inte spelade någon roll att do-while inte fanns i Ada, vi kunde lösa det ändå. Nu kommer vi till något som finns i Ada men inte i c++, nämligen nästa loop (rad 31). Den här loopen avbryts mitt i. C++-motsvarigheten till "exit" är break, så det kan vi fixa, men hur får vi en loop som motsvarar Adas "loop". Här kan man göra på lite olika sätt, men det vanligaste är att man använder en while med ett villkor som alltid är sant, t.ex. true: 25 cout << "Mata in steglängden: "; 26 while ( true ) 27 { 28 cin >> s; 29 if ( s > 0.0) 30 { 31 break; 32 } 33 cout << "ERROR: Mata in steglängden igen: "; 34 }

Vi blir tvugna att ta till en if-sats för vår break. Just "exit when" är en ada-specialitet. If-satsen i c++ är mycket lik den i Ada. Vi har inget "then" eller "end if", vi använder klamrar istället. Det finns självklart else, och också else if. Nu kommer vi fram till den punkt då vi vill sätta att momsen skall vara 25% (rad 37). I vårt c++-program har vi ju inte ens deklarerat m än. Det kan vi göra nu. Vi kan samtidigt passa på att säga att m skall vara en konstant, då måste vi sätta ms värde direkt: 35 const double m = 25.0; "const" marekare alltså att m är ett data som inte får ändras senare i vårt program. Tilldelning gör vi med "=", alltså inte ":=" som i Ada. Man kan då fundera på hur man jämför om två saker är lika i C++, jo med "==", mer om det senare. Just att tilldela en variabel då den deklareras kallas för initiering. Det finns en nyare, mer modern syntax för detta som använder klamrar, jag kommer tillbaka till den strax. Nu vill vi beräkna hur många varv som den kommande for-satsen skall gå. Vi deklarerar därför variabeln n och tilldelar den resultatet från ett uttryck: 36 int n; 37 n = floor((lp fp) / s) + 1.0); Saknas det inte något? Tja, det ser lite märkligt ut eftersom högerledet här verkar ju bli ett flyttal (double) medan till till vänster är heltal. Här sker en automatisk omvandling från double till int. C++ är ett typat språk, men det kan ske automatiska omvandlingar, så det gäller att se upp lite. funktionen "floor" avrundar nedåt och finns inuti ett annat bibliotek som heter cmath, så det får vi lägga till längst upp. I detta fall skulle man faktiskt inte behöva göra "floor" eftersom den automatiska omvandlingen trunkerar (hugger av decimalerna). Nu skall vi bara skriva ut en rad till (rubriken på tabellen), och dessutom göra ett new_line: 38 cout << "MOMSTABELL (mini)" << endl; Man kan göra radbrytningar med specialtecknet '\n'. En "endl" gör precis detta och "flushar" dessutom utmatningsbufferten så att man vet att texten verkligen har skrivits ut innan man går vidare till andra satser. Nu till själva tabellen. Hur ser en for-loop ut i c++? Tja egentligen är det bara en glorifierad while, en while++. Generellt så skriver man den på detta sätt: Villkor för att fortsätta upprepa. for ( ; ; ) Satser som görs en gång innan första varvet Satser som görs i slutet av varje varv. Vi kan alltså formulera vår for-loop på detta sätt: 39 for ( int i = 0 ; i < n ; ++i ) 40 { Innan första varvet vill vi ju ha en ny variabel (precis som vi får från Adas for-loop). I C++ deklarerar vi den i for-satsens första del. Den variabeln kommer bara att existera i for-satsens block. Det är det vi är vana vid

från Ada. Villkoret för att fortsätta är att i håller sig mindre än n, d.v.s det sista värde som i får anta är n - 1. I slutet av varje varv vill vi räkna upp i med 1. Vi hade lika gärna kunnat skriva i = i + 1 här, men vi kan passa på att introducera preinkrementsoperatorn ++ som gör precis samma sak. Här är lite andra varianter: i++ postinkrement, räknar upp i men returnerar det gamla värdet. i += 1 exakt samma som att skriva i = i + 1. Tycker man att dessa verkar krångliga så är det helt ok att skriva i = i + 1. Nu är vi snart klara. Vi skall bara skriva ut raderna i vår tabell. Vi kan använda cout för att skriva ut flyttal också, men om vi inte säger något extra blir det inte snyggt (vi får inte ut några decimaler!). För att säga hur många decimaler man vill skriva ut med så kan man använda utskriftsmanipulatorn setprecision, och fixed. När man använder dessa så kommer de att gälla för alla utskrifter som görs till cout framöver. cout << setprecision(2) << fixed << fp; //skriver ut fp med två decimaler För övrigt är "//" kommentarsymbolen i c++. Man kan även göra kommentarer som spänner över flera rader med "/*" och "*/", men gör inte det, det brukar sällan bli bra. Vi vill också säga att vi vill att talet skall skrivas ut med en viss bredd, det kan vi göra med manipulatorn setw. Detta kommer att ange bredden för hela talet, vi räknar lite och kommer fram till att det borde bli 8. (I Ada-koden var ju Fore 5. Med två decimaler och en plats för decimalpunkt blir detta 8). Setw (till skillnad från setprecision) gäller bara för just nästa utskrift dock: 41 cout << setprecision(2) << fixed 42 << setw(8) << fp + i * s; Obs: åter igen sker en automatisk typomvandling på rad 42 (i är ju int). Vi ser nu att setprecision och fixed alltså borde kunna ligga utanför loopen, men men. Utskriftsmanipulatorerna ligger i biblioteket iomanip, så det får vi också lägga till längst upp. Nu behöver vi bara skriva ut resten. Man kan skicka många saker till cout när man ändå håller på: 43 cout << setw(10) 44 << (fp + (i * s)) * m / 100.0 45 << setw(10) 46 << (fp + i * s) * (1.0 + m / 100.0); 47 << endl; 48 49 } // slut på for loopen Så! Det var hela programmet. Nu tänkte jag gå över och titta på ett annat exempel som illustrerar lite mer I/O. Säg att vi vill ha ett program som låter användaren mata in sitt för- och efternamn (två ord) och sin hobby (en hel rad text). Programmet skall sedan upprepa tills man väljer att avsluta. Körexempel: Mata in ditt för och efternamn: Eva Andersson Mata in din hobby: Åka snowboard och skidor Vill du avsluta (j/n): n (programmet upprepar) I c++ löser vi lätt de två första problemen med datatypen string. En string i c++ kan innehålla godtyckligt många tecken - hurra! Det är alltså inte riktigt så enkelt som i Ada där strängar helt enkelt var fält av tecken.

Exakt hur string är implementerad kan vi titta på någon annan gång, just nu är vi intresserade av hur vi använder den: 1 #include <iostream> 2 3 using namespace std; 4 5 int main() 6 { 7 string first_name, last_name; 8 9 10 11 cout << "Mata in ditt för och efternamn: "; 12 cin >> first_name >> last_name; 13 14 return 0; 15 } Med formaterad inmatning läser cin alltså tecken till strängen tills den stöter på ett vitt tecken. Detta fungerar bra för inläsningen av våra namn. Hur gör vi med hobbyn, det skulle ju vara en hel rad. Lyckligtvis finns det en bra rutin för detta, nämligen get_line, som läser in ända till radslut: 14 15 cout << "Mata in din Hobby: "; 16 getline(cin, hobby); Vi får lägga till hobby bland våra strängvariabler. Nu måste vi dock tänka till lite om tangentbordsbufferten igen. Efter första inmatningen kommer det ju att ligga ett enter-tecken kvar i bufferten. Det innebär ju att getline direkt kommer att ta detta som att användaren skrev in 0 tecken på hobbyn. Mellan inmatningarna måste vi alltså rensa bufferten, en Skip_Line från Ada hade varit trevligt. I C++ finns en liknande rutin som heter ignore som anropas direkt på cin. Till den skickar man hur många tecken som skall ignoreras och vilket tecken som ignoreringen skall sluta vid. Vi lägger alltså till efter den första inmatningen: 13 cin.ignore(1000, '\n'); Detta betyder alltså, börja kasta bort tecken tills antingen du har kastat bort ett entertecken eller tills du har kastat bort 1000 stycken. Varför valde jag just 1000? Tja, om det skulle komma mer skräp innan entertecknet. Nu fungerar ju inte detta om det råkar vara mer än 1000 skräptecken, så egentligen skulle jag vilja göra detta på något mer generellt sätt, men det löser vi inte nu. Nu skall dessa upprepas, så vi lägger på en do-while. Men vad skall vi ha för krav på avslutandet av loopen? Jo, vi låter användaren mata in ett tecken. Vi deklarerar variabeln c (med datatypen char) och läser in endast ett tecken. Det kan vi göra med rutinen get. Nu ser programmet ut så här:

1 #include <iostream> 2 3 using namespace std; 4 int main() 5 { 6 string first_name, last_name; 7 string hobby; 8 char c; 9 do 10 { 11 cout << "Mata in ditt för och efternamn: "; 12 cin >> first_name >> last_name; 13 cin.ignore(1000, '\n'); 14 15 cout << "Mata in din hobby: "; 16 getline(cin, hobby); 17 cout << "Vill du avsluta (j/n): "; 18 cin.get(c); 19 } 20 while (c!= 'j'); 21 22 return 0; 23 } Här är det viktigt att man faktiskt skriver "!=", det är operatorn "skiljt ifrån". Okej vi hade ju lika gärna kunnat skriva "c == n", men om vi skulle använda Adas operatorer "/=" eller "=" så skulle detta tolkas som något helt annat. "=" är ju faktiskt tilldelning, och tilldelning returnerar ett värde i C++. Alltså skulle det fortfarande gå att kompilera men programmet skulle bete sig mycket underligt. Jag varnar alltså därför åter en gång, tänk till när ni skriver "=" i c++, är det tilldelning eller jämförelse ni menare. Detta är en superlätt grej att göra fel på när man är ny.

Innan vi avslutar så skall jag ta ett litet exempel till. Man kan faktiskt läsa tecken från tangentbordet tills det "tar slut". Ett sådant slut brukar kallas för filslut och markeras med ctrl-d. Nu skall vi göra ett program som läser tecken till filslut och summerar hur många vita tecken som matades in. När man använder cin för att läsa in så returneras det alltid sant eller falskt. Så länge det gick bra att läsa så returneras sant, om det inte går bra (t.ex. för att indatat har "tagit slut") så kommer falskt att returneras. Det betyder att man kan sätta själva inläsningen i en while-loops villkor: 1 #include <iostream> 2 #include <cctype> 3 4 using namespace std; 5 6 int main() 7 { 8 char c; 9 int num_spaces{0}; 10 while ( cin.get(c) ) 11 { 12 if (isspace(c)) 13 { 14 num_spaces += 1; 15 } 16 } 17 18 cout << "Du skrev in " << num_spaces 19 << " vita tecken." << endl; 20 21 return 0; 22 } På rad 9 vill vi initiera variabeln num_spaces till 0. Vi skulle kunna göra detta med tilldelningsoperatorn ("=") men jag visar här ett annat sätt att initiera variabler på. Funktionen isspace finns i biblioteket cctype. Där finns det en hel del bra rutiner för att hantera tecken, t.ex. rutiner för att kolla om något är en stor bokstav, om ett tecken är ett numeriskt tecken o.s.v.