Programming lesson
Checksum-Berechnung in C: 8-, 16- und 32-Bit-Prüfsummen für ASCII-Dateien
Lerne in diesem Tutorial, wie du ein C-Programm schreibst, das die 8-, 16- und 32-Bit-Checksumme für eine ASCII-Textdatei berechnet. Schritt-für-Schritt-Anleitung mit Codebeispielen und Tipps zur Fehlerbehandlung.
Einführung: Warum Checksummen wichtig sind
Checksummen sind ein grundlegendes Werkzeug der Datenintegritätsprüfung. Ob beim Download von Dateien, bei der Übertragung über Netzwerke oder in der Speicherung – eine einfache Prüfsumme hilft, Fehler zu erkennen. In diesem Tutorial lernst du, wie du ein C-Programm schreibst, das aus einer ASCII-Textdatei eine 8-, 16- oder 32-Bit-Checksumme berechnet. Das Programm wird über die Kommandozeile gesteuert und gibt die Ergebnisse formatiert aus. Dieses Projekt entspricht typischen Aufgaben aus der Systemprogrammierung und ist ideal, um deine Fähigkeiten in C zu vertiefen.
Stell dir vor, du entwickelst eine App, die Spielstände eines Turniers speichert. Eine Checksumme stellt sicher, dass die Daten nicht korrupt sind. Oder in der Finanzwelt: Bei Überweisungen wird eine Prüfsumme verwendet, um Tippfehler zu vermeiden. Genau solche Konzepte lernst du hier.
Ziel des Programms
Dein Programm soll zwei Kommandozeilenparameter entgegennehmen: den Dateinamen einer ASCII-Textdatei und die gewünschte Checksummen-Größe (8, 16 oder 32 Bit). Es öffnet die Datei, gibt den Inhalt auf der Konsole aus, berechnet die Prüfsumme und gibt sie im Format %2d bit checksum is %8lx for all %4d chars aus. Bei ungültiger Größe wird eine Fehlermeldung auf STDERR ausgegeben.
Schritt 1: Kommandozeilenparameter einlesen
Der erste Schritt ist das Einlesen der Argumente. In C geschieht das über argc und argv. Prüfe, ob genau zwei Argumente übergeben wurden. Das zweite Argument (die Checksummen-Größe) muss in eine ganze Zahl umgewandelt werden. Ist sie nicht 8, 16 oder 32, gib eine Fehlermeldung aus und beende das Programm.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s inputFile.txt checksumSize\n", argv[0]);
return 1;
}
int checksumSize = atoi(argv[2]);
if (checksumSize != 8 && checksumSize != 16 && checksumSize != 32) {
fprintf(stderr, "Valid checksum sizes are 8, 16, or 32\n");
return 1;
}
// ...
}Schritt 2: Datei öffnen und Inhalt ausgeben
Öffne die Datei im Lesemodus. Lese Zeichen für Zeichen (oder blockweise) und gib sie auf STDOUT aus. Achte darauf, dass du insgesamt 80 Zeichen pro Zeile ausgibst – das ist ein typisches Format für Textdateien. Zähle dabei die Anzahl der gelesenen Zeichen, denn du benötigst sie für die Ausgabe der Checksumme.
FILE *file = fopen(argv[1], "r");
if (!file) {
fprintf(stderr, "Error opening file\n");
return 1;
}
int ch;
int charCount = 0;
while ((ch = fgetc(file)) != EOF) {
putchar(ch);
charCount++;
}
rewind(file); // Zurücksetzen für Checksum-BerechnungSchritt 3: Checksumme berechnen
Die Checksumme ist eine laufende Summe aller Zeichenwerte (als unsigned int). Wichtig: Es gibt keinen Überlauf – die Summe wird einfach in einer Variable der entsprechenden Größe gehalten. Für 8 Bit verwendest du unsigned char, für 16 Bit unsigned short, für 32 Bit unsigned int. Du kannst aber auch immer eine 32-Bit-Variable verwenden und später maskieren.
Lese die Datei erneut Zeichen für Zeichen und addiere den Wert jedes Zeichens zur Summe. Nachdem alle Zeichen verarbeitet wurden, musst du die Summe ggf. auf die gewünschte Bitbreite reduzieren:
- 8 Bit:
checksum & 0xFF - 16 Bit:
checksum & 0xFFFF - 32 Bit:
checksum & 0xFFFFFFFF
Zusätzlich wird bei 16 und 32 Bit eine Padding-Information benötigt. Die Padding-Bytes werden in der Ausgabe als Hex-Zahl angehängt. Die genaue Berechnung des Paddings ist in der Aufgabenstellung beschrieben: Es werden so viele 'XX'-Bytes angehängt, dass die Gesamtzahl der Zeichen ein Vielfaches der Checksummen-Größe in Bytes ist. Du kannst das Padding als separate Variable berechnen und später ausgeben.
unsigned int checksum = 0;
int ch;
while ((ch = fgetc(file)) != EOF) {
checksum += (unsigned char)ch;
}
// Reduzieren auf gewünschte Bitbreite
unsigned int result;
switch (checksumSize) {
case 8: result = checksum & 0xFF; break;
case 16: result = checksum & 0xFFFF; break;
case 32: result = checksum & 0xFFFFFFFF; break;
}
// Padding berechnen (vereinfacht):
int padding = (checksumSize/8) - (charCount % (checksumSize/8));
if (padding == (checksumSize/8)) padding = 0;
// Ausgabe
printf("%2d bit checksum is %8lx for all %4d chars\n", checksumSize, result, charCount);Schritt 4: Formatierte Ausgabe
Die Ausgabe muss exakt dem geforderten Format entsprechen. Verwende printf mit den Platzhaltern %2d für die Checksummen-Größe, %8lx für die Checksumme (als Hexadezimal, 8 Stellen breit) und %4d für die Zeichenanzahl. Vergiss nicht, nach dem Dateiinhalt eine neue Zeile einzufügen, falls nötig.
Beispiel für eine korrekte Ausgabe:
This is a test.
8 bit checksum is 6b for all 12 charsSchritt 5: Fehlerbehandlung und Testen
Dein Programm sollte robust sein. Behandle folgende Fälle:
- Datei existiert nicht oder kann nicht geöffnet werden → Fehlermeldung auf STDERR.
- Ungültige Checksummen-Größe → Fehlermeldung auf STDERR.
- Leere Datei → Checksumme ist 0, Zeichenanzahl 0.
Teste dein Programm mit den beigelegten Testdateien (i1.txt bis i5.txt). Die erwarteten Checksummen findest du in der Aufgabenstellung. Verwende das Bash-Skript basetest.sh, um deine Ausgabe mit der Referenz zu vergleichen.
Häufige Fehler und Tipps
- Vergiss nicht, die Datei nach dem ersten Durchlauf zurückzusetzen (
rewind) oder erneut zu öffnen. - Achte auf den Unterschied zwischen
unsigned charundchar– Zeichen können negativ sein, daher immerunsigned charverwenden. - Der Zeilenvorschub (LF, 0x0A) ist Teil der Checksumme. Zähle ihn mit.
- Die Padding-Berechnung kann knifflig sein. Studiere die Beispiele in der Aufgabenstellung genau.
Zusammenfassung
Du hast gelernt, wie man ein C-Programm schreibt, das eine 8-, 16- oder 32-Bit-Checksumme für eine ASCII-Datei berechnet. Dieses Projekt festigt Grundlagen der Dateiverarbeitung, Kommandozeilenargumente und Bit-Manipulation. Solche Checksummen werden in vielen Bereichen eingesetzt, von der Netzwerkkommunikation bis zur Spieleentwicklung. Probiere es selbst aus und passe das Programm an – vielleicht erweiterst du es um eine Überprüfungsfunktion oder eine grafische Oberfläche.