Göm menyn

961G24 Programmering i text-baserad miljö

Styrstrukturer (if-satser och loopar)

Styrstrukturer

De program vi har tittat på hittils är helt sekvensiella. De är raka. De är ungefär som stationerna på en tipspromenad. Först går man till fråga 1, svarar på den, sedan går man till fråga 2 o.s.v.

Det finns många exempel på program där sekvens räcker fullt och gott för att lösa den uppgift som skall lösas. Ibland (oftast) räcker det dock inte. Man inser ganska snart att man vill kunna göra olika saker beroende på vad som har hänt tidigre.

If-satser

Vi tänker oss t.ex. situationen då man kommer hem från arbetet, lite lagom trött. Helst av allt kanske man bara vill slå sig ner i soffan och titta på TV ett par minuter, men det kan ju vara så att någon har lämnat disk i köket - då måste man ställa sig och diska. Först när disken är omhändertagen kan man slå sig ner framför TVn. Om detta hade varit ett program så kanske det hade sett ut så här:


kom_hem_från_jobbet
om disk_i_köket?
  ställ_dig_och_diska
titta_på_tv

Med detta menar vi självklart att vi bara gör "ställ_dig_och_diska" i det fall då "disk_i_köket?" är ett sant påstående. Om "disk_i_köket?" är falskt så hoppar vi över den inskjutna satsen och går direkt ner till "titta_på_tv".

Detta är grundtänket bakom if-satsen, som finns i nästan alla programmeringsspråk. Det är en sats som låter oss testa ett påstående (ett villkor) och som sedan utför vissa satser om villkoret var sant. Hade villkoret varit falskt hoppar man över de omslutna satserna. I python ser satsen ut så här:


if villkor:
  satser

Vad är då ett villkor? Ja det kan vara vad som helst som kan utvärderas till sant eller falskt, eller som det heter i python, True och False. Här är ett litet exempel:


x = input('Mata in ditt namn: ')
if x == 'Erik':
    print('Du är bäst!')
print('Kämpa på ' + x)

I detta fall är alltså villkoret x == 'Erik', vilket endast är sant om variabeln x innehåller exakt strängen 'Erik'. Skulle så vara fallet så kommer programmet skriva ut "Du är bäst!" och sedan "Kämpa på Erik". Om x skulle innehålla något annat än 'Erik', t.ex. 'Emma' så kommer det bara ut "Kämpa på Emma" Observera att vi använder två likmedstecken för att jämföra likhet, eftersom ett enstaka likmedstecken används för tilldelning.

En annan observation är den faktiska inskjutningen för raden "print('Du är bäst!')". Detta kalls för indentering. I många språk är detta bara en estetisk grej för programmeraren, så att man lättare ser vilka satser som påverkas av if-satsen (det kan vara fler än en), och vilka som inte gör det. I Python är dock indenteringen obligatorisk och programmet går inte att köra om man inte skjuter in den raden.

Regeln här är att satser som tillhör samma stycke (vi kallar dem för block) måste skjutas in lika mycket. Det vanliga är att man skjuter in satserna fyra blanksteg. I de flesta texteditorer så sker detta automatiskt när man står med markören i början av raden och trycker på tab-knappen.

Else

Det är inte ovanligt att man vill utföra andra satser i de fall då uttrycket är falskt. Vi fortsätter på exemplet ovan:


x = input('Mata in ditt namn: ')
if x == 'Erik':
    print('Du är bäst!')
else:
    print('Du är OK!')
print('Kämpa på ' + x)

Med tilläget med else:-delen (blocket, eller grenen) så kan vi lägga till satser som körs då (och endast då) x inte är lika med 'Erik'. Skulle man nu mata in 'Emma' till programmet så kommer det komma ut "Du är OK" och sedan "Kämpa på Emma". Behändigt i många fall.

Observera, om man bara vill utföra satser då ett villkor är falskt så är det nog lättare att vända på villkoret än att använda else:


x = input('Mata in ditt namn: ')
if x != 'Erik':
    print('Du är OK!')
print('Kämpa på ' + x)

"x != 'Erik'" betyder alltså om x är skiljt ifrån 'Erik'.

Man hade även kunnat skriva:


if not x == 'Erik':

Vilket kanske är graciösare, åt minstone rent grammatiskt. Observera att det inte är obligatoriskt att använda else. Det är något man kan koppla på om man behöver det.

Else if

Slutligen kommer vi till begreppet else if. Detta tillåter oss att haka på flera villkor efter det initiala. Titta på följande exempel:


x = int(input('Mata in ett heltal: '))
if x == 0:
    print('x var 0')
elif x > 0:
    print('x var positivt')
else:
    print('x var negativt')

Med tilläget med elseif-grenen kommer vi nu (det fall där x inte är 0) kontrollera huruvida x är större än 0. Är x större än 0 kommer vi då att skriva ut "x är positivt" och sedan gå ur hela if-satsen. Om både villkoren är falska så går vi till else-delen och skriver ut att "x var negativt". Nu ett par observationer:

  • Man går endast in på ett ställe i en if-sats. Vid det först sanna villkoret.
  • Man kan ha hur många "elif" som man vill.
  • Man kan bara ha en "else".
  • Man går bara in i "else" om ingen av de ovanstående villkoren var sanna.

Logiska operatorer

Vill man kombinera villkor så kan man använda de logiska operatorerna or och and. T.ex. så här:


x = int(input('Mata in ett heltal: '))
y =  int(input('Mata in ett till heltal: '))
if x == 0 and y > 0:
    ...
elif x < 0 or y < 0:
    ...

Här går vi alltså endast in i den första grenen om det både gäller att x är 0 och y är positivt. Om logiska uttryck blir krångliga kan man alltid använda parenteser för att förtydliga hur man menar. T.ex:

if not (x > 0 or (y < 0 and x == 0)):

If-satser i if-satser

Det är fullt möjligt att ha en if-sats inne i en annan if-sats. T.ex. så här:


if x > 0:
    if y > 0:
        print('Både x och y är positiva')

Observera att detta är ju samma sak som att skriva:

if x > 0 and y > 0:

Övningar

Uppgift 1 Skriv ett program där användaren får mata in två heltal. Programmet skall sedan mata ut det största av dessa två heltal.

Körexempel:

Mata in ett tal: 15
Mata in ett till tal: 8
15 var störst.

Uppgift 2

Skriv ett program där användaren matar in två flyttal X och Y. Vi tänker oss att X och Y är koordinaterna för en punkt i ett kartesiskt koordinatsystem. Ditt program skall sedan mata ut i vilken kvadrant punkten ligger. Om Punkten ligger på en av axlarna eller i origo, skall programmet säga det istället för kvadrant.

Körexempel 1:

Mata in X: 3.0
Mata in Y: -5.0

Punkten liger i fjärde kvadranten.

Körexempel 2:

Mata in X: 0
Mata in Y: -3.5

Punkten ligger på X-axeln.

Repetitionssatser (loopar)

För att verkligen kunna lösa alla lösbara problem behöver vi kunna upprepa kod. För detta använder repetitionssatser (iterationssatser eller loopar). I python finns två sådana strukturer. Vi börjar med while.

While

While-satsen (eller while-loopen) är mycket lik if-satsen. Den har ett villkor som den kontrollerar huruvida det är sant eller inte. Om villkoret är sant så utförs de satser som är indenterade. Om villkoret är falskt så hoppar man över de indenterade satserna. Skillnaden från if-satser är dock att while-loopen går tillbaka och kollar villkoret igen efter att satserna har utförts, och om villkoret fortfarande är sant så utförs satserna igen. Här är ett exempel:


x = input('Mata in ditt namn:')
while x == 'Erik':
   print('Jag älskar dig ' + x)

Det finns dock ett litet problem med detta program, kan du se det? Japp, det avslutas aldrig. Här kommer en liten väckarklocka... Loopar är extremt kraftfulla (uppenbarligen, med tanke på hur mycket datorn nu verkar älska Erik), men de är också riskabla att använda. Om man inte skriver dem rätt så får man program som aldrig avslutas. Nu kanske det i och för sig är så att man vill ha ett oändligt program. I sådana fall kan man skriva koden ovan lite enklare:

(OBS: Om du testar detta i Repl.it så kanske websidan har svårt att sköta detta på rätt sätt. Det får vi tyvärr leva med. Oändliga loopar skapar ofta problem helt enkelt.)

while True:
    print('Jag älskar dig Erik')

Men om man nu inte vill ha detta beteende då? Säg att man vill skriva ut alla tal mellan 1 och 100, hur gör man då? Tja, t.ex. så här:


x = 1
while x <= 100:
    print(x)
    x = x + 1

Första gången vi kommer till villkoret så är x 1, d.v.s. villkoret är sant och vi kör satserna däri. När vi kommer till x = x + 1 så blir x tilldelat 2. När vi kommer till villkoret igen är det fortfarande sant eftersom 2 <= 100. Efter 100 "varv" i loopen räknas x upp till 101, och när villkoret då kontrolleras blir det falskt, och vi hoppar över de inneslutna satserna och går vidare i programmet.

Break

Man kan även avbryta loopen innifrån med hjälp av satsen break. Break avbryter närmsta loop. Vi skulle t.ex. kunna skriva programmet ovan så här:


x = 1
while True:
    print(x)
    if x == 100:
        break
    x = x + 1

Här ser vi ett exempel på hur man kan kombinera if-satser med loopar. I detta program skriver vi ut talet x och ökar upp det tills det är lika med 100, då går vi in i if-satsen och avbryter loopen.

Här är ett annat litet exempel på hur man kan använda en while-loop. I detta exempel vet vi inte på förhand hur många gånger som vi kommer gå runt i loopen (det beror på hur klyftig användaren är):


while True:
    x = int(input('Gissa det hemliga talet!'))
    if x == 42:
        print('Rätt!')
        break
    elif x > 42:
        print('Mindre!')
    else:
        print('Större!')

Övningar

Uppgift 3

Skriv ett program där användaren får mata in två heltal A och B. Programmet skall sedan mata ut alla heltal från A till B, med kommatecken emellan.

Körexempel:

Mata in A: 4
Mata in B: 8
4,5,6,7,8

Uppgift 4

Skriv ett program där användaren får mata in två heltal A och B. Programmet skall sedan skriva ut summan av alla heltal från A till B.

Körexempel:

Mata in A: 5
Mata in B: 10
Summan av alla tal mellan A och B är 45

For

Att upprepa något ett visst antal gånger är dock något som är så pass vanligt i program att det finns en egen sats för detta. Den satsen kallas för for-satsen (eller for-loopen). Antag att vi som tidigare vill skriva ut alla tal från 1 till 100. Då skulle vi kunna skriva detta:


for i in range(1,101):
    print(i)

Variabeln i är här en gratisvariabel som loopen själv håller reda på. Den brukar kallas för loop-räknare, eller styrvariabel. Den kommer sättas till 1 första gången (eftersom vi angav 1 i till range) och räknas upp automatiskt i slutet av varje "varv". Loopen slutar att gå när i räknas upp till 101. Precis som alla variabler väljer vi själva namnet på denna variabel, den behöver alltså inte heta just "i".

Om man vill hoppa t.ex. två steg med styrvariabeln så kan man skicka med detta till range. T.ex:


for i in range(1,101,2):
    print(i)

Med detta så skriver vi ut precis alla udda tal mellan 1 och 101.

for-satsen går igenom olika serier av data och range() är ett sätt att skapa en talserie som går att gå igenom på detta sätt. En begränsning med range() är att den bara fungerar med heltal. Om man behöver gå igenom ett intervall med flyttal så kan man göra det genom att använda range för att gå igenom stegen man behöver istället. Med steget kan man sedan räkna ut vad talet man vill använda i talserien ska vara. Tänk exempelvis att vi vill skriva ut alla tal från 1.0 till och med 2.0 med steglängden 0.2. Då kan vi räkna ut att vi behöver en loop som tar 6 steg för att lösa detta. Sedan kan vi med hjälp av loop-räknaren beräkna vilket tal vi står på i varje varv i loopen:


start = 1.0 #startvärdet
stop = 2.0  #stopvärdet
steglangd = 0.2 #längden av varje steg
antal_varv = ((stop - start) / steglangd) + 1
antal_varv = int(antal_varv) #konvertera till heltal
for i in range(0, antal_varv, 1):
    nuvarande_tal = start + (i * steglangd)
    print(nuvarande_tal)

I vissa fall kanske man inte är intresserad av styrvariabeln, men python kräver ändå att man har med den när man skriver for-satsen. Om jag t.ex. vill ha ett program som skriver ut "Heja Sverige" 100 gånger så behöver jag ju faktiskt inte just styrvariabeln, och då kan jag också ha ett annat intervall, så länge intervallet fortfarande innehåller 100 heltal.


for i in range(0,100):
    print('Heja Sverige!')

Det skall dock nämnas att även om man får använda styrvariabeln så är det ingen god ide att försöka ändra den inne i loopen. Då kan man få underliga effekter...

Övningar

Uppgift 5

Lös uppgift 3 ovan, fast med en for-sats istället för while.

Uppgift 6

Lös uppgift 4 ovan, fast med en for-sats istället för while.

Uppgift 7

Skriv ett program där användaren får mata in två heltal R och K. Programmet skall sedan mata ut en multiplikationstabell med R rader och K kolumner.

Körexempel 1:

Mata in R: 4
Mata in K: 3

  1  2  3
  2  4  6
  3  6  9
  4  8 12

Körexempel 2:

Mata in R: 2
Mata in K: 8

  1  2  3  4  5  6  7  8
  2  4  6  8 10 12 14 16

TIPS: i denna uppgift kanske du behöver en loop inne i en annan loop. Ta det bara lungt och försök lösa en sak i taget så går det nog bra.

Vilken loop ska man välja?

Två verktyg för samma sak? Nja, inte riktigt. För det första så är det viktigt att förstå att for-satsen har mer att erbjuda. Man får den inbyggda styrvariablen. Dessutom så är man garanterad att inte få en oändlig loop. Problemet ligger dock i att man inte alltid kan använda for-satsen. Den är specialkonstruerad för de fall då man på förhand vet (eller kan räkna ut) hur många varv som loopen kommer att gå. När du skall välja loop, ställ dig då följande frågor:

  • Vill jag ha en oändlig loop? Om svaret är ja, använd while True: från ovan.
  • Vet jag (eller kan jag räkna ut) hur många varv som loopen skall gå? Om svaret är ja, använd for.
  • I övriga fall: använd while-loopen.

Sidansvarig: Pontus Haglund
Senast uppdaterad: 2020-09-10