Announcement

Collapse
No announcement yet.

Brauche Hilfe mit regexec

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

  • Brauche Hilfe mit regexec

    Hi,

    Nachdem ich mit viel Mühe einen regulären Ausdruck zusammengezimmert habe (bin dahingehend Anfänger, war also schon eine Leistung für die ich mir selbst auf die Schulter klopfen kann), macht mir jetzt die GNU-Funktion zum Auswerten derselben Probleme.

    Anhand der Dokumentation, die ich ergoogelt habe habe ich folgenden Programmcode zum Testen erstellt:

    [highlight=cpp]
    #include <iostream>
    #include <cstdlib>
    #include <regex.h>

    using namespace std;

    bool IsNumeric(std::string numstr)
    {
    bool rettest = false;
    int regreturn=0;
    const char* regexstr="^((-?\\d?\\.\\d+[eE][+-]?\\d{2})|(-?\\d*\\.?\\d+))$";
    regex_t parsreg;
    if(regcomp(&parsreg, regexstr, REG_NOSUB) != 0)
    {
    cerr << "Could not create regular expression, aborting with 'not matching'";
    }
    else
    {
    regreturn = regexec(&parsreg, numstr.c_str(), 0, NULL,0);
    if (regreturn == REG_ESPACE) cerr << "regular expression ran out of memory, aborting with 'not matching'";
    if(regreturn == 0) rettest=true;
    }
    regfree(&parsreg);
    return rettest;
    }

    int main(int argc, char *argv[])
    {
    cout << "leer:" << IsNumeric("") << "\n";
    cout << "1:" << IsNumeric("1") << "\n";
    cout << "1.3324e-12:"<< IsNumeric("1.3324e-12")<<"\n";
    cout << "125e23:" << IsNumeric("125e23") << "\n";
    cout << "13.445:" << IsNumeric("13.445") << "\n";
    cout << "16468123:" << IsNumeric("16468123") << "\n";
    cout << "-1324.57:" << IsNumeric("-1324.57") << "\n";
    cout << "-1.225e21:" << IsNumeric("-1.225e21") << "\n";

    return EXIT_SUCCESS;
    }
    [/highlight]

    Egal was ich der Funktion übergebe, ich bekomme in regreturn immer eine 1 zurück (No match) ich vermute, dass irgendwo in den Flags ein Fehler hängt, die Beschreibung dazu habe ich nämlich irgendwie nicht so ganz kapiert, denke aber das doch irgendwie richtig ausgewählt zu haben

  • #2
    Gegen welche Eingabe soll das matchen?
    Christian

    Comment


    • #3
      Matchen soll es gegen "gültige" Zahlendarstellung, d.h. Ganzzahlen mit optionalem Minus als Vorzeichen (kein Plus), Gleitkommazahlen genauso aber mit Dezimalpunkt an beliebiger Stelle (außer der letzten und vor dem optionalen Minus) und Exponentialdarstellungen mit optionalem Minus, höchstens einer Vorkommastelle und exakt 2 Stellen für den Exponenten.

      Zum Testen habe ich einige die gehen sollen und einige die nicht gehen sollen in der main-Funktion aufgeführt (sollten alle gehen, bis auf "" und "125e23"), ich kriege aber bei jeder der "Zahlen" von regexec eine 1 zurück, also IsNumeric als false.

      Comment


      • #4
        Da du nur true/false zurückgibst, sollte du dir mal den tatsächlichen Rückgabewert von regreturn anschauen.
        Return Value
        If a match is found, the regexec() function returns 0. If no match is found, the regexec() function returns REG_NOMATCH. Otherwise, it returns a nonzero value indicating an error. A nonzero return value can be used in a call to the regerror() function.
        Christian

        Comment


        • #5
          Hab ich untersucht (im Debugger) und regexec gibt in regreturn (wie schon im OP geschrieben) immer eine 1 zurück, d.h. beim Ausführen an sich passiert also kein Fehler, regex sagt einfach nur "no match", weil für ihn der String und der reguläre Ausdruck nicht zusammenpassen. Ich habe inzwischen den Verdacht, dass ich meiner regex_t-Struktur parsreg irgendwie mitteilen muss, wie das Dach und der Dollar zu interpretieren sind, die Flags die in der Manpage (http://www.manpagez.com/man/3/regexec/) beschrieben werden, deuten aber genau das Gegenteil an, also dass ich die Flags REG_NOTBOL und REG_NOTEOL weglassen muss, wenn der gesamte String als eine Zeile angesehen werden soll, mein Interpretationswunsch durch die Default-Einstellungen also bereits erfüllt ist. (Mal davon abgesehen: wenn ich die angebe kriege ich trotzdem eine 1.)

          Der reguläre Ausdruck an sich ist in Ordnung, wenn ich sie bei verschiedenen regex-Testern online ausprobiere (nachdem ich die Doppel-Backslashes zu einfachen umgewandelt habe), allerdings kann ich da ja auch nicht sagen, wie der Text an die regex herangetragen wird, oder wie die ihren Testern den Matchstring verabreichen, oder ob das bei php bzw. Java überhaupt vergleichbar mit dem Vorgehen unter GNU C++ ist.

          Comment


          • #6
            Ich habe den Ausdruck ebenfalls online und mittels Java getestet. Dieser müsste korrekt sein. M.E. müssten die EG_NOTBOL und REG_NOTEOL weggelassen werden. Teste das doch mal ohne die Begrenzung Anfang/Ende. Dann müsste der Ausdruck ja matchen, wenns daran liegt
            Christian

            Comment


            • #7
              Ich habe so langsam den Verdacht, dass das regex, das da bei unserem C++-Paket dabei ist, ein eigene Notation benötigt. Ich habe nämlich mal den Test gemacht und "1234567" mit "[0-9]+" zu matchen versucht: fehlgeschlagen, aber mit "[0-9]" hat regexec einen Match. Ich hab's aber dann mal versucht mit dem REG_EXTENDED Flag im regcomp, da hat er dann alle meine Strings bis auf den Leerstring wenigstens mit dem Pattern "[0-9]+" gematcht (weil ja mindestens eine Ziffer vorkommt). Soweit ich das verstanden habe, gehören die Quantifier (+,*,?,{n}) aber doch zur basic regex, oder? Ich werd noch ein bisschen probieren, wenn \d nicht als digit sondern als d versucht wird zu matchen, müsste ich dem ja eigentlich mit [0-9] Herr werden.

              Update: mit "[0-9]" statt \d kann regex das anscheinend interpretieren, ich lasse das jetzt in der Schreibweise, da will ich jetzt nicht mehr nachspüren, warum es mit \d nicht klappt, oder warum ich REG_EXTENDED nehmen muss, um das + zu nutzen. Dafür ist mir aufgefallen, dass auch in meinen Ausdruck noch ein Fehler ist: er lässt führende Nullen zu, dies aber auszumerzen (also 0x.xxx zu verbieten und trotzdem ein "0.xxx" oder sogar .xxx zuzulassen) führt zu so viel Alternativen in dem Ausdruck, dass ich den Parser auch direkt schreiben kann.

              Danke erstmal, ich kann ja interessehalber noch mal reinsehen, ansonsten habe ich erst mal etwas, das läuft.
              Zuletzt editiert von M.Dietz; 17.10.2012, 10:06.

              Comment


              • #8
                Geht es dir wirklich um den regulären Ausdruck der möchtest du nur wissen ob der Eingabetext als Zahl interpretiert werden kann?

                In diesem Fall würde ich einfach versuchen den Eingabetext via CAST oder ähnliches in eine Zahl umzuwandeln. Wenn dabei ein Fehler auftritt gibst du in der Funktion FALSE zurück, andernfalls kannst du, wenn nötig noch weitere Eigenschaften prüfen und dann TRUE zurück geben.

                \d ist nur eine Abkürzung für [0-9] und wird nicht von allen Sprachen unterstützt.

                Gruss
                Zuletzt editiert von Wernfried; 17.10.2012, 13:44.

                Comment


                • #9
                  Mal davon dass es schlechter Programmierstil ist, eine Prüfung darüber auszuführen, ob eine bestimmte Funktion eine Exception auslöst, soll das ganze in einem Echtzeitbetriebssystem laufen, und da will ich nicht durch "vorsätzliches" Auslösen von Ausnahmebehandlungen den ganzen Betrieb lahmlegen. So sicher bin ich dann doch nicht, dass ich nicht irgendwelche anderen notwendigen Prozesse behindere, nur weil ich kurz vor Ende meiner Zeitscheibe noch schnell mal einen Fehler verursache...

                  Comment


                  • #10
                    Stimmt, es ist schlechter Programmierstil, wenn ein reguläres Ereignis einen Fehler auslöst aber manchmal(!) muss man halt pragmatisch sein. Die Ausnahme bleibt natürlich nur in deiner Funktion, was soll da lahmgelegt werden?

                    Du kannst auch die Funktion TryCast verwenden, die macht genau das gleiche und erzeugt niemals einen Fehler.

                    Gruss

                    Comment

                    Working...
                    X