Föreläsning 4

I den här föreläsningen skall vi ta upp två begrepp, där det senare ofta förutsätter att man behärskar det tidiare.

  1. loopar
  2. arrayer med ett index

I lektion 4 har vi introducerat loopar och arrayer med hjälp av bildhantering. Här skall skall vi repetera de begreppen och diskutera dem i mer allmänna ordalag.

1. Loopar

Iteration är en viktig byggsten i all programmering. Ofta vill man upprepa ett visst antal satser ett visst antal gånger, dvs utföra en iteration. I Java finns det tre olika typer av satser för iteration (från lektion 4).

  1. Loop 1: for-loopen. for-loopen kan användas i alla sammanhang men den är nog fiffigast när vi i förväg vet hur många iterationer som ska utföras.
    - Testkör koden.
    - Ändra så att den börjar på 5 och slutar på 15.
    - Testa att sätta startvärdet till 100.
    - I vilken ordning görs villkoren i loopens huvud?
     
       int i;  
       System.out.println("for-loopen");
       for (i=0; i<=9; i++) {
          System.out.println("i="+i);
       }
       System.out.println("For-loopen är slut. i="+i);
       //Vilket värde på i kommer att skrivas ut?
    
    Kriterierna för for-satsen är tre: Allmänt om for-loopen:
    1. Det som står innanför klamrarna kallas kropp.
    2. Det som står i kroppen kommer att utföras varje iteration.
    3. Först beräknas initialiseringsuttrycket, loop-variabeln tilldelas ett värde.
    4. Därefter beräknas upprepningsvillkor. Om det är sant utförs sats(erna) i kroppen.
    5. Sist beräknas uppräkningsuttrycket, förändringen.
    6. Därefter beräknas upprepningsvillkoret igen.
    7. Punkterna 4-6 upprepas tills dess att upprepningsvillkoret är falskt.

    Ett annat exempel:

    	double belopp;
            double sum=0.0;
            int    antal;
    	Scanner scan = new Scanner(System.in);
    
    	System.out.println("Ge antal kvitton:");
    	antal = scan.nextInt();
    
            for (int i=1; i<= antal; i++) {
    	    System.out.println("Ge belopp " + i + ":");
    	    belopp = scan.nextDouble();
                sum=sum + belopp;        //uppdatera räknaren "sum"
           }                           //slut på for-satsen
    
           //Skriv ut summan 
           System.out.println("Summan=" + sum);
    
    Exempel på en körning där fet stil är vad användaren matar in: :
    Ge antal kvitton:
    3
    Ge belopp 1:
    29.50
    Ge belopp 2:
    34.76
    Ge belopp 3:
    8.90
    Summan=73.16 
    

  2. Loop 2: while-loopen. while-loopen kan också användas i alla sammanhang även när man inte från början vet hur många gånger loopen kommer att köras.
    - Testkör koden.
    - Prova att ta bort satsen i++; Vad händer? Bryt en oändlig loop genom att högerklicka i Interactions-fönstret och välja Reset interactions.
      
       System.out.println("while-loopen");
       int i=0;        //initialisering: innan loopen
       while( i<10 ) { //upprepningsvillkor
         System.out.println("i="+i); 
         i++;          //förändring
       }
       System.out.println("While-loopen är slut");
    
    Allmän form while (fortsättningsuttryck) { sats; sats; ... (en eller flera satser som utförs i en sekvens } Ett annat exempel:
    Om man tänker sig att vi ska mata in många belopp som ska summeras men att man inte vet hur många belopp det är skulle det vara bra att använda en while-loop. double amount; double sum=0.0; //Måste nollställas Scanner scan = new Scanner(System.in); System.out.println("Mata in belopp som ska summeras, avsluta med att skriv 0."); amount = scan.nextDouble(); //en första inmatning behövs innan while while (amount > 0) { sum=sum+amount; //uppdatera räknaren "sum" System.out.println("Ge belopp, avsluta med 0:"); amount = scan.nextDouble(); } //Skriv ut summan System.out.println("Summan=" + sum); Exempel på en körning, där fet stil är vad användaren matar in:
    Mata in belopp som ska summeras, avsluta med att skriv 0.
    29.50
    Ge belopp:
    34.76
    Ge belopp:
    8.90
    Ge belopp:
    0
    Summan=73.16
    

  3. Loop 3: do-while-loopen. do-while-loopen kan också användas i alla sammanhang även när man inte från början vet hur många gånger loopen kommer att köras. Skillnaden är att loopen alltid körs minst en gång innan villkoret testas!
    - Testkör koden.
    - Testa att initiera i till 100. Kompilera och kör.
       System.out.println("do-while-loopen");
       int i=0;
       do {
         System.out.println("i="+i);
         i++;
       } while(i<10);
       System.out.println("Do-while-loopen är slut");
    
    Allmän form do { sats; sats; ... (en eller flera satser som utförs i en sekvens } while (fortsättningsuttryck);

break-sats och continue-sats i loopar

Med satsen break hoppar man ur en loop.
Med satsen continue hoppar man över de satser i loopens huvud som inte är utförda. Ex. int i=1; int sum=0; while (i<20) { int svar = scan.nextInt(); if (svar==-1) { break; } i++; sum=sum+svar; } int i=1; int sum=0; while (i<20) { int svar = scan.nextInt(); if (svar==0) { continue; } i++; sum=sum+svar; }

2. Arrayer - indexerade variabler

Syfte: att kunna allokera minne till många variabler av samma typ samtidigt.
Antag t ex att vi har en tävling med 100 deltagre som alla ska få ett startnummer. I stället för att skriva:
int nr1, nr2, nr3, nr4,.....,nr100; //OBS: alla nämnas vid namn! //och sen inmatningen... Scanner scan = new Scanner(System.in); nr1 = scan.nextInt(); nr2 = scan.nextInt(); nr3 = scan.nextInt(); //osv 100 gånger Men vi vill kunna säja: "Jag behöver 100 integers."
Man kan skriva:
int[] nr = new int[100]; // nr är ett variabelnamn, i det här // exemplet en array av heltal. // Typen är int[] (inte int). // Initialt innehåller arrayen bara 0:or. Vi får en array, ett fält, en vektor, dvs en "rad" med heltal i minnet. nr är en referens som pekar på arrayen, dvs nr blir en objektvariabel. Elementen nollställs när arrayen skapas!
Elementen i arrayen har index. Första elementet refereras till som nr[0], andra elementet som nr[1] etc.
För att mata in värden i arrayen, eller skriva ut värdena, använder man typiskt en for-loop som startar på 0: //inmatningen blir enkel med en for-loop: for (int i=0; i<nr.length; i++) { //length ger längden av arrayen, här 100 nr[i] = scan.nextInt(); //använd loop-variablen i som index! } Arrayer är objekt i Java. I satsen
    int[] nr = new int[100];
deklareras alltså en referens till arrayen som heter nr. Typen är int[]. Arrayen instansieras med new-operatorn.
En array kan bara innehålla en typ av data, dvs inte både t ex int och char.

Arrayens element är numrerade med index. Första elementet har alltid index = 0. Det sista elementet i exempelt ovan får alltså index 99. Början av arrayen kan se ut så här:
Jämför med en referens t1 till ett Turtle-objekt
     nr

Satsen:
System.out.println(nr[3]); skriver ut elementet med index 3, vilket ger utskriften: 12.

Det går att ändra en enstaka komponent också:
nr[0] = 4; Det går att dela upp deklaration och initiering av arrayer, precis som för vanliga objekt och enkla datatyper: double[] a; //här får man en referensvariabel med värdet null a = new double[3]; //nu skapas en array med tre NOLLSTÄLLDA komponenter a[0] = 1; //ge några värden... a[1] = -3; a[2] = 8; Det första, double[] a; betyder att jag får en array-variabel. Det är en speciell typ av referensvariabel som kan referera till en array, inte till en vanlig variabel. Typen är double[] , jämför den enkla datatypen double. Alla elementen måste då vara av typen double.

Ett alternativt skrivsätt: double[] b = {2.4, 6.0, 8.1, 11.3}; //En array skapas och initieras, length //blir 4, dvs det är 4 element i arrayen.

Indexeringen måste ligga innanför arrayens gränser! För arrayen b ska alltså indexeringen ligga mellan 0 och 3. Om man går utanför blir det fel. Man får kompileringsfel eller exekveringsfel.

Om man fösöker läsa eller skriva utanför arrayen får man exekveringsfel.
Exempel på felaktig kod: //deklarerar en array med 5 element med index 0 tom 4 int[] arr = {-1, 7, 13, 2, 24}; //denna sats är inte fel men de två följande: System.out.println(arr[5]); //Försöker läsa utanför arrayen. Ger exekveringsfel: //"java.lang.ArrayIndexOutOfBoundsException: 5" arr[6] = scan.nextInt(); //Försöker skriva utanför arrayen. //Ger exekveringsfel: //"java.lang.ArrayIndexOutOfBoundsException: 6"
Det finns några bra statiska metoder i klassen java.util.Arrays för att behandla arrayer. Man kan t ex undersöka om två arrayer f och g är lika genom att skriva if (Arrays.equals(f,g)) Metoden equals ger true om arrayerna är lika. Ett annat exempel: Arrays.sort(a); sorterar komponenterna i arrayen a i stigande ordning.

Ett exempel från en lektion
Under en lektion behandlade ni bilder genom att behandla alla pixlar var för sig på ett visst sätt, till exempel reducerade ni den röda komponenten i varje pixel. Det innebar att ni gjorde samma sak många gånger och ni använde er då av en loop för att utföra rödhetsreduceringen:

int index = 0; Pixel pixel = null; Picture p = new Picture("caterpillar.jpg"); //Skapa en array av Pixel-objekt Pixel[] pixelArr = p.getPixels(); // loopa genom alla pixlar i arrayen while(index < pixelArray.length) { //pixel pekar på ett Pixelobjekt i arrayen pixel = pixelArray[index]; //hämta det röda värdet value = pixel.getRed(); //minska det röda värdet med 50% (1/2) value = (int) (value * 0.5); // sätt det röda värdet hos aktuell pixel till det nya värdet pixel.setRed(value); //nu vill vi titta på nästa pixel i arrayen index = index + 1; } För varje iteration förändrar vi rödheten i varje enskild pixel. Gå igenom koden och se att du förstår alla satser.

Sammanfattning


Anna Eckerdal
Last modified: Thu Nov 11 09:20:41 MET 2010