Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3
Excerpt

En kontrollstruktur styrer hva slags hvilken kode som kjører når. Denne siden oppsummerer de viktigste kontrollstrukturene og peker videre til sider som tar for seg hver type.

Sekvens

Et prosedyreorientert program består av setninger som utføres i sekvens, så uten noen spesielle konstrollstrukturer vil all koden bli utført én og bare én gang. Koden under illustrerer poenget:

PlantUML Macro
start
:skriv ut 
Code Block
languagepython
linenumberstrue
print('Hvor gammel er du?')
age = int(input())
print(;
:les inn alder (som et tall);
:skriv ut 'Neste år blir du ' + str(agealder + 1) + ' år!')

Eksempel på sekvens:

;
stop

Illustrasjon av koden med et flytskjema. Kontrollflyten går nedover fra boks til boks. Først skrives spørsmålet ut, venter programmet på input (som bør være et tall) fra brukeren og til slutt skrives en ny melding ut.

 

Code Block
languagepython
titlePython
# pop/sequence.py
PlantUML Macro
start
:print('Hvor gammel er du?');
:age = int(input());
:print('Neste år blir du ' + str(age + 1) + ' år!');
stop
Illustrasjon av koden med et flytskjema. Kontrollflyten går nedover fra boks til boks.


Code Block
languagejava
titleJava
// pop/sequence.jpage
java.util.Scanner scanner = new java.util.Scanner(System.in);
System.out.println("Hvor gammel er du?");
int age = scanner.nextInt();
System.out.println("Neste år blir du " + (age + 1) + " år!");


Betingelser med if-then-else

En kommer imidlertid fort bort i situasjoner hvor kode bare skal utføres i bestemte tilfelle, f. F.eks. vil koden over kræsje hvis input-en ikke er et gyldig tall. Det vil være Derfor kan det vært lurt å bare utføre den siste linja hvis sjekke gyldigheten og utføre ulike setninger avhengig av om input-en faktisk er et tall eller ikke:

code

 

language

 

python

 

PlantUML Macro
start
:skriv ut 
linenumberstrue
print('Hvor gammel er du?')
ageString = input();
:les inn alder (som en tekst);
if (ageString.isdigit()):
    print(alder er et tall) then (sann)
	:skriv ut 'Neste år blir du ' + str(int(ageString)alder + 1) + ' år!')

Her brukes if-nøkkelordet for å angi at print-setningen kun skal utføres hvis betingelsen ageInput.isdigit() er sann.

PlantUML Macro
start
:print('Hvor ...');
:ageString = input();
if (ageString.isdigit()) then (true)
	:print('Neste år ...');
else (false)
	:skriv ut alder + ' er ikke et tall!';
endif
stop

Kontrollflyten har en forgreining, hvor verdien av betingelsen (true eller false) avgjør hvilken grein som tas.

...

 

 

Code Block
languagepython
linenumberstitletruePython
# pop/ifthenelse.py
print('Hvor gammel er du?')
ageString = input()
if (ageString.isdigit()):
    print('Neste år blir du ' + str(int(ageString) + 1) + ' år!')
else:
    print(ageString + ' er ikke et tall!')

Her brukes if-nøkkelordet for å angi at print-setningen kun skal utføres hvis betingelsen ageInput.isdigit() er sann.

Code Block
languagejava
titleJava
// pop/ifthenelse.jpage
java.util.Scanner scanner = new java.util.Scanner(System.in);
System.out.println("Hvor gammel er du?");
String ageString = scanner.nextLine
PlantUML Macro
start
:print('Hvor ...');
:ageString = input();
if (ageString.isdigit()) then (true)
	:print('Neste år ...');
else (false)
	:printmatches("[0-9]+")) {
	int age = Integer.valueOf(ageString);
	System.out.println("Neste år blir du " + (age + 1) + " år!");
}
else
	System.out.println(ageString + '" er ikke et tall!'");
endif
stop

Kontrollflyten har en forgreining, hvor verdien av betingelsen (true eller false) avgjør hvilken grein som tas.

Noen ganger ønsker man å velge mellom flere enn to greiner. Dette kan gjøres ved å ha en ny if inni else-delen. Man tar altså først et valg mellom to greiner og i den ene greina gjør en et nytt valg. Eksemplet under, hvor en karakter (grade) settes basert på en poengsum (score):

Code Block
languagepython
linenumberstrue
if score >= 85:
    grade = 'A';
else:
    if score >= 75:
        grade = 'B';
    else:
        if score >= 60:
            grade = 'C';
        else:
            if score > 50:
                grade = 'D';
            else:
                if score > 40:
                    grade = 'E';
                else:
                    grade = 'F';
print(grade)
PlantUML Macro
start
if (score >= 85) then (true)
	:grade = "A";
else (false)
	if (score > 75) then (true)
		:grade = "B";
	else (false)
		if (score > 60) then (true)
			:grade = "C";
		else (false)
			if (score > 50) then (true)
				:grade = "D";
			else (false)
				if (score > 40) then (true)
					:grade = "E";
				else (false)
					:grade = "F";
				endif
			endif
		endif
	endif
endif
stop

 

Noen ganger blir det mange slike spørringer nøstet, og det blir fort forvirrende. En bedre løsning er da å bruke elseif-strukturen. Her kan man evaluere flere uttrykk, og man vil kjøre den første kodeblokken som passer spørringen. I diagrammet nedenfor kan man tenke seg at man går fra venstre mot høyre, og følger den første pilen som passer. 

PlantUML Macro
(*) --> "If.."
"If.." -->[score > 90] "grade = A"
--> (*)
"If.." -->[score > 80] "grade = B"
--> (*)
"If.." -->[score > 60] "grade = C"
--> (*)
"If.." -->[score > 50] "grade = D"
--> (*)
"If.." -->[score > 40] "grade = E"
-->(*)
"If.." -->[else] "grade = F"
--> (*)

Gruppering av setninger

En kan godt ha flere setninger i then- og/eller else-delen, og de fleste programmeringsspråk har en måte å gruppere setninger på. I Java grupperes setninger ved at en har { og } rundt, mens en i python bruker innrykket for å angi hvilke setninger som hører til de ulike greinene.

 

Løkker

Løkker er kode som utføres flere ganger. Det er vanlig å skille mellom while-løkker og for-løkker. En while-løkke sjekker en betingelse, og gjennomfører koden i løkkekroppen så lenge denne betingelsen er sann. Man må være forsiktig når man skriver while-løkker; dersom ikke betingelsen er formulert riktig kan man ende opp med det som kalles en "uendelig løkke". Når man leser inn data fra en tekstfil, kan det se omtrent slik ut:

PlantUML Macro
start
 
while (lines to read?) is (true)
  :read next line;
endwhile (false)
:close file;
 
stop

 

En for-løkke er et spesialtilfelle av en while-løkke, og brukes dersom man vet hvor mange ganger løkkekroppen skal utføres. Man har en tellevariabel som endres hver gang løkken har kjørt, og til slutt er tellevariabelen så stor eller liten at løkken er ferdig. Det er også mulig å få for-løkker til å kjøre uendelig, så vær forsiktig med bruken av denne også. For å implementere en for-løkke trenger man (1) en startverdi for tellevariabelen, (2) en sluttverdi for tellevariabelen, og (3) hvor mye man ønsker å endre tellevariabelen etter hver løkke. En standard bruk av slike løkker er å bla gjennom en liste, og gjøre noe med hvert element i listen. 

Her brukes if-nøkkelordet for å angi at print-setningen kun skal utføres hvis betingelsen er sann. I Python brukes innrykk for å knytte setninger til true/sann- og false/usann-greinene. I Java tillates bare én setning eller gruppe med setninger i hver grein, og derfor må en gruppere setninger med { og }.

 

 

Dette kalles gjerne betinget utførelse, siden setningene i de to greinene utføres bare hvis en bestemt betingelse er true/sann eller false/usann. Det finnes flere varianter, f.eks. kan en utelate else-delen eller ha en ny if i else-delen for å håndtere flere tilfeller.

Les mer om dette her: if-kontrollstrukturen

while-løkke

Løkker er kode som utføres flere ganger. Det er vanlig å skille mellom while-løkker og for-løkker. En while-løkke sjekker en betingelse, og gjennomfører koden inni løkka så lenge denne betingelsen er sann. Man må være forsiktig når man skriver while-løkker; dersom ikke betingelsen er formulert riktig kan man ende opp med det som kalles en "uendelig løkke". Hvis man vil stille spørsmålet om alder helt til man får et ordentlig svar, så vil det se slik slik ut:

PlantUML Macro
start
:skriv ut 'Hvor gammel er du?';
:les inn alder (som en tekst);
while (alder er et tall) is (usann)
	:skriv ut alder + ' er ikke et tall, skriv det inn på nytt!';
	:les inn alder (som en tekst);
endwhile (sann)
:skriv ut 'Neste år blir du ' + (alder + 1) + ' år!';
stop
Code Block
languagepython
titlePython
# pop/while.py
print('Hvor gammel er du?')
ageString = input()
while (! ageString.isdigit()):
	print(ageString + ' er ikke et tall, skriv det inn på nytt!')
	ageString = input()
print('Neste år blir du ' + str(int(ageString) + 1) + ' år!')   
Code Block
languagejava
titleJava
// pop/while.jpage
java.util.Scanner scanner = new java.util.Scanner(System.in);
System.out.println("Hvor gammel er du?");
String ageString = scanner.nextLine();
while (! ageString.matches("[0-9]+")) {
	System.out.println(ageString + " er ikke et tall!");
	ageString = scanner.nextLine();
}
int age = Integer.valueOf(ageString);
System.out.println("Neste år blir du " + (age + 1) + " år!");

 

 

 

Det finnes varianter hvor man ikke tester løkke-betingelsen på forhånd, men etterpå, og hvor betingelsen snus på. Noen språk har også muligheten til å hoppe ut av løkka fra innsiden.

Les mer om dette her: while-kontrollstrukturen

For-each-løkker

I en del løkker er poenget å behandle et sett med data, så betingelsen koker ned til om det er mere data igjen. Istedenfor at det må gjøres "manuelt" med en while-løkke med en teller som øker og sjekkes mot antall data-elementer, så har en del språk en egen kontrollstruktur som gjerne kalles for-each, for å gå gjennom alle data-elementer i en samling. En slik for-each-løkke holder både styr på om det er flere data-elementer igjen og sørger for å sette en løkke-variabel til neste element i rekka:

Gjør noe for hvert element i en liste

PlantUML Macro
start
:initialiser liste med navn;
while (flere navn igjen) is (sann)
	:sett navn til neste navn i lista
	:skriv ut 'Hei ' + navn;
endwhile (usann)
stop
Code Block
languagepython
titlePython
# pop/foreach.py
names = ['Chris', 'Pat', 'Sam']
for name in names:
    print 'Hei ' + name
Code Block
languagejava
titleJava
// pop/foreach.jpage
String[] names = {"Chris", "Pat", "Sam"};
for (String name : names) {
	System.out.println("Hei " + name);
}

Dette er et eksempel på en data-dreven løkke, som står sentralt i mange typer databehandling. Ikke alle språk har en egen for-each-kontrollstruktur og ikke alle type data støttes heller, men det er greit å tenke på dette som en egen teknikk som har sine konvensjoner og standardløsninger.

To sentrale stikkord når man arbeider med løkker er break og continue. Break betyr at man avbryter løkken, og fortsetter å kjøre koden som står under løkkekroppen. Continue betyr at man starter løkken på nytt uten å utføre resten av koden innenfor løkkekroppen. I for-løkker vil tellevariabelen oppdateres når man bruker contiLes mer om dette her: Data-drevne løkker

Unntakshåndtering

Unntak er hendelser i et program som helst ikke skal skje. Dersom man har en liste med 4 elementer,  og man spør om hva som er det 5. elementet vil det i de fleste programmeringsspråk oppstå et unntak. Det er god programmering å skrive kode slik at man i høyest mulig grad unngår unntak. I eksempelet over betyr det å sjekke om listen inneholder 5 elementer før man spør etter det 5. elementet.

...