Thema: Pseudo-Taschenrechner --> String-Test auf Zahlen und Pluszeichen

Blauäugig wie ich bin dachte ich: Machste mal RegEx. Halbe Stunden lesen und dann los.
Fazit: Mindestens einen halben Tag gelesen und probiert und dann aufgegeben sad

Problem:
1) 1+2+5+11  --> gültig
2) 1  --> gültig
3) 1 +  5  --> gültig
4) 1+  --> ungültig
5) 1+q  --> ungültig
6) 1+12  --> ungültig (optional)
7) 1+1 --> ungültig (optional)

Deshalb Pseudo-Taschenrechner. Ist es aber nicht. Das "Plus" dient nur als Verbinder, es könnte auch ein Komma oder sonstwas sein.
Bereich der Zahlen sollte optional fest eingegrenzt sein. Sagen wir mal von 1 bis 11. Ebenfalls optional ist, daß jede Zahl nur einmal vorkommt.

Fall 1) bis 3)
- nur Zahlen, Leerzeichen und "Plus" da sind
- auf jede Zahl genau ein "Plus" folgt
- am Ende und am Anfang eine Zahl steht
Fall 4)
- am Ende fehlt die Zahl
Fall 5)
- Buchstabe enthalten
Fall 6) - optional
- Zahl außerhalb des Bereiches
Fall 7) - optional
- Zahl kommt doppelt vor

Nun habe ich was von Automaten gelesen und denke mir, daß es so "ein bissel" wie programmieren ist.
- am Anfang muß eine Zahl stehen
- es dürfen nur Zahlen da sein
- auf jede Zahl muß genau ein Plus folgen
- das Plus darf in beliebig viele Leerzeichen eingefaßt sein (und zwar nur in Leerzeichen)
- es darf kein Buchstabe vorkommen
- am Ende muß eine Zahl stehen

Hm. Hat auch nicht weitergeholfen.
Wenn ich das nämlich versuche umzusetzen entsteht folgendes:
(^\d*)(\s*)(\+)(\s*)(\d*$)(![a-z])
Ist aber glaub ich vollkommener Mist! Und das mit den "(" Klammern hab ich auch nicht so richtig verstanden - gesundes Halbwissen wink

Ist meine prinzipielle Herangehensweise falsch? Falls nein, wie gehts dann konkret. Falls ja, wie sollte ich es mir vorstellen?

Kann mir einer helfen?

Danke und viele Grüße.

Re: Pseudo-Taschenrechner --> String-Test auf Zahlen und Pluszeichen

Hallo, alter Freund

ich bin momentan ein wenig in Eile, deshalb in Kürze:

Klammern (also die runden) kann man ua. benutzen, um
sich Teilausdrücke zu merken. Braucht man das nicht,
setzt man hinter die öffnende Klammer ein ?:


Ja nachdem, welche Umgebung man hat, ist das regex-Maschinchen
verschieden gestrickt und erlaubt dieses oder jenes nicht und anderes
anders uswusfetcppp...

Wie gesagt, auf die Schnelle, javascript:


<html>
<head>
<title>regex</title>
<script>

var test = [ ' 1 +    0',
             '   1   + q',
             ' 1 +    ',
             '  + 2',
             '   a +11',
             ' y + x',
             '12   +  45  ',
             '11   +  10  ',
             '    + ',
             '  2 + 0 + 12  ',
             '  2 + 0 + 11  ',
             ' 4 + 0 + z ',
             '   17',
             '201b  ',
             '  007 + 3 + 0006 ',
             ' 00003 + 0815',
             ' 00 '
           ],

      rg = /^\s*\d+\s*(?:\+\s*\d+\s*)*$/,                        // alle Zahlen, naja,
                                                                 // du weißt schon...

      rg = /^\s*(?:\d|1[01])\s*(?:\+\s*(?:\d|1[01])\s*)*$/,      // nur Zahlen bis 11

      rg = /^\s*0*(?:\d|1[01])\s*(?:\+\s*0*(?:\d|1[01])\s*)*$/,  // nur Zahlen bis 11
                                                                 // 007 ist erlaubt

       x = ''


for (var i in test)
 x += test[i] + '   =>   ' + (rg.exec(test[i]) ? 'ok' : 'KO') + '\n'

alert(x)

</script>
</head>
<body>

</body>
</html>

gruß
matho

Bei Unklarheiten bitte fragen, Antwort kann ein, zwei Tage dauern.

Re: Pseudo-Taschenrechner --> String-Test auf Zahlen und Pluszeichen

Moin Moin alter Freund,

vielen Dank für die schnelle - und wie immer voll befriedigende - Antwort.
Habe das letzte Pattern einfach mal in mein Access reingehaun und siehe da - alles wie gewünscht. Incl. Bereichsgrenzentest.
Aber verstanden habe ich es nicht... Ärgert mich!
Ich werde mir mal in Ruhe das einfache zur Hand nehmen und damit rumspielen. Kann nicht sein, daß das nicht in meinen Schädel will wink

Vielen Dank und viele liebe Grüße
Thomas

P.S.
Ich bin seit ca. 4 Jahren in Deiner relativen Nähe (wenn ich mich so recht erinnere, man wird halt nicht jünger und die Mails sind mit einem Rechnerumzug alle mal flöten gegangen). In der Regel 4-Tage-Woche und dann ab nach Hause - 600km.

Re: Pseudo-Taschenrechner --> String-Test auf Zahlen und Pluszeichen

N'abend

ich weiß en detail nicht, wie sich regexes in Access verhalten, aber ich
glaube, ziemlich ähnlich zu denen in javascript.
D.h., es gibt dann doch einige Dinge, die zwar in perl, oder auch zB. python
relativ locker gehn, aber hier nicht.
So ist zB. das "sone Sache" mit der Formulierung beliebiger Ober - bzw. Untergrenzen
im pattern selbst, oder auch dem Aufspüren von Verdopplungen.

Ein grober Versuch einer Erklärung (genauer geht's momentan nicht, alldieweil
Ferien sind und das Haus voller Kinder):


<html>
<head>
<title>regex</title>
<script>

var    og =  '11',
       ug =  '-25',

     test = [" 10 +  +9 + 11 +  -9 + -8 ",
             " 10 +  +9 + 11 +   9 + -8 ",
             " 10 +  + 9 + 11 +   9 + -8 ",
             " 10 +  +9 + 11 +  19 + -8 ",
             " 10 +  +9 + 11 + -77 + -8 ",
             " -7 + -17",
             " -7 + - 17",
             " rumumbel ",
             " 00 "
            ],


       rg = /^\s*[-+]?\d\d*\s*(\+\s*[-+]?\d\d*\s*)*$/,
       rz = /[-+]?\d\d*/g,

       // es folgt das gleiche in grün, nochmal ausführlicher und diesmal unter
       // Verwendung des Konstruktors  =>  new RegExp( pattern [, option[s]] )

       rg  =  new RegExp( '^\\s*[-+]?\\d\\d*\\s*(\\+\\s*[-+]?\\d\\d*\\s*)*$' ),

       // das sieht ziemlich blöde aus, also nochmal in übersichtlich, aufgeteilt
       // in kleine appetitliche häppchen, die dann zusammenfügt werden:

        v  =  '[-+]?' ,    // vorzeichen ( entweder + oder minus ), mit dem
                           // ?-quantifier, also: ein- oder keinmal

        d  =  '\\d'   ,    // ziffer, digit, von 0 bis neun, kann auch
                           // als zeichenklasse geschrieben werden: [0-9],
                           // oder auch [0123456789]
                           // eigentlich: \d, aber weil in string: \\d

       db  =  '\\d*'  ,    // dasselbe mit *-quantifier, also: beliebig oft ( 0, 1, oder mehr)

        w  =  '\\s*'  ,    // beliebig viel whitespace

       tr  =  '\\+'   ,    // beliebiges trennzeichen, hier ein literales +
                           // ein escape wg. sonderzeichen und
                           // ein escape wg. escape des escapes in string
                           // das + ist ein regex sonderzeichen:
                           // der +-quantifier ( mindestens einmal, oder beliebig oft )

        z  =  v + d + db,  // beliebige zahl

       zw  =  w + z + w,   // dito, mit umgebenden beliebigem whitespace


       rg  =  new RegExp( '^'  +         // anker: zeilenanfang, hier stringanfang

                          zw   +

                          '('  +         // einfangende und gruppierende klammer öffnend

                          tr   +

                          zw   +

                          ')*' +         // einfangende und gruppierende klammer schließend
                                         // mit *-quantifier: beliebig oft

                          '$'            // anker: zeilenende, hier stringende
                        ),

       rz  = new RegExp( z, 'g' )        // g ist die option für's globale matching
                                         // d.h.: finde jedes vorkommen diese patterns im
                                         // gegebenen string


alert( rg + '\n\n' + rz )                // nur mal zum guggen, ob die konstruierten
                                         // regexes auch hinhaun

if ( !isNaN( og*1 ) && !isNaN( ug*1 ) )  // sind og und ug tatsächlich brauchbare zahlen
if ( og*1 >= ug*1 )                      // und ist og wirklich mindestens so groß wie ug
  for( var i in test )
     {  var x, y,
            a = [],
            s = 0,
            f = 0

        if( x = rg.exec( test[i] ) )       // stimmt die struktur insgesamt?
          {
            if( x[1] )                     // das ist der sinn der einfangenden klammer:
                                           // wenn sich nach der ersten zahl mindestens ein
                                           // vorkommen des musters \+\s*[-+]?\d\d*\s* findet
              {
                while( y = rz.exec( test[i] ) ) a.push( y*1 )  // schaufle alle  [-+]?\d\d*  als
                                                               // numerische werte ins array a

                for ( var j = 0; j < a.sort().length; j++ )    // array a wird aufsteigend
                                                               // sortiert und auf doppelte
                                                               // nachbarn abgeklopft bzw. og und ug
                  if( a[j] == a[j+1] )
                    { alert('test[' + i + '] ' + a[j] + ' ist doppelt\n\n:' + test[i]);
                      s = 0;
                      f = 1;
                      break;
                    }
                  else if( a[j] > og*1 )
                    { alert('test[' + i + '] ' + a[j] + ' ist zu groß\n\n:' + test[i]);
                      s = 0;
                      f = 1;
                      break;
                    }
                  else if( a[j] < ug*1 )
                    { alert('test[' + i + '] ' + a[j] + ' ist zu klein\n\n:' + test[i]);
                      s = 0;
                      f = 1;
                      break;
                    }
                  else  s += a[j]
               }

             else  s = x[0]*1

             if( !f ) alert( 'test[' + i + '] ' +  '  summe => ' + s)
          }

        else  alert( 'test[' + i + "]  nüscht wg:\n\n" + test[i] )
     }
else  alert( og + ' kleiner ' + ug)
else  alert( ' tja, zahlen sind halt ein eher abstraktes konzept ')

</script>
</head>
<body>

</body>
</html>

gruß

matho