Zeichenfolge (C-String) auf Mod 8/16 verlängern



  • Guten Tag !

    Bin auf der Suche nach einer sehr schnellen Methode Zeichenfolgen zu verlängern. Das heißt für einen Verschlüsselungs-Algorithmus muss die Länge des Klartextes durch 8 bzw. 16 teilbar sein.

    Folgendes theoretisches Konzept habe ich mir dazu überlegt:
    1.) nächste durch 8/16 teilbare Zahl finden
    2.) Puffer-Variable mit der "neuen Länge" anlegen
    3.) alte Zeichenfolge in neue übertragen und mit 0 auffüllen

    Das Problem ist jetzt die praktische Umsetzung. Könnte mir jemand dabei wohl unter die Arme greifen ???

    P.S.: Wüsste jemand eine andere/bessere Methode ???
    Grüsse Michael 🙂



  • Hm, die Länge des Strings mit length bzw. getLength erfragen,
    dann die 'Neue' Länge berechnen. Abstand zwischen denen ausrechnen,
    ein char* array dieser Größe allokieren, und einem String zuweisen.
    (Oder in einer Schleife jeweils ein char an den String anhängen ;))
    neuerstring = textstring + 'array'string;

    Devil



  • Mein Code sieht jetzt wie folgt aus:

    Eigene Kopier-Funktion für unsigned char Strings

    inline void stringcopy (unsigned const char *sSource, unsigned char *sDest){
    
    	for ( ; *sSource != '\0'; ++sSource, ++sDest) {
    		*sDest = *sSource;
    	}
    
    	*sDest = '\0';
    }
    

    Diese Funktion gibt die nächste Mod 8/16 Zahl zurück

    inline WORD32 getmodbase(WORD32 lNumOfBytes, int base) {
    
    	//Überprüfen ob String nicht durch 8 teilbar ist
    	if (lNumOfBytes % base != 0) {
    
    		while (lNumOfBytes % base != 0) {
    
    			lNumOfBytes++;
    
    		} // while
    
    	} // if
    
    	return lNumOfBytes;
    }
    

    Die Funktion erledigt das Auffüllen

    inline void pushstring (const unsigned char *sSrc, unsigned char *sDest, WORD32 lNullBytes) {
    
    	// String kopieren
    	stringcopy(sSrc, sDest);
    
    	// Überprüfen ob nur mit einem Zeichen aufgefüllt werden muss
    	if (lNullBytes == 1) {
    
    		strcat((char *)sDest, "1");
    
    	} // if
    
    	else if (lNullBytes > 1 ){
    
    		WORD32 len = lNullBytes; //- 1;
    
    		strcat((char *) sDest, "1");
    
    		for (int i = 1; i < lNullBytes; i++) {
    			strcat((char *) sDest, "0");
    		}
    
    	} // else if
    }
    

    Test der Routinen

    #include <string.h>
    
    #include <iostream>
    using namespace std;
    
    typedef unsigned __int32 WORD32;
    
    // ***** P R O T O T Y P E S ***** //
    inline WORD32 getmodbase(WORD32 lNumOfBytes, int base=8); // gibt die nächste durch BASE (8/16) teilbare Zahl zurück
    inline void stringcopy (const unsigned char *sSource, unsigned char *sDest); // kopiert einen String (Pointer - Version)
    inline void pushstring (const unsigned char *sSrc, unsigned char *sDest, WORD32 lNullBytes); // füllt einen String mit NULLEN auf
    
    int main(void) {
    
    	unsigned char sData[] = "Hallo Welt !";
    
    	int i = getmodbase(strlen((char *) sData));
    	int len = strlen((char *) sData);
    
    	unsigned char *snew = new unsigned char[i+1];
    
    	pushstring(sData, snew, i - len);
    
    	cout << "Verlaengerung nach: " << i << endl
    		 << "Original: " << sData << endl
    		 << "Kopie:    " << snew << endl;
    
    	return 0;
    }
    

    Kann man diesen Code noch optimieren damit diese Routinen so schnell wie möglich ablaufen, denn eine Verschlüsselung nimmt ja auch Zeit in Ansrpuch.

    Gruß Michael



  • Jep, einen Verbesserungsvorschlag hab ich da schon

    inline WORD32 getmodbase(WORD32 lNumOfBytes, int base) 
    {   
    
       if(!(lNumOfBytes%base)) return lNumOfBytes;
    
       return lNumOfBytes + (base - (lNumOfBytes % base));
    
    }
    

    und

    inline void pushstring (const unsigned char *sSrc, unsigned char *sDest, WORD32 lNullBytes) { 
    
         int len = strlen((char*)sSrc);
        //String Kopieren 
    
        memcpy((char*)sDest,(char*)sSrc,len);
    
       //ans Ende was anhängen 
       if (lNullBytes){ 
    
           sDest = (unsigned char*)(sSrc + len);
           *(sDest++)='1'; 
           memset((char*)sDest, '0' ,lNullBytes-1);
           *(sDest+lNullBytes+1)='\0'; 
        }
    

    nebenbei bemerkt ist das hier alles Ansi-C und hat mit C++ nix am Hut (Außer Deine Ausgabe)

    Und Du sollten in Deinen Funktionen zuerst das Ziel, und dann die Quelle in der Parameterliste angeben. Da das sonst alle machen, ist das weniger Verwirrend. 🙂

    und, warum nimmst Du "unsigned char*", wenn Du doch jedesmal nach "char*" casten must?

    grüße Con@n



  • in C++ Würde ich das so machen

    inline void StringFill( std::string &String, int base=8)
    {
          int len = String.length();
          static std::string temp;
          temp="";
    
          if (len=( len % base))
               {
                   len = base - len ;
                   temp.insert( temp.begin() , len , '0' );
                    temp[0] = '1';
    
                   String+=temp;
               }
    }
    

    das füllt Dir einen String auf die Basis, die Du angibts auf.

    grüße Con@n



  • Michael__W. schrieb:

    inline void stringcopy (unsigned const char *sSource, unsigned char *sDest){
    	
    	for ( ; *sSource != '\0'; ++sSource, ++sDest) {
    		*sDest = *sSource;
    	}
    
    	*sDest = '\0';
    }
    

    Wahrscheinlich bringt dir folgendes zwar keine Geschwindigkeitsvorteile, aber mich beeindruckt trotzdem die Ausdruckskraft:

    inline void stringcopy(const char* sSource, char* sDest)
    {
        while(*sDest++=*sSource++) ;
    }
    

    Quelle: "Die C++ Programmiersprache" von Bjarne Stroustroup



  • @Con@n

    Jep, einen Verbesserungsvorschlag hab ich da schon

    Gut, das leuchtet ein und ist auch schneller.

    Zu der veränderten PUSHSTRING Funktion habe ich zwei Verständnis-Fragen.
    Mit memcpy verschiebt man Speicherblöcke ??? <- ist somit schneller als strcpy

    Mit memset wird der String anhand von lNullBytes aufgefüllt. Wenn lNullBytes jetzt nur 1 wird aber nur eine 1 angehängt, richtig ?

    in C++ Würde ich das so machen

    Die Pointer Version ist aber schneller, richtig ?

    mit in C++ Würde ich das so machen meinst du eine OOP Lösung durch die Klasse String, richtig ?

    Herzlichen Dank für eure Hilfe ! 🙂

    Grüsse Michael



  • Michael__W. schrieb:

    Zu der veränderten PUSHSTRING Funktion habe ich zwei Verständnis-Fragen.
    Mit memcpy verschiebt man Speicherblöcke ??? <- ist somit schneller als strcpy

    Ja, memcpy ist etwas schneller als strcpy, aber nicht wirklich entscheident

    Michael__W. schrieb:

    Mit memset wird der String anhand von lNullBytes aufgefüllt. Wenn lNullBytes jetzt nur 1 wird aber nur eine 1 angehängt, richtig ?

    auch richtig, es wird die erste Stelle mit '1' überschrieben, und dann der Rest mit '0'. wenn es keinen Rest gibt, dann passiert nix.

    Michael__W. schrieb:

    Die Pointer Version ist aber schneller, richtig ?

    ähmm, nein. In meinen Test hat die C++ Variante besser abgeschnitten. Vor allem, wenn die Zeichenketten länger als "Hello World !" sind.

    Michael__W. schrieb:

    mit in C++ Würde ich das so machen meinst du eine OOP Lösung durch die Klasse String, richtig ?

    das ist das Beispiel, das ich aufgezeigt habe.

    grüße Con@n


Anmelden zum Antworten