Ubungspaket 12 ¨ Der Datentyp char
Ubungsziele: ¨
1. Umgang mit dem Datentyp char, 2. Deklarationen von char-Variablen, 3. char-Konstanten
4. und char-Rechenoperationen.
Skript:
Kapitel: 29 bis 31 sowie 24, 25 und 27 Semester:
Wintersemester 2021/22 Betreuer:
Thomas, Tim und Ralf Synopsis:
In diesem ¨ Ubungspaket gibt es einiges zum Thema Zeichen. Die Struk-
tur der Aufgaben ¨ ahnelt sehr den vorherigen. Neben der eigentlichen
Zeichenverarbeitung ist die Umwandlung von Werten des Datentyps
char in Werte des Datentyps int und umgekehrt Teil dieses ¨ Ubungs-
paketes.
Teil I: Stoffwiederholung
Aufgabe 1: Notation von Zeichenkonstanten
In Vorlesung und Skript haben wir gesehen, dass in der Programmiersprache C Zeichen in drei verschiedenen Formen angeben k¨onnen. Vervollst¨andige folgende Tabelle:
C-Notation
Zeichen Zeichen Escape/Oktal Ganzzahl Hexadezimal
Großbuchstabe A ’A’ ’\101’ 65 0x41
Semikolon ’;’ ’\73’, ’\073’ 59 0x3B
Ziffer 3 ’3’ ’\63’, ’\063’ 51 0x33
Nullbyte ’\0’, ’\00’, ’\000’ 0 0x0
Aufgabe 2: Ein- und Ausgabe
Erl¨auter anhand von zwei Beispielen, wie Zeichen ein und ausgelesen werden k¨onnen?
Format: %c, %nc Eingabe: scanf( "%c", & c ) Ausgabe: printf( "%3c", c )
Aufgabe 3: Zeichen und deren ASCII-Werte
Schreibe ein kleines Testprogramm, das die Zeichen ’A’ bis ’Z’ nebst ihrer zugeh¨origen ASCII Werte in tabellarischer Form ausgibt. Frage: Muss man bei der Aufgabe die konkrete ASCII-Kodierung der einzelnen Zeichen selber in der ASCII-Tabelle nachschlagen oder kann das der Compiler dies erledigen? nein, der Compiler kann es: ’Zeichen’
1 # i n c l u d e < s t d i o . h >
2
3 int m a i n ( int argc , c h a r ** a r g v )
4 {
5 c h a r c ;
6 p r i n t f ( " Z e i c h e n | D e z i m a l w e r t \ n " ) ; 7 for ( c = ’ A ’ ; c <= ’ Z ’ ; c = c + 1 ) 8 p r i n t f ( " %7 c | %2 d \ n " , c , c ) ;
9 }
Teil II: Quiz
Aufgabe 1: Datentyp char vs. Datentyp int
Der Datentyp char geh¨ort zu den Ganzzahldatentypen, da die einzelnen Zeichen einzeln aufgef¨uhrt werden k¨onnen. Aber dennoch gibt es einige Unterschiede zum Datentyp int.
Diese Unterschiede betreffen in erster Linie die Zahl der verwendeten Bytes im Arbeitsspei- cher und damit die Zahl der verf¨ugbaren Bits und dem daraus resultierenden Wertebereich.
Erg¨anze folgende Tabelle:
Datentyp # der Bytes # der Bits Wertebereich
int 4 32 -2 147 483 648 bis 2 147 483 647
char 1 8 -128 bis 127 bzw. 0 bis 255
Aufgabe 2: Ausdr¨ ucke
Welche Werte erhalten die Variablenchar cundint idurch die angegebenen Ausdr¨ucke?
Ausdruck Resultat
c = ’a’ + 1 c = ’b’
c = ’m’ - 1 c = ’l’
c = ’a’ + 4 c = ’e’
c = ’m’ - ’a’ + ’A’ c = ’M’
Ausdruck Resultat
c = ’n’ - ’z’ + ’Z’ c = ’N’
c = ’P’ - ’A’ + ’a’ + 1 c = ’q’
i = ’z’ - ’a’ i = 25
i = ’9’ - ’0’ i = 9
Aufgabe 3: Datentypen
Im Zusammenhang mit Variablen und Werten vom Typ char gibt es immer wieder Fra- gen bez¨uglich des resultierenden Datentyps. In den folgenden Ausdr¨ucken gilt folgende Variablendefinition: char c und int i
Ausdruck Datentyp
c char
’a’ int
’\101’ int
Ausdruck Datentyp c + 1 int c - ’0’ int c + i int
Hinweis: Die Anweisung printf("%d\n", Ausdruck) gibt einen Hinweis auf den resultierenden Typ.Ausdruck kann eine Variable, ein Ausdruck oder ein Typ sein.
Teil III: Fehlersuche
Aufgabe 1: Summenberechnung mit kleinen Fehlern
Das folgende Programm soll die Summe der Zeichen ’a’ bis ’z’, ’A’ bis ’Z’ und ’0’
bis ’9’ bestimmen. Leider sind dem Programmierer wieder einmal ein paar kleine Fehler unterlaufen. Finde die 14 Fehler und korrigiere sie:
1 # i n c l u d e ’ s t d i o . h ’ 2
3 int m a i n ( int argc , c h a r ** a r g v )
4 {
5 c h a r c ,
6 int s .
7 for ( s = ’ a ’ , c = ’ b ’ ; c < ’ z ’ ; c = c + 1 )
8 s = c ;
9 for ( c = ’ A ’ ; c >= ’ Z "; c = + 1 )
10 s = s + c ;
11 for ( c "9 ’ ; c > ’ 0 ’ , c = c + 1 )
12 s = s + c ;
13 p r i n t f ( " s u m m e = % d \ n ’ , s ) ;
14 ]
Zeile Fehler Erl¨auterung Korrektur
1 ’...’ statt
<...>
Die standard.h-Dateien m¨ussen in<...>angegeben werden.
<stdio.h>
. . . .
5/6 ,/. statt ; Alle Anweisungen m¨ussen mit einem Semikolon ab- geschlossen werden.
char c;
int x;
. . . .
7 < statt <= Gem¨aß Aufgabentellung muss auch das ’z’ mit zur Summe gez¨ahlt werden. Daher muss dort der<=Ope- rator stehen.
c <= ’z’
. . . .
8 s + fehlt Es fehlt die Summenbildung. s = s + c
. . . .
9 " statt ’ Einzelne Zeichen geh¨oren in einfache ’ ’ ’Z’
. . . .
9 c fehlt So wird c nicht weitergeschaltet. c = c + 1
. . . .
11 Die for- Schleife ist mehrfach fehlerhaft
Entweder soll innerhalb der for-Schleife aufw¨arts oder abw¨arts gez¨ahlt werden. F¨ur keine dieser bei- den M¨oglichkeiten passen die Angaben zusammen.
Wir entscheiden uns f¨urs Abw¨artsz¨ahlen.
for(
c = ’9’;
c >= ’0’;
c = c - 1 )
Zeile Fehler Erl¨auterung Korrektur 13 ’ statt " Die Ausgabeanweiung ben¨otigt die Textausgaben in
G¨ansef¨ußchen "..." eingeschlossen werden.
"su ... "
. . . .
13 ] statt } Eine Funktion wird durch eine geschweifte Klammer- zu } beendet.
]
Programm mit Korrekturen:
1 # i n c l u d e < s t d i o . h >
2
3 int m a i n ( int argc , c h a r ** a r g v )
4 {
5 c h a r c ;
6 int s ;
7 for ( s = ’ a ’ , c = ’ b ’ ; c <= ’ z ’ ; c = c + 1 )
8 s = s + c ;
9 for ( c = ’ A ’ ; c <= ’ Z ’ ; c = c + 1 )
10 s = s + c ;
11 for ( c = ’ 9 ’ ; c >= ’ 0 ’ ; c = c - 1 )
12 s = s + c ;
13 p r i n t f ( " s u m m e = % d \ n " , s ) ;
14 }
Teil IV: Anwendungen
Aufgabe 1: Umwandlung von Ziffern in Zahlen
Ein echter Klassiker: Schreibe ein kleines Programm, das eine einzelne Ziffer, also die Zeichen von ’0’ bis ’9’, in ihren entsprechenden Zahlenwerte, also ints von 0 bis 9, umwandelt. Das folgende Programmschnipsel zeigt, wie ihr es nicht machen sollt . . .
1 # i n c l u d e < s t d i o . h >
2
3 int m a i n ( int argc , c h a r ** a r g v )
4 {
5 c h a r z e i c h e n ;
6 int z a h l ;
7 z e i c h e n = ’ 5 ’ ; 8 s w i t c h ( z e i c h e n )
9 {
10 c a s e ’ 0 ’ : z a h l = 0; b r e a k ; 11 c a s e ’ 1 ’ : z a h l = 1; b r e a k ; 12 c a s e ’ 2 ’ : z a h l = 2; b r e a k ; 13 c a s e ’ 3 ’ : z a h l = 3; b r e a k ; 14 c a s e ’ 4 ’ : z a h l = 4; b r e a k ; 15 c a s e ’ 5 ’ : z a h l = 5; b r e a k ; 16 c a s e ’ 6 ’ : z a h l = 6; b r e a k ; 17 c a s e ’ 7 ’ : z a h l = 7; b r e a k ; 18 c a s e ’ 8 ’ : z a h l = 8; b r e a k ; 19 c a s e ’ 9 ’ : z a h l = 9; b r e a k ;
20 }
21 p r i n t f ( " Z e i c h e n = ’% c ’ Z a h l = % d \ n " , zeichen , z a h l ) ;
22 }
Eine derartige Umwandlung geht mit einer einfachen Anweisung. Uberlege zun¨¨ achst, in welchem Zusammenhang die ASCII-Zeichen und deren Kodierung zueinander stehen. For- muliere und erkl¨are die entsprechende C-Anweisung, und schreibe ein entsprechendes Test- programm:
Alle Ziffern sind in der ASCII-Tabelle nacheinander angeordnet, sodass sich die Werte benachbarter Ziffern um eins unterscheiden. Beispielsweise ist der (ASCII-) Wert der Ziffer ’7’ um genau eins gr¨oßer als der (ASCII-) Wert der Ziffer ’6’. Den Wert einer beliebigen Ziffer bekommt man, in dem man vom ASCII-Wert den Wert des Zeichens’0’
subtrahiert. Daher kann man einfach formulieren:
int value = ascii char - ’0’;
Testprogramm zur einfachen Wandlung von Ziffern in Zahlenwerte:
1 # i n c l u d e < s t d i o . h >
2
3 int m a i n ( int argc , c h a r ** a r g v )
4 {
5 c h a r c ;
6 int v a l u e ;
7 p r i n t f ( " Z e i c h e n | D e z i m a l w e r t \ n " ) ; 8 for ( c = ’ 0 ’ ; c <= ’ 9 ’ ; c = c + 1 )
9 {
10 v a l u e = c - ’ 0 ’ ;
11 p r i n t f ( " %7 c | %2 d \ n " , c , v a l u e ) ;
12 }
13 }
Aufgabe 2: Klassifizierung von Zeichen: <ctype.h>
Die Include-Datei <ctype.h> stellt eine Reihe von n¨utzlichen Makros zur Klassifizierung von Zeichen zur Verf¨ugung. Nenne mindestens sechs von ihnen:
Bedeutung Makroname Buchstaben isalpha() Kleinbuchstaben islower() Großbuchstaben isupper()
Bedeutung Makroname Ziffern isdigit() Hex-Ziffern isxdigit()
”Leerzeichen“ isspace()
Aufgabe 3: Wandeln von hexadezimalen Ziffern
1. Aufgabenstellung
Erweiter das Programm aus Aufgabe 1 dieses Teils so, dass es auch hexadezimale Ziffern, ’A’bis ’F’bzw. ’a’ bis’f’ korrekt wandelt.
2. Pflichtenheft
Aufgabe : Umwandlung hexadezimaler Ziffern in die entsprechenden Zahlenwerte Eingabe : eine hexadezimale Ziffer
Ausgabe : eingegebene Ziffer und ihr Zahlenwert
Sonderf¨alle : Fehlermeldung bei Eingabe nicht-hexadezimaler Zeichen 3. Testdaten
Alle Ziffern von ’0’bis ’9’, ’A’ bis’F’ und ’a’bis ’f’
4. Implementierung
Das Wesentliche haben wir ja schon in der vorherigen ¨Ubungsaufgabe gehabt. Jetzt m¨ussen wir nur ¨uberpr¨ufen, ob wir eine Ziffer ’0’-’9’, einen Kleinbuchstaben
’a’-’f’oder einen Großbuchstaben’A’-’F’vorliegen haben. Je nach dem ¨andert sich die Umwandlung geringf¨ugig. Im Kern sieht die ¨Anderung also wie folgt aus:
Umwandlung von hexadezimalen Ziffern in Zahlenwerte Variablen: Integer: zahl
Char: zeichen
wenn ziffer ≥ ’0’ und ziffer ≤ ’9’
dann zahl = ziffer - ’0’
sonst wenn ziffer ≥ ’a’ und ziffer ≤ ’f’
dann zahl = ziffer - ’a’ + 10
sonst wenn ziffer ≥ ’A’ und ziffer ≤ ’F’
dann zahl = ziffer - ’A’ + 10 sonst Ausgabe einer Fehlermeldung
5. Kodierung
1 # i n c l u d e < s t d i o . h >
2
3 int m a i n ( int argc , c h a r ** a r g v )
4 {
5 c h a r c ;
6 int val , e r r o r = 0;
7 s c a n f ( " % c " , & c ) ;
8 if ( c >= ’ 0 ’ && c <= ’ 9 ’ )
9 val = c - ’ 0 ’ ;
10 e l s e if ( c >= ’ a ’ && c <= ’ f ’ )
11 val = c - ’ a ’ + 10;
12 e l s e if ( c >= ’ A ’ && c <= ’ F ’ )
13 val = c - ’ A ’ + 10;
14 e l s e e r r o r = 1;
15 if ( e r r o r )
16 p r i n t f ( " ’% c ’ ist k e i n hex - z e i c h e n \ n " , c ) ; 17 e l s e p r i n t f ( " % c hat den w e r t % d \ n " , c , val ) ;
18 }
Aufgabe 4: Umwandlung von Klein in Großbuchstaben
1. Aufgabenstellung
Enwickle ein Programmst¨uckchen, das Kleinbuchstaben in Großbuchstaben umwan- deln kann und umgekehrt. Auch diese Umwandlung geht wieder in einer Zeile.
2. Pflichtenheft
Aufgabe : Umwandlung von Klein- in Großbuchstaben und umgekehrt
Eingabe : keine; die entwickelten Anweisungen werden direkt in Schleifen aufge- rufen
Ausgabe : Paare von Klein- und Großbuchstaben in Tabellenform Sonderf¨alle : keine
3. Testdaten
Alle Buchstaben von ’a’ bis’z’ und ’A’bis ’Z’.
4. Implementierung
Da diese Aufgabe eigentlich keine gr¨oßeren Schwierigkeiten bereiten sollte, konzen- trieren wir uns hier auf die eigentliche Umwandlung der Zeichen. Wie lautet die jeweiligen Anweisungen zum Umwandeln der Buchstaben?
Klein- in Großbuchstaben: upper = lower - ’a’ + ’A’
Groß- in Kleinbuchstaben: lower = upper - ’A’ + ’a’
5. Kodierung
Schreibe ein entsprechendes Testprogramm f¨ur die beiden obigen Anweisungen:
1 # i n c l u d e < s t d i o . h >
2
3 int m a i n ( int argc , c h a r ** a r g v )
4 {
5 c h a r c ;
6 p r i n t f ( " k l e i n | g r o s s \ n " ) ;
7 for ( c = ’ a ’ ; c <= ’ z ’ ; c = c + 1 )
8 p r i n t f ( " %5 c | % c \ n " , c , c - ’ a ’ + ’ A ’ ) ; 9 p r i n t f ( " \ n g r o s s | k l e i n \ n " ) ;
10 for ( c = ’ A ’ ; c <= ’ Z ’ ; c = c + 1 )
11 p r i n t f ( " %5 c | % c \ n " , c , c - ’ A ’ + ’ a ’ ) ;
12 }
Aufgabe 5: Zeichen-Matrix
1. Aufgabenstellung
Zur Wiederholung: Eine Variable vom Typcharbesitzt in der Regel acht Bits, womit sich 256 verschiedene Werte darstellen lassen. Entwickle ein Programm, das diese 256 M¨oglichkeiten in Form einer 16×16 Matrix darstellt, und zwar nicht als Zahlenwerte sondern als Zeichen. Da einige Zeichen
”merkw¨urdig“ aussehen, ist es g¨unstig" %2c"
als Formatierung zu nehmen. Mit etwas Gl¨uck wird folgende Matrix ausgegeben.
Gew¨unschte Ausgabe:
2. Pflichtenheft
Aufgabe : Darstellung aller 256 Zeichen in Form einer 16×16 Matrix Eingabe : keine, die Tabelle wird direkt ausgegeben
Ausgabe : Ausgabe der Tabelle Sonderf¨alle : keine
3. Implementierung
Ausgabe aller 256 Zeichen als Matrix setze zeichen = 0
f¨ur i = 0 bis 16 schrittweite 1 wiederhole
f¨ur j = 0 bis 16 schrittweite 1 wiederhole
setze zeichen = zeichen + 1 Ausgabe zeichen
Ausgabe Zeilenumbruch
4. Kodierung
1 # i n c l u d e < s t d i o . h >
2
3 int m a i n ( int argc , c h a r ** a r g v )
4 {
5 int i , j , c ;
6 for ( c = i = 0; i < 16; i ++ )
7 {
8 for ( j = 0; j < 16; j ++ , c ++ )
9 p r i n t f ( " %2 c " , c ) ; 10 p r i n t f ( " \ n " ) ;
11 }
12 }
5. Alternative-I: Berechnung des auzugebenen Zeichens in Zeile 9:
1 # i n c l u d e < s t d i o . h >
2
3 int m a i n ( int argc , c h a r ** a r g v )
4 {
5 int i , j ;
6 for ( i = 0; i < 16; i ++ )
7 {
8 for ( j = 0; j < 16; j ++ )
9 p r i n t f ( " %2 c " , i * 16 + j ) ; 10 p r i n t f ( " \ n " ) ;
11 }
12 }
6. Alternative-II: Test auf die notwendigen Zeilenumbr¨uchen in den Zeilen 9 und 10:
1 # i n c l u d e < s t d i o . h >
2
3 int m a i n ( int argc , c h a r ** a r g v )
4 {
5 int c ;
6 for ( c = 0; c < 2 5 6 ; c ++ )
7 {
8 p r i n t f ( " %2 c " , c ) ;
9 if ( c % 16 == 15 )
10 p r i n t f ( " \ n " ) ;
11 }
12 }