Posts mit dem Label Strings werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Strings werden angezeigt. Alle Posts anzeigen

Freitag, 7. Oktober 2011

Stringinvertierung - andersherum / inverting strings - the other way around

Beim durchstöbern meiner Codeschnipsel stolperte ich eben über eine andere Sichtweise der Stringinvertierung. Bei dieser geht es um einen einfachen Positionstausch innerhalb eines übergebenen Strings.

Mit anderen Worten: aus
 MeineInvertierteZeichenkette
wird
etteknehcieZetreitrevnIenieM
Das folgende Codemuster zeigt drei mögliche Wege auf, dies zu erreichen...

* // Funktionstest 
CLEAR 
liS=SECONDS()
?RevertString1( [etteknehcieZetreitrevnIenieM] )
?SECONDS() - liS

liS=SECONDS()
?RevertString2( [etteknehcieZetreitrevnIenieM] )
?SECONDS() - liS

liS=SECONDS()
?RevertString3( [etteknehcieZetreitrevnIenieM] )
?SECONDS() - liS

* Invertieren mit VFP Bordmitteln                        
FUNCTION RevertString1
LPARAMETERS vString AS String
    LOCAL liZaehler AS Integer, lcReturn AS String
    liZaehler    = 0
    lcReturn    = []
    FOR liZaehler = LEN ( vString ) TO 1 STEP -1
        lcReturn = lcReturn + SUBSTR ( vString , liZaehler , 1 )
    ENDFOR
    RETURN lcReturn
ENDFUNC

* Invertieren über die MS C++ Laufzeitbibliothek        
FUNCTION RevertString2
LPARAMETERS vString as String
    DECLARE STRING _strrev IN msvcrt20.dll STRING @
    m.vString = m.vString + CHR( 0 )
    RETURN _strrev( @m.vString )
ENDFUNC 

* Invertieren mit Bordmitteln und optimierter Schleife    
FUNCTION RevertString3
LPARAMETERS vString AS String
    LOCAL lcReturn as String
    lcReturn = SPACE( LEN( vString ) )
    FOR liZaehler = 1 TO LEN( vString ) / 2
        lcReturn = STUFF( lcReturn , liZaehler , 1 , SUBSTR( vString , LEN( vString ) + 1 - liZaehler , 1) )
        lcReturn = STUFF( lcReturn , LEN( vString ) + 1 - liZaehler , 1 , SUBSTR( vString , liZaehler , 1) )
    ENDFOR 
    RETURN lcReturn
ENDFUNC 

Bei kleinen Strings ist der zeitliche Unterschied marginal. Bei größeren Textmengen sieht es aber ganz anders aus und die Schere zu Variante 1 geht immer weiter auseinander.

Mittwoch, 5. Oktober 2011

Stringinvertierung - segmentiert und komplett / inverting strings - segmented and complete

Im Microsofts deutschem Foxpro Forum kam vor einigen Wochen die Frage wie ein String von A nach Z, B nach Y, C nach X usw. invertiert werden kann.

Im folgenden Codebeispiel steht wahlweise eine segmentierte Invertierung (nur für Buchstaben und Zahlen) sowie eine komplette Invertierung (sämtlich Zeichen der ASCII Tabelle = 0-255) zur Verfügung.

Vor der eigentlichen Funktion findet sich wie immer ein Funktionstest. Also einfach den Code markieren und über die Zwischenablage in ein PRG kopieren... ;-)


* // Stringinhalt unterscheidet sich von der Anzeige    
* // da nicht darstellbare Zeichen enthalten sein können
* // string content may differ from displayed value due 
* // to non-displayable chars                            

* // test - start --------------------------------
CLEAR 
lcTest = [Aa Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk Ll Mm Nn Oo Pp Qq Rr Ss Tt Uu Vv Ww Xx Yy Zz]
* // Original
?lcTest
* // segmentiert / segemented
?InvertString( lcTest )
* // komplett / complete
?InvertString( lcTest , 1 )
?
lcTest = [0 1 2 3 4 5 6 7 8 9]
* // Original
?lcTest
* // segmentiert / segemented
?InvertString( lcTest )
* // komplett / complete
?InvertString( lcTest , 1 )
* // test - ende ---------------------------------



FUNCTION InvertString as String
LPARAMETERS vString as String, vVersion as Integer
    * // Param #1:    string to invert            
    * // Param #2:    0|1 (optional)                
    * //            0 or ommit = sequenced ascii
    * //             1 = complete ascii range    
    LOCAL i as Integer, liAsc as Integer, lcReplace as String    
    vVersion = EVL( vVersion , 0 )
    FOR i = 1 TO LEN( vString )
        liAsc = ASC( SUBSTR( vString , i , 1 ) )
        DO CASE 
        * // complete ASCII    
        CASE vVersion = 1
            lcReplace = CHR( BITNOT( liAsc ) + 256 )
        * // A - Z            
        CASE BETWEEN( liAsc , 65 ,  90 )
            lcReplace = CHR( ABS( 25 - ( liAsc - 65 ) ) + 65 )
        * // a - z            
        CASE BETWEEN( liAsc , 97 , 122 )
            lcReplace = CHR( ABS( 25 - ( liAsc - 97 ) ) + 97 )
        * // 0 - 9            
        CASE BETWEEN( liAsc , 48 , 57 )
            lcReplace = CHR( ABS(  9 - ( liAsc - 48 ) ) + 48 )
        * // anything else    
        OTHERWISE 
            lcReplace = SUBSTR( vString , i , 1 )
        ENDCASE 
        vString = STUFF( vString , i , 1 , lcReplace )
    ENDFOR
    RETURN vString
ENDFUNC