Übung 2
- Bearbeiten Sie Scrabble.
- Bearbeiten Sie Lesbarkeit.
- Bearbeiten Sie Cäsar.
Warm-Up-Aufgaben
Erstellen Sie für jede Übungseinheit jeweils eine eigene Datei für die Warm-Up-Aufgaben in dem Projektverzeichnis, in dem Sie auch die Übungsaufgaben bearbeiten werden.
Weitere Informationen finden Sie in diesem FAQ (Warm-Up-Aufgaben).
Als kompilierbares Codegerüst können Sie zu Beginn folgendes Snippet in Ihre Datei kopieren:
#include <cs50.h>
#include <stdio.h>
int main(void)
{
return 0;
}
Beachten Sie insbesondere den Import der CS50-Bibliothek und der “Standard Input and Output”-Bibliotheken.
Warm-Up 1
Erstellen Sie einen string
namens letters
mit dem Inhalt "lol HerWdl!o"
.
Geben Sie anschließend den Inhalt an der fünften Position des Strings, also das H
, mit printf
aus. Erinnern Sie sich daran, dass die Zählung des Index-Wertes bei 0
beginnt.
Wo zu finden?
Warm-Up 2
Erstellen Sie eine Schleife, die über den String iteriert und jeweils die einzelnen char
-Werte des Strings ohne Zeilenumbruch ausgibt, sodass lol HerWdl!o
ausgegeben wird. Verwenden Sie strlen
um die Länge des Strings abzufragen. Geben Sie im Anschluss einen Zeilenumbruch aus.
Vergessen Sie nicht <string.h>
in die Datei einzubinden.
Wo zu finden?
strlen
finden Sie auch im CS50 Handbuch.
Warm-Up 3
In der Vorlesung wurde bereits die Funktion toupper
aus der <ctype.h>
Bibliothek vorgestellt. Eine weitere Funktion ist die isupper
Funktion. Lesen Sie sich kurz die entsprechende Dokumentation durch.
Binden Sie die <ctype.h>
Bibliothek in die Datei ein.
Erweitern Sie die Schleife um eine if
-Bedingung, die dafür sorgt, dass nur die Großbuchstaben des Strings ausgegeben werden.
Die Ausgabe sollte also folgendermaßen aussehen:
HW
Welchen booleschen Ausdruck müssten Sie in die if
-Bedingung schreiben, wenn Ihnen isupper
nicht zur Verfügung stünde?
Tipp: Überfliegen Sie die Liste der übrigen Funktionen der <ctype.h>
Bibliothek (der Filter-Toggle “frequently used in CS50” sollte standardmäßig aktiviert sein, ansonsten aktivieren). Diese könnten Ihnen in Zukunft nützlich sein.
Wo zu finden?
uppercase.c
aus der Vorlesung 2. Arrays an.
Warm-Up 4
Ändern Sie die if
-Bedingung aus “Warm-Up 3”, sodass nur alphabetische Zeichen ausgegeben werden:
lolHerWdlo
Wechseln Sie einmal kurz das Ausgabeformat von printf
von %c
auf %i
, sodass die char
-Werte als Integer ausgegeben werden. Erinnern Sie sich, was hinter der Ausgabe steckt?
Wo zu finden?
Warm-Up 5
Errechnen Sie nun jeweils die Position des Buchstabens im Alphabet (d.h. für A
die Position 1
, B
die Position 2
usw.). Erinnern Sie sich, dass Sie direkt mit char
-Werten rechnen können (z.B. 'A' - 'A' == 0
).
Ändern Sie dazu printf
, sodass zunächst der Buchstabe gefolgt von einem :
ausgegeben wird und anschließend seine Position im Alphabet. Fügen Sie außerdem einen Zeilenumbruch nach jedem Buchstaben ein.
Tipp: Unabhängig von der Groß- oder Kleinschreibung bleibt die Position eines Buchstabens im Alphabet gleich. Sie können den Buchstaben jeweils in einen Kleinbuchstaben (oder Großbuchstaben) umwandeln, bevor Sie seine Position im Alphabet errechnen. Erinnern Sie sich, dass es hierzu die Funktion tolower
(oder toupper
) gibt. Dadurch benötigen Sie keine if
else
Statements und können die Berechnung innerhalb einer Zeile direkt im printf
-Aufruf durchführen.
Die Ausgabe sollte folgendermaßen aussehen:
l: 12
o: 15
l: 12
H: 8
e: 5
r: 18
W: 23
d: 4
l: 12
o: 15
Wo zu finden?
uppercase.c
aus der Vorlesung 2. Arrays an.
Warm-Up 6
Dann wollen wir uns jetzt noch um die Entschlüsselung der Zeichenfolge lol HerWdl!o
kümmern.
Kommentieren Sie den bisherigen Code mittels der Blockkommentar-Syntax aus (dann haben Sie all Ihren geschrieben Code weiterhin in einer Datei zur Verfügung):
/*
// Code bis Warm-Up 6
*/
Und fügen Sie folgenden Code oben in die Datei ein:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main()
{
string letters = "lol HerWdl!o";
for (int i = 0, length = strlen(letters); i < length; i++)
{
printf("%c\n", letters[i]);
}
printf("\n");
return 0;
}
Dieser Code kommt Ihnen hoffentlich bekannt vor! So (oder so ähnlich) sollte Ihr Code nach Warm-Up 2 ausgesehen haben.
Beim Zugriff auf den Array-Index können auch Operationen und Funktionen ausgeführt und verschachtelt werden. Beispielsweise kann man mit letters[strlen(letters) - 1]
auf das letzte Zeichen in diesem String zugreifen (strlen
gibt die Anzahl aller Zeichen zurück und da ein Array mit dem 0
-Index beginnt, muss noch eine 1
abgezogen werden).
Um die Zeichenfolge lol HerWdl!o
zu entwirren, fügen Sie ein int
-Array namens map
wie folgt unterhalb der string
-Deklaration ein:
int map[] = {4, 5, 2, 9, 1, 3, 7, 11, 6, 0, 8, 10};
Hinweis: Dies ist die “Instantiation Syntax”, mit der einem Array direkt alle seine Werte zugewiesen werden. In diesem Fall ist es nicht notwendig, die Anzahl der Elemente in die []
zu schreiben, wie es normalerweise der Fall ist.
Statt wie bisher einfach die Buchstaben nacheinander entsprechend des Schleifen-Indexes auszugeben, greifen Sie jeweils auf den Wert des map
-Arrays am aktuellen Schleifen-Index zu. Verwenden Sie nun diesen Wert als Index, um auf das entsprechende Zeichen in letters
zuzugreifen. Wie eingangs beschrieben, können Sie alle diese Operationen direkt innerhalb der printf
-Funktion schachteln.
Erklärung
Anstatt mit dem Index der Schleife nacheinander auf die einzelnen Zeichen des Strings zuzugreifen, greifen Sie nun auf map
zu. Als dessen Index verwenden Sie den Index der Schleife, also map[i]
.
Um dann mit diesem Wert auf den entsprechenden Array-Index von letters
zuzugreifen, verschachteln wir die Array-Zugriffe zu letters[map[i]]
. Im ersten Schleifendurchlauf bedeutet dies, dass zunächst map[0]
abgefragt wird. Dahinter verbirgt sich die Zahl 4
. Diese Zahl ist nun der Index, mit dem wir auf den String zugreifen (d.h. letters[4]
). Das bedeutet, wir greifen im ersten Schleifendurchlauf auf den Inhalt des Strings an der fünften Position zu, also dem H
.
Wahrscheinlich haben Sie es anhand der Buchstaben schon geahnt: Welcher bekannte Ausspruch verbirgt sich hinter der Zeichenfolge?
Wo zu finden?
Warm-Up 7
Nun noch ein letzter kleiner Test Ihres Wissens. Überfliegen Sie das folgende Code-Snippet und führen Sie es aus:
#include <stdio.h>
#include <math.h>
int main() {
int integerA = 11;
int integerB = 3;
float floatB = 3;
int c = 11 / 3;
float d = 11 / 3;
float e = 11 / 3.0;
float f = integerA / floatB;
float g = (float) 11 / 3;
float h = integerA / (float) integerB;
int i = round(11 / 3);
int j = round(11.0 / 3);
int k = round(h);
float l = round(11) / 3;
printf("int c = 11 / 3 --> %i (printed with %%i)\n", c);
printf("float d = 11 / 3; --> %f (printed with %%f)\n", d);
printf("float e = 11 / 3.0; --> %f (printed with %%f)\n", e);
printf("float f = integerA / floatB; --> %f (printed with %%f)\n", f);
printf("float g = (float) 11 / 3; --> %f (printed with %%f)\n", g);
printf("float h = integerA / (float) integerB; --> %f (printed with %%f)\n", h);
printf("int i = round(11 / 3); --> %i (printed with %%i)\n", i);
printf("int j = round(11.0 / 3); --> %i (printed with %%i)\n", j);
printf("int k = round(h); --> %i (printed with %%i)\n", k);
printf("float l = round(11) / 3; --> %f (printed with %%f)\n", l);
return 0;
}
Wie kommt die jeweilige Ausgabe zustande? Worauf müssen Sie beim Rechnen in C demnach achten? Und warum genau funktioniert eigentlich die letzte Berechnung mit round
wie gewünscht? Lesen Sie ggf. die Spezifikation von round
in der Dokumentation nach.
Beachten Sie auch, dass zur Verwendung von round
<math.h>
eingebunden werden muss.
Wo zu finden?
scores.c
aus der Vorlesung 2. Arrays und insbesondere das Short zu Datentypen und Variablen an.