Announcement

Collapse
No announcement yet.

IsNumeric auch für Exponentialdarstellung

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • IsNumeric auch für Exponentialdarstellung

    Das ist jetzt weniger eine Anfrage nach Eigenschaften von C++, sondern eher die Suche nach einer zündenden Idee.

    Da ich in meinem Framework einen Satz von Funktionen habe, die mir "sicher" einen Text in eine Zahl umwandeln, indem sie atoi/atof kapseln und im Fehlerfall 0 zurückgeben, müsste ich den String nun in den Fällen, in denen 0 ein korrekter Rückgabewert sein könnte vorher überprüfen. Hierzu habe ich folgende Funktion geschrieben:

    mal sehen, ob ich abspeichern kann, ohne dass der Code drin steht, und nachher wieder erstezen

    Nun möchte ich dies erweitern, dass es auch Zahlenrepräsentationen der Form -1.23e-45 erkennt, in der Exponentialdarstellung sind aber weitere Kriterien drin, die ich nur über komplizierte Fallunterscheidungen auflösen könnte :
    • nur ein E oder e, aber nicht direkt nach dem Dezimalpunkt
    • wenn ein e drin ist, muss ein Punkt vorhanden sein, der muss aber nach dem (möglicherweise aber auch weggelassenen) Vorzeichen oder nach maximal einer Ziffer kommen
    • nach dem e dürfen nur maximal 2 Ziffern kommen
    • falls bis zu 2 Minusszeichen drin sind, dürfen diese nur an Position 0 und hinter dem e auftauchen


    Gibt es da eine einfache Möglichkeit, dies zu testen, ohne die Anzahl der Nachkommastellen irgendwie einzuschränken (ein Umwandeln in eine double mit nachfolgendem sprintf und Textvergleich geht also nicht), oder bin ich wirklich darauf angewiesen, jedes Kriterium explizit zu testen? Gut, ich könnte ein atof in einen try-catch-Block kapseln, und dann false zurückgeben, wenn ich im catch gelandet bin, aber eine Überprüfung über das Auslösen einer Exception will ich eigentlich vermeiden, man weiß nie wie der Debugger damit umgeht...
    Zuletzt editiert von M.Dietz; 15.10.2012, 10:45.

  • #2
    Eine RegEx könnte das prüfen......
    Christian

    Comment


    • #3
      Also hier nochmal der Code (Irgendwie hat Euer System Probleme damit, Code zu posten, ich bekomm jedesmal ein "Connection reset by peer", wenn ich es versuche und zwar inzwischen nicht mehr nur bei Neuen Posts sondern auch beim Ändern, bei Beiträgen ohne Code klappt es):
      [highlight=cpp]
      bool Framework::IsNumeric(std::string numstr)
      {
      bool rettest=false;
      if (numstr.compare("") == 0) return false; // don't even start investigating on an empty string
      std::string allowed= "-0123456789.";

      rettest= (numstr.find_first_not_of(allowed) == string::npos); // check to find any char not allowed in numerics
      if(rettest)
      {
      // if there are at least two dots, these differ else both are the same position or both are npos
      // if there is a dot, it must not be on the last position
      rettest = (numstr.find(".") == numstr.rfind(".") && numstr.find(".") != numstr.length()-1);
      if (rettest)
      {
      //if there is a dash in the string it's only allowed on position 0
      size_t posDash=numstr.find("-");
      rettest = (posDash == std::string::npos || posDash==0);
      }
      }
      return rettest;
      }
      [/highlight]

      Comment


      • #4
        http://www.regular-expressions.info/floatingpoint.html
        Christian

        Comment


        • #5
          Danke Christian, aber die dort abgelegte floating-point regex hat einen unschönen Fehler: Sie match auch Strings wie 123E45, was ja nicht erlaubt ist (Exponentialdarstellung erfordert ja eine Dezimalpunktdarstellung mit maximal 1 Stelle vor dem Dezimalpunkt) es müsste dann als 1.23e47 angegeben werden). Hat mich ein bisschen Mühe gekostet, das auszugleichen, im Endeffekt ist eine nicht ganz so schöne, aber immerhin erfolgreichere Expression herausgekommen (in der Zeit hätte ich vielleicht auch den entsprechenden Parser geschrieben, den ich in meinem ersten Beitrag erwähnt hatte, aber was solls.

          Für's Archiv, hier noch die regular expression:
          Code:
          ^(([+-]?[0-9]?\.[0-9]+[eE][+-]?[0-9]{2})|([+-]?(0?\.|[1-9][0-9]*\.|[1-9])[0-9]+)|[+-]?[1-9]|0)$
          bzw, wenn man führende + (außer im Exponenten)verbieten will
          Code:
          ^((-?[0-9]?\.[0-9]+[eE][+-]?[0-9]{2})|(-?(0?\.|[1-9][0-9]*\.|[1-9])[0-9]+)|-?[1-9]|0)$
          Der verweigert jetzt auch führende Nullen.
          Zuletzt editiert von M.Dietz; 17.10.2012, 13:17.

          Comment

          Working...
          X