Einzelnen Beitrag anzeigen

Benutzerbild von cruiser
cruiser

Registriert seit: 23. Dez 2003
Ort: Königsbrück/Sachsen
455 Beiträge
 
Delphi 7 Enterprise
 
#29

Re: Bruch einlesen

  Alt 10. Jun 2007, 20:32
mh... mal eine Funktion, die einen String in eine Extended (Floatingpoint) Variable wandelt.

sollte die Eingabe ungültig sein gibt die Funktion NaN zurück

Beispieleingaben sind: '1,34', '-1,34', '2/3', '-2/3', '1 4/5', '-1 4/5'

Delphi-Quellcode:
function TextToFloat(const s: string): Extended;
const
  NaN = 0.0 / 0.0;
var
  allowed: set of Char;
  decpos,l,i: Integer;
  m, g, z, n: Extended;
  pc: ^Char;
  aftercomma, evalz, evaln: Boolean;

  // Hilfsfunktion fuer 10er Potenz
  function decposmul: Extended;
  begin
    Result := Exp(decpos * Ln(10));
  end;
begin
  // Ergebnis ist noch keine Zahl
  Result := NaN;

  // laenge ermitteln, bei bedarf rausgehn
  l := Length(s);
  if l = 0 then Exit;

  // Stati setzen
  allowed := ['0'..'9', ' ', '/'];
  aftercomma := False;
  evalz := False;
  evaln := False;

  // Position + Pointer auf Start setzen
  i := 1;
  pc := @s[i];

  // Positiv/Negativ Auswertung
  if pc^ = '-then begin
    m := -1.0;
    Inc(pc);
    Inc(i);
  end else if pc^ = '+then begin
    m := 1.0;
    Inc(pc);
    Inc(i);
  end else begin
    m := 1.0;
  end;

  // Werte setzen
  decpos := 0;
  g := 0.0;
  z := 0.0;
  n := 0.0;

  // Ganzzahl/Dezimalzal (X)
  while i <= l do begin
    // Zeichen nicht erlaubt -> Funktion beenden
    if not((pc^ in allowed) or (pc^ = DecimalSeparator)) then Exit;
    // Leerzeichen trennt ganze Zahl von Bruch
    if pc^ = ' then begin
      // Komma wurde vorher gefunden -> ungueltig
      if aftercomma then Exit;
      Inc(pc);
      Inc(i);
      evalz := True;
      Break;
    end;
    // Schraegstrich trennt Zaehler und Nenner
    if pc^ = '/then begin
      // Komma wurde vorher gefunden -> ungueltig
      if aftercomma then Exit;
      z := g;
      g := 0.0;
      evaln := True;
      Inc(pc);
      Inc(i);
      Break;
    end;
    // Komma (oder Punkt) fuer Dezimalzahlen
    if pc^ = DecimalSeparator then begin
      aftercomma := True;
      Inc(pc);
      Inc(i);
      Continue;
    end;
    // Zahlen auswerten
    if aftercomma then begin
      Dec(decpos);
      g := decposmul * (Ord(pc^) - 48) + g;
    end else begin
      g := g * 10 + (Ord(pc^) - 48);
    end;
    Inc(i);
    Inc(pc);
  end;

  allowed := ['0'..'9', '/'];

  if evalz then begin
    while i <= l do begin
      // Zeichen nicht erlaubt -> Funktion beenden
      if not(pc^ in allowed) then Exit;
      if pc^ = '/then begin
        if i = l then Exit;
        evaln := True;
        Inc(pc);
        Inc(i);
        Break;
      end;
      z := z * 10 + (Ord(pc^) - 48);
      Inc(decpos);
      Inc(pc);
      Inc(i);
    end;
  end;

  allowed := ['0'..'9'];

  if evaln then begin
    decpos := 0;
    while i <= l do begin
      // Zeichen nicht erlaubt -> Funktion beenden
      if not(pc^ in allowed) then Exit;
      n := n * 10 + (Ord(pc^) - 48);
      Inc(decpos);
      Inc(pc);
      Inc(i);
    end;
  end;

  if evalz and evaln then
    Result := m * (g + (z / n))
  else
    Result := m * g;
end;
  Mit Zitat antworten Zitat