Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi ISBN Testen (https://www.delphipraxis.net/137278-isbn-testen.html)

xZise 17. Jul 2009 17:12


ISBN Testen
 
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

fkerber 17. Jul 2009 17:15

Re: ISBN Testen
 
Hi!

Kann es sein, dass das hier falsch ist?

Delphi-Quellcode:
(LowerCase(AISBN10[i]) = 'X')
Müsste das nicht ein x sein oder ein UpperCase?


Grüße, Frederic

xZise 17. Jul 2009 21:35

Re: ISBN Testen
 
Ich habe es eh umgeschrieben, da ich damit die Aufrufe von LowerCase spare:
Delphi-Quellcode:
(AISBN[i] in ['x', 'X'])
MfG
xZise


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:55 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz