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