Föreläsning 5-7 Checklista Programexempel: chiffer
Transcription
Föreläsning 5-7 Checklista Programexempel: chiffer
Föreläsning 5-7 Checklista Innehåll Programexempel – chiffer Exempel på vad du ska kunna tecken – datatypen char logiska uttryck läsa data från fil och skriva data på fil Känna till och använda de primitiva datatyperna int, double, boolean och char. Repetition inför delmålskontroll 1 Programexempel – tärningsspel formulera aritmetiska uttryck med operatorerna +, -, *, / och % formulera logiska uttryck i Java slumptal - klassen Random algoritm för summering algoritm för att beräkna max och min Undervisningsmoment: föreläsning 5-7 övning 3 laboration 6 Avsnitt i läroboken: 3.9, 6 (ej 6.5), 7 EDAA20 (F5-7 programmering) använda if- for- och while-satser använda klassen Random för att generera slumptal formulera algoritmer och programkod för att beräkna summor formulera algoritmer och programkod för att beräkna minsta och största värde HT 2015 1 / 48 EDAA20 (F5-7 programmering) Programexempel: chiffer Programexempel: chiffer Förskjutningschiffer Rot13 HT 2015 2 / 48 I chiffret Rot13 används chiffernyckeln 13. Rot13 är sin egen invers, dvs. man kan kan använda samma algoritm för att kryptera och dekryptera. I förskjutningschiffer (ceasarchiffer) byter man ut varje bokstav mot bokstaven ett bestämt antal steg framåt i alfabetet. Exempel: om antal steg (chiffernyckeln) är 3 byts ’A’ ut mot ’D’ osv: ABCDEFGHIJKLMNOPQRSTUVWXYZ NOPQRSTUVWXYZABCDEFGHIJKLM ABCDEFGHIJKLMNOPQRSTUVWXYZ DEFGHIJKLMNOPQRSTUVWXYZABC Exempel: JAVA -> MDYD Exempel: JAVA -> WNIN -> JAVA När man dekrypterar texten gör man samma sak i motsatt riktning. Vi ska skriva ett program som läser en text och krypterar alla tecken i intervallet [A-Za-z] med chiffret Rot13. Exempel: MDYD -> JAVA EDAA20 (F5-7 programmering) HT 2015 3 / 48 EDAA20 (F5-7 programmering) HT 2015 4 / 48 Programexempel: chiffer Tecken Kryptera ett tecken Exempel: Börja med det enklare delproblemet att kryptera ett tecken i intervallet [A-Za-z]: char c1 = ’A’; char c2 = ’7’ char space = ’ ’; ABCDEFGHIJKLMNOPQRSTUVWXYZ NOPQRSTUVWXYZABCDEFGHIJKLM Observera att det ska vara apostrofer omkring en teckenkonstant. Detta kan man lösa genom följande algoritm: Tecknen är internt numrerade 0, 1, 2, ... enligt Unicode-tabellen: Siffrorna 0 till 9 kommer i följd (nr 48-57). Bokstäverna A till Z kommer i följd (nr 65-90). Bokstäverna a till z kommer i följd (nr 97-122) Å, Ä, Ö och å, ä, ö är besvärliga att hantera. De kommer inte direkt efter de andra bokstäverna och dessutom i fel ordning. om tecknet är i intervallet [A-Ma-m] ersätt tecknet med bokstaven 13 steg framåt i alfabetet annars om tecknet är i intervallet [N-Zn-z] ersätt tecknet med bokstaven 13 steg bakåt i alfabetet EDAA20 (F5-7 programmering) HT 2015 5 / 48 Några speciella tecken EDAA20 (F5-7 programmering) HT 2015 6 / 48 HT 2015 8 / 48 Konvertering mellan tecken och heltal Några tecken måste skrivas på speciellt sätt: \n \t \" Ett tecken i ett heltalsuttryck konverteras automatiskt till motsvarande heltal. radframmatningstecken tabulatortecken citattecken char c = ’D’; int nr = c + 13; Exempel: 'D' 81 I andra riktningen måste man konvertera explicit. System.out.println("Ett\nord\npå\nvarje\nrad"); c = (char) nr; System.out.println("En\tsnygg\ttabell"); System.out.println("10\t20\t30"); EDAA20 (F5-7 programmering) EDAA20 (F5-7 programmering) // 68 + 13 c nr HT 2015 7 / 48 c nr 'Q' 81 Programexempel: chiffer Logiska uttryck Metod för att kryptera ett tecken Logiska uttryck kan ha två möjliga värden, true eller false. Variabler av typen boolean kan tilldelas logiska uttryck public class Encrypter { /** Krypterar ett tecken i intervallet [A-Za-z] genom att använda krypteringsalgoritmen Rot13. */ public static char encryptRot13(char c) { if (c >= ’a’ && c <= ’m’ || c >= ’A’ && c <= ’M’) { c = (char)(c + 13); } else if (c >= ’n’ && c <= ’z’ || c >= ’N’ && c <= ’Z’) { c = (char)(c - 13); } return c; } boolean ok = true; ok = false; ok = x < 5; Logiska uttryck används bland annat som villkor i if- och while-satser: if (x < 5) ... } { while (true) { ... } } EDAA20 (F5-7 programmering) HT 2015 9 / 48 Relationer HT 2015 10 / 48 Logiska operatorer Ett logiskt uttryck kan vara en relation där man jämför värdet av två uttryck: x < 5 Relationsoperatorer: < <= == ”lika med” >= > != ”skilt från” EDAA20 (F5-7 programmering) EDAA20 (F5-7 programmering) Logiska uttryck kan kopplas samman med operatorerna: ! ”icke” && ”och” || ”eller” Exempel: x >= 0 && x <= 10 !(x >= 0 && x <= 10) vilket är det samma som x < 0 || x > 10 Ett och-uttryck är true om alla deluttryck har värdet true. Ett eller-uttryck är true om minst ett av deluttrycken har värdet true. HT 2015 11 / 48 EDAA20 (F5-7 programmering) HT 2015 12 / 48 Programexempel: chiffer Programexempel: chiffer Läsa och kryptera en teckensträng Läsa och kryptera en teckensträng, forts Skriv ett program som läser en teckensträng och chiffrerar den. Programkod: Skriv ett program som läser en teckensträng och chiffrerar den. public class Rot13 Algoritm: public static void main(String[] args) { Scanner scan = new Scanner(System.in); String s = scan.next(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); c = Encrypter.encryptRot13(c); System.out.print(c); } } läs en teckensträng för varje tecken i teckensträngen kryptera tecknet skriv ut } EDAA20 (F5-7 programmering) HT 2015 13 / 48 EDAA20 (F5-7 programmering) HT 2015 14 / 48 Inläsning av tecken Klassen String En teckensträng består av 0 till flera tecken. Exempel: "Detta är en teckensträng" "A" "" I klassen Scanner finns en metod next för att läsa in en teckensträng: String name = scan.next(); I Java används klassen String för att beskriva teckensträngar. ↵ /** Skapar en tom sträng. */ String(); Det finns ingen speciell metod för att läsa in ett värde av typen char. Istället kan man t.ex. läsa en teckensträng metoden next och sedan plocka ut första tecknet. Scanner scan = new Scanner(System.in); String name = scan.next(); char initial = name.charAt(0); /** Returnerar antal tecken i strängen. */ int length(); /** Returnerar tecknet på plats pos. */ char charAt(int pos); ... ⌦ EDAA20 (F5-7 programmering) HT 2015 15 / 48 EDAA20 (F5-7 programmering) HT 2015 16 / 48 Programexempel: chiffer Programexempel: Rot13 Läsa och kryptera en text Läsa och kryptera en text, forts Skriv ett program som läser en text och chiffrerar den. Programkod: Skriv ett program som läser en text och chiffrerar den. public class Rot13 public static void main(String[] args) { System.out.println("Skriv texten som ska krypteras:"); Scanner scan = new Scanner(System.in); while (scan.hasNextLine()) { String s = scan.nextLine(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); c = Encrypter.encryptRot13(c); System.out.print(c); } System.out.println(); } } } Algoritm: Så länge det finns en rad att läsa läs en rad för varje tecken på raden kryptera tecknet skriv ut EDAA20 (F5-7 programmering) HT 2015 17 / 48 Klassen Scanner HT 2015 18 / 48 try catch-sats När vi ska läsa något från tangentbordet gör vi det med hjälp av ett Scanner-objekt: Scanner scan = new Scanner(System.in); Man kan också skapa Scanner-objekt som läser från en fil (här från en fil med namnet indata.txt): Scanner scan = new Scanner(new File("indata.txt")); Det är inte säkert att den angivna filen finns. Då får man ett fel som man måste ta hand i en try catch-sats. Se nästa bild. EDAA20 (F5-7 programmering) EDAA20 (F5-7 programmering) HT 2015 19 / 48 Vissa fel, t.ex. att försöka öppna en fil som inte finns, måste man ta hand om i en try catch-sats. I exemplet nedan görs ett försök att öppna filen indata.txt. Om det inte går avbryts exekveringen av satserna i try-blocket och satserna i catch-blocket kommer att utföras. try { // Här försöker vi öppna filen indata.txt scan = new Scanner(new File("indata.txt")); } catch (FileNotFoundException e) { // Här kan man skriva vad som ska hända om // filen inte kan öppnas. } EDAA20 (F5-7 programmering) HT 2015 20 / 48 Programexempel: chiffer Programexempel: chiffer Läsa tecknen från en fil Skriva ut på en fil public class Rot13 { public static void main(String[] args) { Scanner scan = null; try { scan = new Scanner(new File("indata.txt")); } catch (FileNotFoundException e) { System.out.println("Filen kunde inte öppnas"); System.exit(1); } while (scan.hasNextLine()) { String s = scan.nextLine(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); c = Encrypter.encryptRot13(c); System.out.print(c); } System.out.println(); } } } EDAA20 (F5-7 programmering) HT 2015 public class Rot13 { public static void main(String[] args) { PrintWriter out = null; try { out = new PrintWriter(new File("utdata.txt")); } catch (FileNotFoundException e) { System.out.println("Filen kunde inte öppnas"); System.exit(1); } // Skapa Scanner-objekt och läs som tidigare men // byt System.out.print(c) mot out.print(c) etc. // Utskrifterna kommer nu att hamna på filen utdata.txt. } 21 / 48 } out.close(); EDAA20 (F5-7 programmering) Delmål 1 Delmål 1 Repetition Exempel på vad du ska kunna HT 2015 22 / 48 Förklara följande begrepp: algoritm, program, kompilering, exekvering, variabel, tilldelningssats. På föreläsning 6 blir det repetition inför delmålskontroll 1. Det vi ska repetera är framförallt: Formulera algoritmer med if-, for- och while-satser (beräkna minimum, maximum, summor ...) viktiga begrepp som klass, attribut, konstruktor ... hur man skapar och använder objekt implementering av klasser Skriva enkla program som skapar och använder objekt. Förklara följande begrepp: objekt, klass, specifikation, implementering, attribut, metod, parameter, konstruktor, private, public. Material till denna repetitionsföreläsning delas ut separat. Implementera enkla klasser. Rita figur över minnessituationen med variabler och objekt med attribut (dvs. visa att du förstår vilka objekt som finns i ett program och hur de hänger ihop). EDAA20 (F5-7 programmering) HT 2015 23 / 48 EDAA20 (F5-7 programmering) HT 2015 24 / 48 Programexempel: tärningsspel Programexempel: tärningsspel Kasta tärning tills etta Vi börjar med att lösa det enklare delproblemet att kasta en tärning tills den visar en etta. Därefter utökar vi programmet stegvis. Skriv ett program som låter en användare spela detta tärningsspel: Spelaren gör första tärningsslaget och får samma poäng som tärningen visar. Sedan fortsätter spelet enligt följande regler: Algoritm: Om tärningen visar något annat än en etta adderas antal prickar tärningen visar till spelaren poäng. Om spelaren slår en etta sätts poängsumman till 0 och spelet avbryts. Spelaren kan inför varje tärningsslag välja att avbryta spelet och nöja sig med den poäng som uppnåtts. EDAA20 (F5-7 programmering) HT 2015 25 / 48 kasta tärningen int sum = antal prickar så länge summan ej är lika med 0 kasta tärningen om tärningen visar en etta sum = 0 annars sum = sum + antal prickar EDAA20 (F5-7 programmering) Klassen Die Slumptalsgenerator Specifikation Klassen Random Vi behöver en klass som beskriver en tärning. Den ska ha metoder för att kasta tärningen och för att läsa av antal prickar: ↵ /** Skapar en tärning. */ public Die(); 26 / 48 Inuti klassen Die behöver vi dra slumpmässiga tal mellan 1 och 6. Slumptal får man med hjälp av standardklassen java.util.Random. ↵ /** En slumptalsgenerator med slumptalsfröet seed. */ Random(long seed); /** En slumptalsgenerator med ett slumpmässigt slumptalsfrö. */ Random(); /** Kastar tärningen. */ public void roll(); /** Slumpmässigt heltal i intervallet [0,n). */ int nextInt(int n); /** Tar reda på resultatet av det senaste kastet. */ public int getResult(); ⌦ EDAA20 (F5-7 programmering) HT 2015 HT 2015 27 / 48 /** Slumpmässigt reellt tal i intervallet [0,1.0). */ double nextDouble(); ⌦ EDAA20 (F5-7 programmering) HT 2015 28 / 48 Övning Slumptal Dra slumptal inom ett heltalsintervall Exempel: krona eller klave Lägg till programkoder för att dra ett slumptal i intervallet [0,5] och ett slumptal i intervallet [1,6]. Random rand = new Random(); EDAA20 (F5-7 programmering) HT 2015 29 / 48 Random rand = new Random(); if (rand.nextDouble() < 0.5) { System.out.println("krona"); } else { System.out.println("klave"); } EDAA20 (F5-7 programmering) Slumptal Tärning Exempel: tippa 1, x eller 2 Klassen Die 30 / 48 public class Die { private static Random rand = new Random(); private int pips; // antal prickar som visas Sannolikhet för 1 ska vara 55% -”x -”- 15% -”2 -”- 30% /** Skapar en tärning. */ public Die() { roll(); // så att pips får ett värde 1..6 } Random rand = new Random(); double nbr= rand.nextDouble(); char res; if (nbr < 0.55) { res = ’1’; } else if (nbr < 0.7) { res = ’x’; } else { res = ’2’; } /** Kastar tärningen. */ public void roll() { pips = 1 + rand.nextInt(6); } } EDAA20 (F5-7 programmering) HT 2015 HT 2015 31 / 48 /** Tar reda på resultatet av det senaste kastet. */ public int getResult() { return pips; } EDAA20 (F5-7 programmering) HT 2015 32 / 48 Klassen Die – kommentarer Anropa metod på objektet självt För att tärningen ska få ett vettigt startvärde anropas metoden roll inuti konstruktorn: Slumptalsgeneratorn rand är ett statiskt attribut. Det betyder att rand hör till själva klassen Die och inte till något enskilt tärningsobjekt. Alla tärningsobjekt man skapar delar på samma slumptalsgenerator. Man får då en bättre fördelning av slumptalen jämfört med om varje tärning har sin egen slumptalsföljd. /** Skapar en tärning. */ public Die() { roll(); } Ett anrop av nextInt(6) ger ett heltal mellan 0 och 5. För att få ett slumptal mellan 1 och 6 får vi göra så här: pips = rand.nextInt(6) + 1; För att tärningen ska få ett vettigt startvärde anropas metoden roll inuti konstruktorn. EDAA20 (F5-7 programmering) HT 2015 33 / 48 Normalt anger man med punktnotation vilket objekt en metod ska utföras på. Det behövs inte i det här fallet. Metoden roll är deklarerad i den här klassen och utförs på det aktuella objektet. Man kan också anropa metoden så här: this.roll(); EDAA20 (F5-7 programmering) Programexempel: tärningsspel Summering Kasta tills tärningen visar en etta Mönster 34 / 48 Uppgift: Beräkna summan av ett antal termer. Die d = new Die(); d.roll(); int sum = d.getResult(); System.out.println("Poäng: " + sum); while (sum != 0) { d.roll(); if (d.getResult() == 1) { sum = 0; } else { sum = sum + d.getResult(); System.out.println("Poäng: " + sum); } Lösning: Deklarera och nollställ en variabel som håller reda på det aktuella värdet av summan. Gå sedan igenom termerna en efter en och addera varje term till summan. Algoritmen i pseudokod: sum = 0; för alla termer { term = "nästa term" sum = sum + term; } } EDAA20 (F5-7 programmering) HT 2015 HT 2015 35 / 48 EDAA20 (F5-7 programmering) HT 2015 36 / 48 Programexempel: tärningsspel Programexempel: tärningsspel Låt spelaren välja när det är dags att avbryta Låt spelaren välja när det är dags att avbryta Lägg till programkod som låter användaren av programmet avgöra när det är dags att sluta slå tärningen. Algoritm: kasta tärningen int sum = antal prickar fråga om användaren vill fortsätta så länge sum är skild från 0 och användaren vill fortsätta kasta tärningen om tärningen visar en etta sum = 0 annars sum = sum + antal prickar fråga om användaren vill fortsätta EDAA20 (F5-7 programmering) HT 2015 37 / 48 Die d = new Die(); d.roll(); int sum = d.getResult(); Scanner scan = new Scanner(System.in); System.out.println("Poäng: " + sum); System.out.println("Vill du fortsätta (ja/nej)"); String answer = scan.next(); while (sum != 0 && answer.equals("ja")) { d.roll(); if (d.getResult() == 1) { sum = 0; } else { sum = sum + d.getResult(); System.out.println("Poäng: " + sum); System.out.println("Vill du fortsätta (ja/nej)?"); answer = scan.next(); } } System.out.println("Du fick " + sum + " poäng."); EDAA20 (F5-7 programmering) Programexempel: tärningsspel Programexempel: tärningspel Alternativ – avbryt med break Antal tärningsslag, max antal poäng Die d = new Die(); d.roll(); int sum = d.getResult(); Scanner scan = new Scanner(System.in); while (sum != 0) { System.out.println("Poäng: " + sum); System.out.println("Vill du fortsätta (ja/nej)?"); String answer = scan.next(); if (!answer.equals("ja")) { break; } d.roll(); if (d.getResult() == 1) { sum = 0; break; } else { sum = sum + d.getResult(); } } EDAA20 (F5-7 programmering) HT 2015 HT 2015 38 / 48 Hur mycket poäng kan det vara rimligt att förvänta sig (maximalt och i genomsnitt)? Låt programmet simulera ett stort antal spelomgångar och skriv ut den största poängumman som uppnåddes samt den genomsnittliga poängsumman. Utgå från programmet som kastar tärningen tills det blir en etta. Ändra stegvis koden på följande sätt: Låt programmet skriva ut antal poäng som uppnåtts innan kastet med den avslutande ettan. Tag bort alla övriga utskrifter. Låt programmet upprepa antal spelomgångar ett stort antal gånger. Istället för att skriva ut en poängsumma per spelomgång ska nu programmet ändras så att det skriver ut den största poängsumman som uppnåddes. Lägg till kod för att beräkna och skriva ut den genomsnittliga poängsumman. 39 / 48 EDAA20 (F5-7 programmering) HT 2015 40 / 48 Beräkna maximum Konstanter för minsta och största tal Mönster Uppgift: Beräkna det största talet i en följd av tal. Lösning: Deklarera en variabel max som ska hålla reda på det hittills största värdet. Låt max få ett litet startvärde. Gå sedan igenom talen och jämför med max. Uppdatera max ifall det aktuella talet är större. Konstanter för minsta respektive största värde ett int-tal kan ha: Algoritmen i pseudokod: max = "litet värde"; för alla värden { value = "nästa värde"; if (value > max) { max = value; } } EDAA20 (F5-7 programmering) int i1 = Integer.MIN_VALUE; int i2 = Integer.MAX_VALUE; // -2147483648 // 2147483647 double d1 = Double.MIN_VALUE; double d2 = Double.MAX_VALUE; double d3 = -Double.MAX_VALUE // 4.9E-324 (OBS! >0) // 1.8E308 // -1.8E308 Med E menas ”gånger 10 upphöjt till” HT 2015 41 / 48 EDAA20 (F5-7 programmering) Beräkna minimum Beräkna maximum Mönster Övning Uppgift: Beräkna det minsta talet i en följd av tal. Lösning: Deklarera en variabel min som ska hålla reda på det hittills minsta värdet. Låt min få ett stort startvärde. Gå sedan igenom talen och jämför med min. Uppdatera min ifall det aktuella talet är mindre. Algoritmen i pseudokod: HT 2015 42 / 48 Beräkna och skriv ut det största talet av ett antal heltal som läses in från tangentbordet. Fyll i den kod som saknas. Scanner scan = new Scanner(System.in); int max = Integer.MIN_VALUE; while (scan.hasNext()) { int nbr = scan.nextInt(); min = "stort värde"; för alla värden { value = "nästa värde"; if (value < min) { min = value; } } EDAA20 (F5-7 programmering) HT 2015 43 / 48 EDAA20 (F5-7 programmering) HT 2015 44 / 48 Programexempel: tärningspel Heltalsdivision och rest Antal tärningsslag, max antal poäng, forts Det färdiga programmet finns på kursens hemsida. a / b ger ett heltal som resultat om både a och b är heltal. För att beräkna den genomsnittliga poängsumman ska man dividera totala poängsumman med antal spelomgångar. Exempel: 17 / 3 är lika med 5 (heltalsdivision) 17 % 3 är lika med 2 (rest vid heltalsdivision) Tänk på att Java vid division ger resultatet i form av ett heltal om bägge operanderna är heltal. Se därför till att en av operanderna har typen double. Ex: 3 personer ska rättvist dela på 17 kakor. Alla får 5 kakor var och 2 kakor blir över. System.out.println(totalSum / (double) n); EDAA20 (F5-7 programmering) HT 2015 45 / 48 EDAA20 (F5-7 programmering) Heltalsdivision och rest Heltalsdivision och rest Exempel på användning Exempel på användning Avgör om x är udda eller jämnt: 46 / 48 Skriv ut antal timmar och minuter mellan start- och sluttid. if (x % 2 == 0) { System.out.println("jämnt" ); } else { System.out.println("udda"); } System.out.println("Skriv starttid och sluttid " + "(timmar och minuter):"); Scanner scan = new Scanner(System.in); int startHour = scan.nextInt(); int startMin = scan.nextInt(); int stopHour = scan.nextInt(); int stopMin = scan.nextInt(); int minutes = 60 * (stopHour - startHour) + (stopMin - startMin); Avgör om x är jämnt delbart med 10: if (x % 10 == 0) { System.out.println("x är jämnt delbar med 10"); } EDAA20 (F5-7 programmering) HT 2015 HT 2015 System.out.println("Tidsavstånd " + minutes/60 + " timmar och " + minutes % 60 + " minuter"); 47 / 48 EDAA20 (F5-7 programmering) HT 2015 48 / 48