Hallo ihr,
hier mein Code, um zu testen, ob es sich bei einem String um eine korrekte ISBN handelt.
Ein alternativer Code für die "alte" ISBN10 gibt es
hier.
Dieser hier geht von beiden Versionen (ISBN10 und ISBN13) aus:
Delphi-Quellcode:
function IsValidISBN(AISBN : string) : Boolean;
var
CheckSum10, CheckSum13, Digit, i : Integer;
begin
CheckSum10 := 0;
CheckSum13 := 0;
Digit := 0;
for i := 1 to Length(AISBN) do
begin
if (AISBN[i] in ['0'..'9']) or ((Digit = 10) and (AISBN[i] in ['x', 'X'])) then
begin
// Zählt zum einen die Ziffern und zum anderen gibt die aktuelle Stelle in der ISBN als Nummer an.
Inc(Digit);
// Das 10. Zeichen der ISBN10 kann auch ein X sein, und ist dann eine 10
if (Digit = 10) and (AISBN[i] in ['x', 'X']) then
begin
// Und da 10 (Stelle) * 10 (Wert) = 100 ergibt, kann direkt 100 addiert werden
Inc(CheckSum10, 100);
end else
begin
// Bei ISBN13 gilt: Ungerade normal addieren, Gerade Stellen mit 3 multiplizieren und dann addieren
if (Digit mod 2 = 0) then
Inc(CheckSum13, 3 * StrToInt(AISBN[i]))
else
Inc(CheckSum13, StrToInt(AISBN[i]));
// Für die ISBN10 gilt (solange kein zusätzliches Zeichen abgefragt wird): Stelle (beginnend bei 1) * Wert (v.l.n.r.)
if Digit <= 10 then
Inc(CheckSum10, Digit * StrToInt(AISBN[i]));
end;
end;
end;
// Wenn 10 Ziffern (bzw 9 Ziffern und ein X) enthalten waren, muss die Prüfsumme ISBN10 kompatibel sein (PS mod 11 = 0)
// Bei 13 Ziffern muss die Prüfsumme ISBN13 kompatibel sein (PS mod 10 = 0)
// Ansonsten ist es alles andere, nur keine >GÜLTIGE< ISBN
Result := ((CheckSum10 mod 11 = 0) and (Digit = 10)) or ((CheckSum13 mod 10 = 0) and (Digit = 13) and (Copy(AISBN, 1, 2) = '97') and (AISBN[3] in ['8', '7']));
end;
Wer nur ISBN10 oder ISBN13 zulässt für den gibt es die einzelnen Funktionen.
Delphi-Quellcode:
function IsValidISBN10(AISBN10 : string) : Boolean;
var
i, ziffer: Integer;
PruefSumme : Integer;
begin
PruefSumme := 0;
ziffer := 0;
i := 1;
while (Ziffer <= 10) and (i <= Length(AISBN10)) do
begin
if (AISBN10[i] in ['0'..'9']) or ((Ziffer = 10) and (AISBN10[i] in ['x', 'X'])) then
begin
Inc(Ziffer);
if (Ziffer = 10) and (AISBN10[i] in ['x', 'X']) then
Inc(PruefSumme, 100)
else
Inc(PruefSumme, ziffer * StrToInt(AISBN10[i]));
end;
Inc(i);
end;
Result := PruefSumme mod 11 = 0;
end;
function IsValidISBN13(AISBN13 : string) : Boolean;
var
i, ziffer: Integer;
PruefSumme : Integer;
begin
PruefSumme := 0;
ziffer := 0;
i := 1;
while (Ziffer <= 13) and (i <= Length(AISBN13)) do
begin
if (AISBN13[i] in ['0'..'9']) then
begin
Inc(Ziffer);
if (Ziffer mod 2 = 0) then
Inc(PruefSumme, 3 * StrToInt(AISBN13[i]))
else
Inc(PruefSumme, StrToInt(AISBN13[i]));
end;
Inc(i);
end;
Result := PruefSumme mod 10 = 0;
end;
Für ISBN10 ist es leider nicht möglich die ISBN wirklich als ISB-NUMMER zu verwenden, weil das letzte Zeichen ein X sein kann. Aber bei der ISBN13 kann auch eine Zahl angegeben werden (führende Nullen gibt es nicht, da die "Bücherländer" 978 und 979 sind.
Delphi-Quellcode:
function IsValidISBN13(AISBN13 : Int64) : Boolean;
var
i, ziffer: Integer;
PruefSumme : Integer;
begin
PruefSumme := 0;
for i := 1 to 13 do
begin
//AISBN13 mod 10 = Die (13-i). Stelle :P
if i mod 2 = 0 then
Inc(PruefSumme, 3 * AISBN13 mod 10)
else
Inc(PruefSumme, AISBN13 mod 10);
AISBN13 := AISBN13 div 10; // Die letzte Stelle "abschneiden)
end;
Result := PruefSumme mod 10 = 0;
end;
Nur die erste der genannten Funktionen testet bei der ISBN13, ob die ersten drei Ziffern korrekt sind (zur Zeit ziemlich Workaround mäßig... mal sehen, ob ich da mir noch was überlege). So könnte man zufällige gültige ISBN Nummern weiter vermeiden.
MfG
xZise