Übungsaufgaben zu Zeichenketten und Prüfziffern
https://bildung.social/@oerinformatik/
https://oer-informatik.de/zeichenketten-pruefziffern-uebungsaufgaben
Zeichenketten, Prüfziffer, GTIN, Luhn-Algorithmus, Modulo 97, Leitweg-ID, Lauflängenkodierung, Pseudocode, Struktogramm, Übungsaufgaben, Prüfungsvorbereitung
tl/dr; (Bearbeitungszeit insgesamt 87 min, mehrere Aufgaben): Zwei umfangreiche Übungsaufgaben zu Algorithmen über Zeichenketten: Prüfziffern nach GS1, Luhn und Modulo 97 berechnen, prüfen und berichtigen, große Zahlen schrittweise rechnen, Codes zerlegen und zusammensetzen, eindeutige Zufallscodes mit Prüfzeichen erzeugen, Lauflängenkodierung samt Mehrdeutigkeiten und gemischte Ausdrücke aus Text und Zahl. Alle Lösungen sind ausgeblendet und mit Punkteverteilung versehen [AI-Assisted]. (Zuletzt geändert am 29.10.2026)
Diese Übungsaufgaben gehören zum Artikel Zeichenketten und Prüfziffern: Algorithmen für Codes, Nummern und Texte. Er erklärt die Pseudocode-Operationen für Zeichenketten, die hier verwendet werden. Die Grundmuster (Durchlaufen, Summieren, Maximum, Suche) findest Du im Artikel Prozedurale Algorithmen mit Arrays.
Hinweise zur Bearbeitung: Von FIA wird erwartet, dass ihnen Aufgaben auf Profilkompetenz-Ebene (Aufgabe 3.1 und Aufgabe 3.2) keine Probleme bereiten. Wenn nichts anderes verlangt ist, darfst Du Deine Algorithmen in Pseudocode, als Struktogramm oder als Programmablaufplan angeben. Arrays und Zeichenketten beginnen mit dem Index 0, Variablen musst Du nicht deklarieren. Zur Verfügung stehen in allen Teilaufgaben:
| Funktion | Beschreibung |
|---|---|
laenge(text: string): integer |
Anzahl der Zeichen; für Arrays: Anzahl der Elemente bzw. Zeilen |
text[i] |
Zeichen an Index i |
teilText(text: string, start: integer, anzahl: integer): string |
anzahl Zeichen ab Index start |
zuText(zahl: integer): string |
Zahl als Zeichenkette ohne führende Nullen, z. B. "7" |
ziffernwert(c: char): integer |
'0' … '9' → 0 … 9, 'A' … 'Z' bzw. 'a' … 'z' → 10 … 35 |
istZiffer(c: char): boolean, istBuchstabe(c: char): boolean |
Zeichenart prüfen |
& (JANA, Pseudo-Python: +) |
verkettet Zeichenketten und Zeichen; Text und Zahl ergibt Text (Auswertung von links nach rechts) |
Die Beispiellösungen verwenden die Schreibweise aus dem Artikel (:= für die Zuweisung, = und <> für Vergleiche, mod für den Rest, & für die Verkettung). Andere korrekte Lösungen sind ebenfalls richtig. Schreib Deine Lösung zuerst vollständig auf, bevor Du die Beispiellösung aufklappst.
Die Codebeispiele kannst Du in vier Notationen anzeigen. Die Notationen sind im Artikel Algorithmen mit Pseudocode dokumentieren beschrieben.
anzahl: integer := 0
Du möchtest eigene Aufgaben zum Üben von einem KI-Sprachmodell generieren lassen?
Kopiere den Text in ein KI-Sprachmodell Deiner Wahl und passe Kompetenzstufe, Anzahl, Bearbeitungszeit und Szenario bei Bedarf an. Wie die Aufgaben aufgebaut sind, beschreibt der Artikel Wie sind die Aufgaben aufgebaut?. Prüfe die Ergebnisse mit dem Lehrartikel: KI-Sprachmodelle machen Fehler.
Erstelle neue Übungsaufgaben zum Thema „Zeichenketten und Prüfziffern“.
Bauplan: Halte Dich an Aufbau, Kompetenzstufen, Operatoren,
Anforderungsbereiche, Punkte und Zeitschätzung, die im Artikel
https://oer-informatik.de/aufgaben-aufbau beschrieben sind.
Fachliche Grundlage:
- https://oer-informatik.de/zeichenketten-pruefziffern
- https://oer-informatik.de/algorithmen-prozedural
- https://oer-informatik.de/pseudocode
- https://oer-informatik.de/programmentwurfstechniken
- Stilbeispiel: https://oer-informatik.de/zeichenketten-pruefziffern-uebungsaufgaben
Die Aufgaben sollen Inhalte zu diesen Schlagwörtern abdecken:
- Zeichenketten
- Prüfziffer
- GTIN
- Luhn-Algorithmus
- Modulo 97
- Leitweg-ID
- Lauflängenkodierung
- Pseudocode
- Struktogramm
Kompetenzstufe: Profilkompetenz (alternativ: Basiskompetenz, Kernkompetenz, Expertise)
Anzahl: 1 Aufgabe mit Teilaufgaben
Bearbeitungszeit in Minuten ca.: <5 bis 30 min>
Szenario: eines der Szenarien aus dem Bauplan
Vorgehen:
1. Lies zuerst die verlinkten Artikel. Kannst Du keine Webseiten
abrufen, sag mir das, statt zu raten.
2. Steht bei einer Angabe noch ein Platzhalter in <…>, frag mich
zuerst danach. Richte Punkte und Zahl der Teilaufgaben nach der
Bearbeitungszeit (ca. 0,9 min je Punkt).
3. Gib je Aufgabe Titel mit Kompetenzstufe, Ausgangssituation und
Teilaufgaben mit Operator und Punktzahl aus, dazu die geschätzte
Bearbeitungszeit.
4. Gib die Beispiellösungen mit Punkteverteilung erst aus, wenn ich
danach frage.
Aufgabe 3.1: Nummern prüfen im Fahrrad-Onlineshop (Profilkompetenz)
(ca. 50 min Bearbeitungszeit)
Du bist Auszubildende*r im Entwicklungsteam der CSB-Rad GmbH in Bielefeld. Cem Sarıkaya, Geschäftsführer Technik und IT, leitet das Projekt „Lager 4.0“: Lagerplätze und Artikel bekommen Barcode-Etiketten, die mit Handscannern gelesen werden. Gleichzeitig häufen sich Fehler bei Nummern, die Kund*innen oder Beschäftigte von Hand eingeben. Du sollst zusammen mit Jonas, Deinem Mit-Azubi, mehrere Prüffunktionen für das Shop-Backend entwickeln.
a) Für Artikel ohne Herstellerbarcode druckt CSB-Rad eigene 13-stellige Nummern im GTIN-Format. Sie beginnen mit 29 (Nummernbereich für den internen Gebrauch), es folgen die fünfstellige Artikel-ID, eine fünfstellige Variantennummer und die Prüfziffer. Die Prüfziffer wird nach GS1 berechnet:
Die Ziffern werden von rechts beginnend abwechselnd mit 3 und 1 gewichtet; die Ziffer direkt links neben der Prüfziffer hat das Gewicht 3.
Die Produkte werden addiert.
Die Prüfziffer ergänzt die Summe zum nächsten Vielfachen von 10 (ist die Summe bereits ein Vielfaches von 10, ist die Prüfziffer 0).
aa) Berechne die Prüfziffer für die Bremse BRE-HYD-01 (Artikel-ID 8) in der Variante 412, also für die Ziffernfolge 290000800412. Stelle Deinen Rechenweg in einer Tabelle dar. (3 Punkte)
| Ziffer | 2 | 9 | 0 | 0 | 0 | 0 | 8 | 0 | 0 | 4 | 1 | 2 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Gewicht | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 |
| Produkt | 2 | 27 | 0 | 0 | 0 | 0 | 8 | 0 | 0 | 12 | 1 | 6 |
Summe 56, nächstes Vielfaches von 10 ist 60, Prüfziffer 4; die Nummer lautet 2900008004124.
Bewertung: Gewichte richtig von rechts zugeordnet 1 Punkt, Summe 1 Punkt, Prüfziffer 1 Punkt. Wer von links mit 3 beginnt, erhält Summe 48 und Prüfziffer 2 (Folgefehler: 1 Punkt für die Prüfziffer).
ab) Erstelle eine Funktion pruefzifferGs1(ziffern: integer[]): integer, die für ein Array beliebiger Länge mit den Ziffern ohne Prüfziffer die Prüfziffer nach GS1 berechnet und zurückgibt. Die Funktion soll auch für Sendungsnummern mit 17 Ziffern funktionieren. (6 Punkte)
Funktion pruefzifferGs1(ziffern: integer[]): integer
n: integer := laenge(ziffern)
summe: integer := 0
zähle i von 0 bis n - 1
wenn (n - 1 - i) mod 2 = 0 dann // gerader Abstand zum rechten Ende
summe := summe + ziffern[i] * 3
sonst
summe := summe + ziffern[i]
Ende wenn
Ende zähle
Rückgabe (10 - summe mod 10) mod 10
Ende pruefzifferGs1
Alternative: Schleife von rechts nach links mit einer Variablen gewicht, die mit 3 beginnt und nach jeder Ziffer zwischen 3 und 1 wechselt (gewicht := 4 - gewicht).
Bewertung:
Summe initialisieren und Schleife über alle Ziffern 1 Punkt,
Gewicht abhängig vom Abstand zum rechten Ende (funktioniert für 12 und 17 Ziffern) 2 Punkte (nur
i mod 2von links: 1 Punkt, da nur für eine bestimmte Länge richtig),gewichtete Summe bilden 1 Punkt,
Ergänzung zum nächsten Vielfachen von 10 1 Punkt, Sonderfall Rest 0 (Ergebnis 0, nicht 10) 1 Punkt.
ac) Erstelle eine Funktion istGueltigeGtin(code: string): boolean, die eine gescannte Nummer prüft. Sie gibt nur dann wahr zurück, wenn der Code genau 13 Zeichen lang ist, nur aus Ziffern besteht und die letzte Ziffer der Prüfziffer entspricht, die Deine Funktion aus ab) für die ersten 12 Ziffern berechnet. (6 Punkte)
Funktion istGueltigeGtin(code: string): boolean
wenn laenge(code) <> 13 dann
Rückgabe false
Ende wenn
ziffern: integer[12]
zähle i von 0 bis 12
wenn nicht istZiffer(code[i]) dann
Rückgabe false
Ende wenn
wenn i < 12 dann
ziffern[i] := ziffernwert(code[i])
Ende wenn
Ende zähle
Rückgabe pruefzifferGs1(ziffern) = ziffernwert(code[12])
Ende istGueltigeGtin
Test: istGueltigeGtin("2900008004124") ergibt wahr, "2900008004125" falsch, "290000800412" (12 Zeichen) falsch.
Bewertung: Längenprüfung 1 Punkt, Prüfung aller 13 Zeichen auf Ziffer 1 Punkt, Array mit 12 Elementen anlegen und mit ziffernwert befüllen 2 Punkte, Aufruf von pruefzifferGs1 und Vergleich mit der umgewandelten letzten Ziffer 1 Punkt, Wahrheitswert zurückgeben 1 Punkt.
b) Mira Engel, Kundin der Bestellung 3, meldet, dass die Sendungsverfolgung ihre Nummer nicht kennt. Im Shop steht die Sendungsnummer 00340434160000123456. Sie besteht aus dem Datenbezeichner 00 und der 18-stelligen Nummer der Versandeinheit (SSCC), deren letzte Ziffer die Prüfziffer nach GS1 ist (Verfahren wie in a).
ba) Überprüfe die Sendungsnummer, berichtige sie gegebenenfalls und begründe Dein Ergebnis. (4 Punkte)
Geprüft werden die 17 Ziffern der SSCC ohne Datenbezeichner und ohne Prüfziffer: 34043416000012345. Bei 17 Ziffern beginnt die Gewichtung links mit 3.
| Ziffer | 3 | 4 | 0 | 4 | 3 | 4 | 1 | 6 | 0 | 0 | 0 | 0 | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Gewicht | 3 | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 |
| Produkt | 9 | 4 | 0 | 4 | 9 | 4 | 3 | 6 | 0 | 0 | 0 | 0 | 3 | 2 | 9 | 4 | 15 |
Summe 72, Ergänzung auf 80, Prüfziffer 8. Gespeichert ist aber eine 6 – die Nummer ist ungültig. Berichtigt lautet sie 00340434160000123458, sofern die übrigen 17 Ziffern stimmen.
Begründung: Die gespeicherte Prüfziffer passt nicht zu den übrigen Ziffern. Die Prüfziffer zeigt nur, dass ein Fehler vorliegt, nicht wo: Ebenso gut könnte eine andere Ziffer falsch abgetippt worden sein. Deshalb sollte die Nummer mit dem Versandbeleg oder dem Portal des Paketdienstes abgeglichen werden, bevor sie geändert wird.
Bewertung: richtige Ziffernfolge (ohne 00 und ohne Prüfziffer) und Gewichte 1 Punkt, Summe und Prüfziffer 8 1 Punkt, Aussage „ungültig“ mit berichtigter Nummer 1 Punkt, Begründung 1 Punkt.
bb) Die Handscanner liefern die Sendungsnummer als Zeichenkette mit 20 Zeichen. Beschreibe, wie Du mit den vorgegebenen Funktionen und pruefzifferGs1 prüfst, ob die enthaltene SSCC gültig ist. (2 Punkte)
Zuerst prüfen, ob die ersten beiden Zeichen "00" sind (teilText(scan, 0, 2) = "00"). Dann die 17 Zeichen ab Index 2 (teilText(scan, 2, 17), also Index 2 bis 18) in ein int-Array mit 17 Elementen umwandeln (ziffernwert), pruefzifferGs1 aufrufen und das Ergebnis mit ziffernwert(scan[19]) vergleichen.
Bewertung: Datenbezeichner abtrennen bzw. richtige Indizes 1 Punkt, Umwandlung, Aufruf und Vergleich mit dem letzten Zeichen 1 Punkt.
c) Natalia Wróbel aus der Buchhaltung schickt die Rechnungen an den Zweckverband Radwege OWL als XRechnung. Das Rechnungsportal des Zweckverbands hat die letzte Rechnung mit der Meldung „Leitweg-ID ungültig“ abgewiesen. Im Kundenstamm steht die Leitweg-ID 05711000-ZVRAD-63.
Für die Prüfung der Leitweg-ID gilt (Verfahren ISO 7064 MOD 97-10):
Die Bindestriche werden entfernt, jeder Buchstabe wird durch seinen Wert ersetzt (A = 10, B = 11, …, Z = 35, Groß- und Kleinschreibung egal).
Die entstehende Ziffernfolge wird als ganze Zahl gelesen.
Die Leitweg-ID ist gültig, wenn diese Zahl geteilt durch 97 den Rest 1 lässt.
Die Zahl ist zu lang für jeden Ganzzahl-Datentyp. Den Rest kannst Du aber schrittweise berechnen: Für jede Ziffer wird rest := (rest * 10 + ziffer) mod 97 gerechnet, für jeden Buchstaben (der für zwei Ziffern steht) rest := (rest * 100 + wert) mod 97.
ca) Beschreibe, warum die Leitweg-ID nicht einfach mit einer Umwandlungsfunktion in eine Ganzzahl umgewandelt und dann durch 97 geteilt werden kann, und warum das schrittweise Verfahren trotzdem den richtigen Rest liefert. (2 Punkte)
Nach dem Ersetzen der Buchstaben hat die Zahl hier 20 Stellen, Leitweg-IDs können noch deutlich länger sein. Der größte übliche Ganzzahltyp (long, 64 Bit) reicht nur bis etwa 9,2 · 1018 (19 Stellen); die Umwandlung würde überlaufen oder scheitern. Außerdem enthält die ID Bindestriche und Buchstaben.
Das schrittweise Verfahren funktioniert wie die schriftliche Division: Eine Zahl, an die man eine Ziffer anhängt, ist alteZahl * 10 + ziffer. Für den Rest genügt es, statt alteZahl deren Rest zu verwenden, weil (a * 10 + z) mod 97 = ((a mod 97) * 10 + z) mod 97. So bleiben alle Zwischenwerte kleiner als 97 · 100.
Bewertung: Überlauf/zu große Zahl 1 Punkt, Begründung des schrittweisen Verfahrens 1 Punkt.
cb) Entwickle eine Funktion pruefeLeitwegId(id: string): boolean, die eine Leitweg-ID nach dem Verfahren oben prüft. Bindestriche werden übersprungen. Enthält die ID ein anderes Zeichen als Ziffer, Buchstabe oder Bindestrich, gibt die Funktion falsch zurück. (8 Punkte)
Funktion pruefeLeitwegId(id: string): boolean
rest: integer := 0
zähle i von 0 bis laenge(id) - 1
c: char := id[i]
wenn istZiffer(c) dann
rest := (rest * 10 + ziffernwert(c)) mod 97
sonst
wenn istBuchstabe(c) dann
rest := (rest * 100 + ziffernwert(c)) mod 97
sonst
wenn c <> '-' dann
Rückgabe false // unzulässiges Zeichen
Ende wenn
Ende wenn
Ende wenn
Ende zähle
Rückgabe rest = 1
Ende pruefeLeitwegId
Test: pruefeLeitwegId("05711000-ZVRAD-63") liefert den Rest 48, also falsch. Die öffentliche Beispiel-ID 04011000-1234512345-06 liefert den Rest 1, also wahr.
Bewertung:
Rest mit 0 initialisieren, Schleife über alle Zeichen 1 Punkt,
Zeichen ermitteln und Fallunterscheidung Ziffer/Buchstabe/Bindestrich/sonstiges 2 Punkte,
Ziffer:
rest * 10 + ziffernwertundmod 97in jedem Schritt 2 Punkte,Buchstabe:
rest * 100 + ziffernwert1 Punkt,unzulässiges Zeichen → falsch 1 Punkt, Rückgabe
rest = 11 Punkt.
Wer den Rest erst am Ende einmal bildet statt in jedem Schritt, rechnet mit derselben zu großen Zahl wie in ca) (höchstens 5 Punkte).
cc) Deine Funktion ermittelt für 05711000-ZVRAD-63 den Rest 48. Ermittle daraus ohne erneuten Durchlauf durch alle Zeichen, welche zweistellige Prüfziffer richtig wäre, und begründe Dein Vorgehen. (3 Punkte)
Die Prüfziffer bildet die letzten beiden Stellen der Zahl. Ersetzt man 63 durch 00, verringert sich die Zahl um 63, der Rest also ebenfalls um 63 (modulo 97):
r_{00} = (48 - 63) \bmod 97 = -15 \bmod 97 = 82
Damit die Zahl mit der richtigen Prüfziffer pz den Rest 1 hat, muss (82 + pz) \bmod 97 = 1 gelten, also
pz = 98 - 82 = \underline{\underline{16}}
Die korrekte Leitweg-ID lautet 05711000-ZVRAD-16; eine Kontrolle mit pruefeLeitwegId ergibt den Rest 1. Natalia sollte die ID trotzdem beim Zweckverband erfragen, denn der Fehler kann auch in einem anderen Teil der ID liegen (siehe ba).
Bewertung: Rest für die Prüfziffer 00 (82) 1 Punkt, Prüfziffer 16 1 Punkt, Begründung (Rest-Arithmetik bzw. Prüfbedingung Rest 1) 1 Punkt. Alternativ volle Punktzahl für eine nachvollziehbare Neuberechnung mit 00 und 98 - Rest.
d) Ab Januar 2027 bekommt jedes Fahrrad nach der ersten Inspektion in der Werkstatt Sennestadt eine zehnstellige Servicenummer, die Kund*innen im Werkstattportal eingeben. Die letzte Ziffer ist eine Prüfziffer nach dem Luhn-Verfahren:
Von rechts beginnend wird jede zweite Ziffer verdoppelt, beginnend mit der Ziffer links neben der Prüfziffer.
Ist ein verdoppelter Wert größer als 9, wird seine Quersumme verwendet.
Alle Werte werden addiert. Die Summe wird auf die nächstgrößere durch 10 teilbare Zahl aufgerundet (ist sie schon durch 10 teilbar, bleibt sie). Die Prüfziffer ist die Differenz zwischen aufgerundetem Wert und Summe.
Jonas hat dazu folgende Funktion geschrieben:
Funktion pruefeServicenummer(nr: string): boolean
summe := 0
zähle i von 0 bis laenge(nr) - 2
z := ziffernwert(nr[i])
wenn i mod 2 = 0 dann
z := z * 2
wenn z > 9 dann
z := z - 10
Ende wenn
Ende wenn
summe := summe + z
Ende zähle
pz := 10 - summe mod 10
Rückgabe pz = ziffernwert(nr[laenge(nr) - 1])
Ende pruefeServicenummer
da) Ermittle mit einem Schreibtischtest für die Servicenummer 3057182648 die Werte von z und summe nach jedem Schleifendurchlauf sowie den Rückgabewert der Funktion. Gib an, ob die Nummer nach der Vorschrift gültig ist. (3 Punkte)
| i | nr[i] | verdoppeln? | z | summe |
|---|---|---|---|---|
| 0 | 3 | ja | 6 | 6 |
| 1 | 0 | nein | 0 | 6 |
| 2 | 5 | ja | 10 → 0 | 6 |
| 3 | 7 | nein | 7 | 13 |
| 4 | 1 | ja | 2 | 15 |
| 5 | 8 | nein | 8 | 23 |
| 6 | 2 | ja | 4 | 27 |
| 7 | 6 | nein | 6 | 33 |
| 8 | 4 | ja | 8 | 41 |
pz = 10 - 41 mod 10 = 9, die letzte Ziffer ist 8 → Rückgabe falsch.
Nach der Vorschrift ist die Nummer aber gültig: Die verdoppelte 5 ergibt 10 mit der Quersumme 1, die Summe ist 42, aufgerundet 50, Prüfziffer 8.
Bewertung: Tabelle 2 Punkte (bis zum ersten Fehler richtig: 1 Punkt), Rückgabewert und Aussage zur Gültigkeit 1 Punkt.
db) Nenne die beiden Fehler in Jonas’ Funktion und korrigiere sie. Gib außerdem an, unter welcher Voraussetzung die Bedingung i mod 2 = 0 die richtigen Ziffern verdoppelt. (5 Punkte)
Quersumme falsch:
z := z - 10ergibt für 10 … 18 die Werte 0 … 8 statt der Quersumme 1 … 9. Richtig istz := z - 9.Prüfziffer bei einer Summe mit Rest 0 falsch:
10 - summe mod 10ergibt 10 statt 0, wenn die Summe schon durch 10 teilbar ist; jede gültige Nummer mit Prüfziffer 0 wird abgelehnt. Richtig istpz := (10 - summe mod 10) mod 10oder wie in der Vorschrift:
aufgerundet: integer := summe
wenn summe mod 10 <> 0 dann
aufgerundet := summe + 10 - summe mod 10
Ende wenn
pz: integer := aufgerundet - summe
Voraussetzung für i mod 2 = 0: Die Servicenummer hat neun Nutzziffern (insgesamt zehn Stellen). Dann steht die Ziffer links neben der Prüfziffer auf Index 8, also auf einem geraden Index, und von links werden die Indizes 0, 2, 4, 6, 8 verdoppelt. Bei einer anderen Länge müsste von rechts gezählt werden: (laenge(nr) - 2 - i) mod 2 = 0. Eine Längenprüfung (laenge(nr) = 10) und eine Prüfung auf Ziffern wären sinnvolle Ergänzungen.
Bewertung: je Fehler 1 Punkt für das Nennen und 1 Punkt für die Korrektur (4 Punkte), Voraussetzung 1 Punkt.
dc) Sophie Bertram fragt, ob das Werkstattportal mit der Prüfung der Servicenummer schon sicherstellt, dass ein Fahrrad mit dieser Nummer existiert. Begründe Deine Antwort. (2 Punkte)
Nein. Die Prüfziffer zeigt nur, dass die Nummer formal gültig ist, also wahrscheinlich nicht vertippt wurde. Jede zehnte zufällig gebildete Nummer hat ebenfalls eine passende Prüfziffer, und auch eine gültige Nummer muss nicht vergeben sein. Ob es das Fahrrad gibt (und ob es der angemeldeten Person gehört), muss zusätzlich in der Datenbank geprüft werden. Die Prüfziffer spart dabei unnötige Abfragen und erlaubt sofort eine verständliche Fehlermeldung („Bitte Nummer prüfen“).
Bewertung: Nein mit Begründung (nur Tippfehlererkennung) 1 Punkt, Datenbankprüfung bzw. Zuordnung zum Konto 1 Punkt.
e) Die Lipper SchließTec KG vergibt für gleichschließende Schlösser Schließungscodes wie VS-7Q4K2M9. Mit dem Code können Schlüssel nachbestellt werden; Birgit Haas, Vertriebsleiterin bei SchließTec, bittet deshalb darum, die Codes vertraulich zu behandeln. Jonas schlägt vor, an jeden Code ein Prüfzeichen anzuhängen, „damit sich niemand einen Code ausdenken und Schlüssel für fremde Schlösser bestellen kann“. Nimm Stellung zu diesem Vorschlag. (3 Punkte)
Ein Prüfzeichen ist sinnvoll, um Tippfehler beim Eingeben des Codes sofort zu erkennen. Gegen absichtliches Erfinden schützt es nicht: Das Verfahren ist bekannt oder lässt sich aus wenigen echten Codes ableiten, und wer einen Code ausprobieren will, berechnet das passende Prüfzeichen einfach mit. Schutz bieten stattdessen ausreichend lange, kryptografisch zufällige Codes (großer Nummernraum), die Prüfung gegen die Datenbank, eine Bindung an das Kundenkonto (Nachbestellung nur durch die angemeldete Person, ggf. mit zusätzlicher Bestätigung) und eine Begrenzung der Fehlversuche.
Bewertung: Nutzen gegen Tippfehler 1 Punkt, kein Schutz gegen Fälschung mit Begründung 1 Punkt, geeignete Alternative 1 Punkt.
f) Im Projekt „Lager 4.0“ bekommt jeder Lagerplatz ein Etikett. Die Lagerplätze stehen im zweidimensionalen Array lager: int[][]; jede Zeile ist ein Lagerplatz mit den Spalten 0 = Regal (1 bis 40), 1 = Ebene (1 bis 6), 2 = Fach (1 bis 30), 3 = Artikel-ID, 4 = Bestand. Ausschnitt:
| Zeile | Regal | Ebene | Fach | Artikel-ID | Bestand |
|---|---|---|---|---|---|
| 0 | 3 | 1 | 12 | 8 | 5 |
| 1 | 7 | 2 | 5 | 7 | 30 |
| 2 | 11 | 4 | 2 | 8 | 4 |
| 3 | 7 | 3 | 5 | 7 | 18 |
| 4 | 12 | 1 | 1 | 1 | 12 |
Für die Entnahme soll der Handscanner anzeigen, an welchem Lagerplatz ein Artikel am meisten Bestand hat. Der Lagerplatz wird als Zeichenkette im Format R07-E2-F05 angegeben: R, zweistellige Regalnummer, -E, Ebene, -F, zweistellige Fachnummer.
Erstelle eine Funktion lagerplatzText(lager: integer[][], artikelId: integer): string, die den Lagerplatz mit dem höchsten Bestand des Artikels in diesem Format zurückgibt. Liegt der Artikel an keinem Lagerplatz, gibt sie eine leere Zeichenkette zurück. Bei gleichem Bestand genügt der erste Lagerplatz. (8 Punkte)
Funktion lagerplatzText(lager: integer[][], artikelId: integer): string
maxBestand: integer := -1
pos: integer := -1
zähle i von 0 bis laenge(lager) - 1
wenn lager[i][3] = artikelId und lager[i][4] > maxBestand dann
maxBestand := lager[i][4]
pos := i
Ende wenn
Ende zähle
wenn pos = -1 dann
Rückgabe ""
Ende wenn
Rückgabe "R" & zweistellig(lager[pos][0]) & "-E" & zuText(lager[pos][1]) & "-F" & zweistellig(lager[pos][2])
Ende lagerplatzText
Funktion zweistellig(zahl: integer): string
wenn zahl < 10 dann
Rückgabe "0" & zuText(zahl)
Ende wenn
Rückgabe zuText(zahl)
Ende zweistellig
Ergebnisse für den Ausschnitt: Artikel 8 → R03-E1-F12, Artikel 7 → R07-E2-F05, Artikel 1 → R12-E1-F01, Artikel 9 → "".
Bewertung:
Startwerte für Maximum und Position 1 Punkt,
Schleife über alle Zeilen, Vergleich der Artikel-ID 1 Punkt,
Maximum und Position merken 2 Punkte,
leere Zeichenkette, wenn nichts gefunden 1 Punkt,
Zeichenkette in der richtigen Reihenfolge mit Trennzeichen zusammensetzen 1 Punkt,
führende Null für Regal und Fach 2 Punkte (Hilfsfunktion oder Verzweigung direkt im Rumpf).
Aufgabe 3.2: Badges und Türschilder für das Barcamp (Profilkompetenz)
(ca. 37 min Bearbeitungszeit)
Du bist Auszubildende*r und gehörst zum Orga-Team des Barcamps „Lernen.Digital.Leben 2027“, das am Samstag, 13.03.2027, am Ratz und Rübe Berufskolleg (RRB) in Bielefeld stattfindet. Dimitrios Papadopoulos, der die Organisation leitet, hat Dir die Weiterentwicklung der Software für Badges und Türschilder übertragen. Mia Schröder (Azubi FIA im 3. Lehrjahr) und Emre Aksoy aus dem Technikteam arbeiten mit Dir zusammen.
a) Bisher bestehen die Badge-Codes aus BC27, einem Buchstaben für die Ticketart (z. B. R für Referent*in, S für Schüler*in) und der dreistelligen Anmeldenummer, etwa BC27R005. Weil man daraus die Codes anderer Teilnehmender erraten kann, bekommt jede Person künftig einen Code aus sieben Zeichen der Zeichenkette ALPHABET = "ACDEFHJKMNPRTUVWXY34679". Diese 23 Zeichen lassen sich auf Badge und Bildschirm kaum verwechseln; der Wert eines Zeichens ist sein Index in ALPHABET ('A' = 0, 'C' = 1, …, '9' = 22).
Die ersten sechs Zeichen werden zufällig gewählt, das siebte ist ein Prüfzeichen. Das Check-in-Terminal erkennt einen gültigen Code so: Es gewichtet die Werte der sieben Zeichen von links nach rechts mit 7, 6, 5, 4, 3, 2 und 1, addiert die Produkte, und die Summe muss durch 23 teilbar sein. Beim Erzeugen wird das Prüfzeichen deshalb so gewählt, dass es die gewichtete Summe der ersten sechs Zeichen zum nächsten Vielfachen von 23 ergänzt: Es hat den Wert (23 - summe mod 23) mod 23.
Beispiel: Für MW3FAY mit den Werten 8, 15, 18, 4, 0, 17 ergibt sich 7 · 8 + 6 · 15 + 5 · 18 + 4 · 4 + 3 · 0 + 2 · 17 = 286, 286 mod 23 = 10, Prüfzeichen hat den Wert 13, also 'U'. Der Code lautet MW3FAYU; das Terminal rechnet 286 + 1 · 13 = 299 = 13 · 23.
Die bereits vergebenen Codes verwaltet der Check-in-Server in einer Menge vergeben (entspricht Set<String> in Java bzw. set in Python) mit den Methoden enthaelt(code: string): boolean und hinzufuegen(code: string). Außerdem steht zufallszahl(von: integer, bis: integer): integer zur Verfügung; sie liefert eine ganze Zufallszahl von von bis einschließlich bis.
Mia hat einen ersten Entwurf geschrieben:
Funktion erzeugeBadgeCode(vergeben: Menge): string
code := ""
summe := 0
wiederhole
zähle i von 0 bis 5
wert := zufallszahl(0, laenge(ALPHABET))
code := code & ALPHABET[wert]
summe := summe + (7 - i) * wert
Ende zähle
code := code & ALPHABET[summe mod 23]
solange vergeben.enthaelt(code)
Rückgabe code
Ende erzeugeBadgeCode
aa) Mias Entwurf enthält vier Fehler. Benenne sie und beschreibe jeweils, was beim Barcamp-Check-in passieren würde. (4 Punkte)
codeundsummewerden vor der Schleife zurückgesetzt: Ist der erste Code schon vergeben, hängt der zweite Versuch weitere sieben Zeichen an, und die Summe wächst weiter. Es entstehen Codes mit 14, 21, … Zeichen, die das Terminal nie als gültig erkennt.zufallszahl(0, laenge(ALPHABET))liefert auch 23: Der größte Index ist 22. Gelegentlich bricht die Funktion mit einem Indexfehler ab – ein Fehler, der im Test leicht übersehen wird, weil er nur selten auftritt.Prüfzeichen
summe mod 23statt Ergänzung: Mia hängt den Rest an, nicht die Ergänzung zum nächsten Vielfachen von 23. Die Prüfung am Terminal schlägt dann für fast alle Codes fehl (richtig ist sie nur, wenn der Rest 0 ist).Code wird nicht in
vergebenaufgenommen: Die Funktion prüft gegen die Menge, trägt den neuen Code aber nicht ein. Ein späterer Aufruf kann denselben Code noch einmal liefern, zwei Personen hätten dann denselben Badge.
Bewertung: je Fehler mit Auswirkung 1 Punkt.
ab) Dimitrios möchte außerdem verhindern, dass das Programm bei fast vollem Nummernraum endlos weitersucht. Stelle die korrigierte Funktion erzeugeBadgeCode(vergeben: Menge): string als Struktogramm dar. Sie bricht nach höchstens 50 Versuchen ab und gibt dann eine leere Zeichenkette zurück; einen gefundenen Code nimmt sie in vergeben auf. (8 Punkte)
Als Pseudocode:
Funktion erzeugeBadgeCode(vergeben: Menge): string
code: string := ""
versuche: integer := 0
wiederhole
code := ""
summe: integer := 0
zähle i von 0 bis 5
wert: integer := zufallszahl(0, laenge(ALPHABET) - 1)
code := code & ALPHABET[wert]
summe := summe + (7 - i) * wert
Ende zähle
code := code & ALPHABET[(23 - summe mod 23) mod 23]
versuche := versuche + 1
solange vergeben.enthaelt(code) und versuche < 50
wenn vergeben.enthaelt(code) dann
Rückgabe ""
Ende wenn
vergeben.hinzufuegen(code)
Rückgabe code
Ende erzeugeBadgeCode
Ebenfalls richtig: eine kopfgesteuerte Schleife mit einer Variablen gefunden oder ein vorzeitiges Rückgabe code innerhalb einer Zählschleife über die 50 Versuche.
Bewertung:
Wiederholung mit beiden Bedingungen (Code vergeben und weniger als 50 Versuche) 2 Punkte,
codeundsummeinnerhalb der Wiederholung zurücksetzen, Versuche zählen 1 Punkt,Zufallsindex im Bereich 0 bis 22, Zeichen über den Index 1 Punkt,
gewichtete Summe mit Gewicht
7 - i1 Punkt,Prüfzeichen als Ergänzung
(23 - summe mod 23) mod 231 Punkt,nach der Schleife unterscheiden: leere Zeichenkette oder Code aufnehmen und zurückgeben 1 Punkt,
formal korrektes Struktogramm (DIN 66261) 1 Punkt.
ac) Emre fragt, wozu der Aufwand gut ist. Begründe kurz, warum die Codes nicht mehr fortlaufend nummeriert werden, warum ein eigenes Alphabet verwendet wird und was das Prüfzeichen leistet – und was nicht. (3 Punkte)
Zufall statt Nummerierung: Fortlaufende Codes lassen sich erraten (wer
BC27R005hat, probiertBC27R006). Mit sechs Zufallszeichen aus 23 gibt es rund 148 Millionen Möglichkeiten; bei 400 Teilnehmenden ist ein geratener Code praktisch nie gültig. Für echten Schutz solltezufallszahlein kryptografisch sicherer Zufallsgenerator sein.Eigenes Alphabet: Zeichen wie
0/O,1/I/L,5/S,8/Bwerden beim Abtippen am Infostand leicht verwechselt; ohne sie gibt es weniger Rückfragen.Prüfzeichen: Es erkennt Tippfehler sofort am Terminal, ohne Nachschlagen in der Menge. Weil 23 eine Primzahl ist und die Gewichte 1 bis 7 verschieden und kleiner als 23 sind, fällt jedes falsche Einzelzeichen und jede Vertauschung zweier benachbarter Zeichen auf. Vor Fälschung schützt es nicht, denn die Regel lässt sich nachrechnen.
Bewertung: je Entscheidung 1 Punkt.
b) Die zwölf E-Ink-Türschilder bekommen ihre Anzeige per MQTT vom Info-Server. Das Schwarz-Weiß-Display ist 800 Pixel breit. Im Prototyp überträgt Emre jede Bildzeile als Zeichenkette aus 'W' (weißes Pixel) und 'S' (schwarzes Pixel). Weil es nur zwei Farben gibt, schlägt er eine Lauflängenkodierung vor, die gar keine Zeichen speichert, sondern nur die Längen der Läufe:
Die Läufe wechseln sich ab; der erste Lauf ist immer weiß.
Die Längen werden als Dezimalzahlen, durch Kommas getrennt, übertragen.
Beginnt eine Zeile mit einem schwarzen Pixel, ist die erste Länge 0.
Beispiel: WWWWSSSSSSSWWWWWWWWWWWWS (24 Zeichen) wird zu 4,7,12,1 (8 Zeichen).
ba) Kodiere von Hand die Zeilen SSSWWWWWSWW und WSWSWSWS. Beurteile anhand Deiner Ergebnisse, für welche Bildinhalte sich die Kodierung lohnt. (3 Punkte)
SSSWWWWWSWW(11 Zeichen) →0,3,5,1,2(9 Zeichen): Die Zeile beginnt schwarz, deshalb steht vorne ein weißer Lauf der Länge 0.WSWSWSWS(8 Zeichen) →1,1,1,1,1,1,1,1(15 Zeichen): fast doppelt so lang.
Die Kodierung lohnt sich bei langen gleichfarbigen Flächen, also bei Text auf weißem Grund, Rahmen und Balken. Bei feinen Mustern mit häufigem Farbwechsel (Raster, Schachbrett, Fotos) wird sie länger als das Original.
Bewertung: je Kodierung 1 Punkt, Beurteilung 1 Punkt.
bb) Entwickle eine Funktion kodiere(zeile: string): string, die eine Bildzeile nach dieser Vorschrift kodiert. (8 Punkte)
Funktion kodiere(zeile: string): string
ergebnis: string := ""
farbe: char := 'W'
anzahl: integer := 0
zähle i von 0 bis laenge(zeile) - 1
wenn zeile[i] = farbe dann
anzahl := anzahl + 1
sonst
ergebnis := ergebnis & zuText(anzahl) & ","
farbe := zeile[i]
anzahl := 1
Ende wenn
Ende zähle
ergebnis := ergebnis & zuText(anzahl) // letzter Lauf
Rückgabe ergebnis
Ende kodiere
Weil farbe mit 'W' beginnt, entsteht bei einer schwarz beginnenden Zeile automatisch die Länge 0 am Anfang. Ebenfalls richtig ist eine äußere Schleife mit innerer Zählschleife je Lauf wie im Artikel; dann muss die erste Länge 0 als Sonderfall behandelt werden.
Bewertung:
Ergebnis, aktuelle Farbe
'W'und Zähler initialisieren 1 Punkt,Schleife über alle Zeichen der Zeile 1 Punkt,
gleiche Farbe: Zähler erhöhen 1 Punkt,
Farbwechsel: Länge als Text und Komma anhängen 2 Punkte,
Farbe wechseln und Zähler auf 1 setzen 1 Punkt,
letzten Lauf nach der Schleife anhängen 1 Punkt,
Rückgabe 1 Punkt.
Typische Fehler: letzter Lauf fehlt, Zähler nach dem Wechsel auf 0 statt 1, führende 0 für schwarz beginnende Zeilen vergessen.
bc) Mia hat die Gegenstelle auf dem Türschild programmiert:
Funktion dekodiere(daten: string): string
ergebnis := ""
farbe := 'W'
anzahl := 0
zähle i von 0 bis laenge(daten)
wenn i < laenge(daten) und istZiffer(daten[i]) dann
anzahl := anzahl * 10 + ziffernwert(daten[i])
sonst
zähle k von 1 bis anzahl
ergebnis := ergebnis & farbe
Ende zähle
wenn farbe = 'W' dann
farbe := 'S'
sonst
farbe := 'W'
Ende wenn
anzahl := 0
Ende wenn
Ende zähle
Rückgabe ergebnis
Ende dekodiere
Ermittle für den Aufruf dekodiere("0,5,3,12") die Werte, die anzahl jeweils beim Erreichen des Sonst-Zweigs hat, und den Rückgabewert. Erkläre, warum die Zählschleife bis laenge(daten) und nicht bis laenge(daten) - 1 läuft. (3 Punkte)
Index 1 (Komma): anzahl = 0, kein weißes Pixel, Farbe wird schwarz.
Index 3 (Komma): anzahl = 5, fünf schwarze Pixel, Farbe wird weiß.
Index 5 (Komma): anzahl = 3, drei weiße Pixel, Farbe wird schwarz.
Index 8 (
i = laenge(daten)): Die Ziffern'1'und'2'wurden zu anzahl = 12 zusammengesetzt; zwölf schwarze Pixel.
Rückgabe: SSSSSWWWSSSSSSSSSSSS (0 + 5 + 3 + 12 = 20 Zeichen).
Hinter der letzten Zahl steht kein Komma. Der zusätzliche Durchlauf mit i = laenge(daten) wirkt wie ein Komma am Ende und gibt den letzten Lauf aus; die Bedingung i < laenge(daten) steht vorne, damit dabei nicht hinter die Zeichenkette gelesen wird.
Bewertung: Werte von anzahl 1 Punkt, Rückgabewert 1 Punkt, Begründung 1 Punkt.
bd) Im Team gibt es zwei Vorschläge, die Datenmenge weiter zu verringern:
Mia: „Die Kommas weglassen – die Zahlen stehen ja ohnehin hintereinander.“
Emre: „Jede Länge als ein Byte (Binärwert 0 bis 255) senden statt als Dezimaltext mit Komma.“
Beurteile beide Vorschläge. Gib für Emres Vorschlag an, wie eine vollständig weiße Bildzeile übertragen werden kann. (4 Punkte)
Mias Vorschlag ist unbrauchbar: Ohne Trennzeichen ist nicht mehr erkennbar, wo eine Länge endet.
05312kann 0, 5, 3, 12 bedeuten, aber auch 0, 53, 12 oder 0, 5, 31, 2 – alles gültige, aber verschiedene Bildzeilen. Die Kodierung wird mehrdeutig.Emres Vorschlag ist eindeutig und kompakt: Jede Länge belegt genau ein Byte, ein Trennzeichen ist überflüssig. Allerdings passt eine Länge über 255 nicht in ein Byte, und eine Zeile ist bis zu 800 Pixel lang. Abhilfe: Ein zu langer Lauf wird aufgeteilt, dazwischen steht ein Lauf der Länge 0 der anderen Farbe. Eine weiße Zeile wird so zu den sieben Bytes 255, 0, 255, 0, 255, 0, 35 (3 · 255 + 35 = 800).
Bewertung: Mehrdeutigkeit mit Beispiel 2 Punkte, Vorteil von Emres Vorschlag 1 Punkt, Umgang mit Läufen über 255 einschließlich Beispiel 1 Punkt.
c) Die Badge-Drucker drucken den Namen in einer Zeile mit höchstens 18 Zeichen.
ca) Erstelle eine Funktion badgeName(vorname: string, nachname: string): string nach folgender Regel:
Passt „Vorname Nachname“ (mit einem Leerzeichen) in 18 Zeichen, wird er so gedruckt.
Sonst wird der Vorname auf den Anfangsbuchstaben mit Punkt gekürzt („V. Nachname“), wenn das passt.
Passt auch das nicht, werden die ersten 17 Zeichen des Nachnamens mit einem Punkt gedruckt.
Gib außerdem an, was Deine Funktion für Dimitrios Papadopoulos und für Petra Schulze-Albers liefert. (5 Punkte)
Funktion badgeName(vorname: string, nachname: string): string
name: string := vorname & " " & nachname
wenn laenge(name) <= 18 dann
Rückgabe name
Ende wenn
name := teilText(vorname, 0, 1) & ". " & nachname
wenn laenge(name) <= 18 dann
Rückgabe name
Ende wenn
Rückgabe teilText(nachname, 0, 17) & "."
Ende badgeName
Ergebnisse: „Dimitrios Papadopoulos“ hat 22 Zeichen → D. Papadopoulos (15 Zeichen). „Petra Schulze-Albers“ hat 20 Zeichen → P. Schulze-Albers (17 Zeichen). „Oluwaseun Adeyemi“ (17 Zeichen) bliebe unverändert.
Bewertung: Name mit Leerzeichen zusammensetzen und Länge prüfen 1 Punkt, Kürzung mit teilText und ". " 1 Punkt, Kürzung des Nachnamens 1 Punkt, Reihenfolge der Fälle 1 Punkt, beide Beispiele 1 Punkt.
cb) Für die Türschilder hat Mia folgende Zeile geschrieben; slot ist der Index des Session-Slots (0 bis 4), raum der Raumname:
kopf := "Slot " + slot + 1 + " | " + raum
Ermittle den Inhalt von kopf für slot = 1 und raum = "A.104", erläutere die Ursache und korrigiere die Zeile. (3 Punkte)
kopf enthält "Slot 11 | A.104" statt "Slot 2 | A.104".
Ursache: Der Ausdruck wird von links nach rechts ausgewertet. "Slot " + slot ergibt bereits eine Zeichenkette ("Slot 1"), an die + 1 als Text angehängt wird.
Korrektur: kopf := "Slot " + (slot + 1) + " | " + raum oder kopf := "Slot " + zuText(slot + 1) + " | " + raum.
Bewertung: Inhalt 1 Punkt, Ursache 1 Punkt, Korrektur 1 Punkt.
Links und weitere Informationen
Zeichenketten und Prüfziffern: Algorithmen für Codes, Nummern und Texte
Prozedurale Algorithmen mit Arrays: suchen, zählen, Extremwerte und Gruppenwechsel
Hinweis zur Nachnutzung als Open Educational Resource (OER)
Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Übungsaufgaben zu Zeichenketten und Prüfziffern” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/zeichenketten-pruefziffern-uebungsaufgaben veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/algorithmik/algorithmen. Erstellt mit KI-Assistenz; von mir umfassend redaktionell überarbeitet, geprüft und freigegeben. Stand: 29.10.2026.
[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]
