Rot13 Template?
-
#define ROT13_1(str,x) str[pos<sizeof str?pos:sizeof str-1] #define ROT13_2(str,x) ROT13_1(str,x), ROT13_1(str,x+1) #define ROT13_4(str,x) ROT13_2(str,x), ROT13_2(str,x+2) #define ROT13_8(str,x) ROT13_4(str,x), ROT13_4(str,x+4) #define ROT13_16(str,x) ROT13_8(str,x), ROT13_8(str,x+8) #define ROT13_32(str,x) ROT13_16(str,x), ROT13_16(str,x+16) #define ROT13_64(str,x) ROT13_32(str,x), ROT13_32(str,x+32) #define ROT13(str) rot13<ROT13_64(str, 0)>::value;Den String auf die richtige Läge zurückzukürzen, ist eine kleine Übungsaufgabe.
Mit boost-PP wird es noch etwas einfacher.
-
Nachdem ich nun ein halbes Dutzend Bugs in meinem Code behoben durfte (dadurch rechtfertigt sich Kellerautomats Aussage natürlich
), funktioniert das:#include <iostream> template<char c> char constexpr rot13C() { return (c + 13 > (c >= 'A' && c <= 'Z' ? 'Z' : 'z'))? c - 13 : c + 13; } template<> char constexpr rot13C<'\0'>() { return '\0'; } template<char...c> struct rot13 { static char constexpr value[] = { rot13C<c>()..., '\0' }; }; template<char...c> char constexpr rot13<c...>::value[]; #define ROT13_1(str,pos) str [ pos < sizeof str ? pos : sizeof str - 1 ] #define ROT13_2(str,x) ROT13_1(str,x), ROT13_1(str,x + 1) #define ROT13_4(str,x) ROT13_2(str,x), ROT13_2(str,x + 2) #define ROT13_8(str,x) ROT13_4(str,x), ROT13_4(str,x + 4) #define ROT13_16(str,x) ROT13_8(str,x), ROT13_8(str,x + 8) #define ROT13_32(str,x) ROT13_16(str,x), ROT13_16(str,x + 16) #define ROT13_64(str,x) ROT13_32(str,x), ROT13_32(str,x + 32) #define ROT13(str) rot13< ROT13_64( (str), 0) >::value //Hier müssen btw besser Klammern um str int main() { std::cout << ROT13("Bla") << '\n'; //Die ROT13-Version des Textes std::cout << ROT13( ROT13("Bla") ) << '\n'; // Verschlüsselt und zurück }Funktioniert mit meinem GCC 4.8, auf Ideone gibt es einen Haufen Fehlermeldungen. Was solls.
-
Sone schrieb:
std::cout << ROT13( ROT13("Bla") ) << '\n'; // Verschlüsselt und zurückUnd in diesem Augenblick steht "Bla" wieder in der Executable.
-
SeppJ schrieb:
Sone schrieb:
std::cout << ROT13( ROT13("Bla") ) << '\n'; // Verschlüsselt und zurückUnd in diesem Augenblick steht "Bla" wieder in der Executable.
War nur ein Beispiel!

Am Ende sieht AFAIK die main-Funktion (vereinfacht) ja so aus:
int main() { std::string str = ROT13("Bla"); std::cout << transform(str) << '\n';//Hier zur Laufzeit zurückverwandelt }
-
Die ständige Rücktransformation sollte man sich eigentlich sparen können:
std::string s = rot13(ROT13("Hallo Welt")); // rot13 normale FunktionDabei eventuell dafür sorgen, dass rot13 nicht rausoptimiert und dann wirklich erst zur Laufzeit einmalig ausgeführt wird. Könnte man eventuell auch gleich mit ins Makro packen.
-
Also am Besten so, dass ROT13 ein Objekt darstellt, mit einem Konvertierungsoperator für string.
-
camper schrieb:
Also am Besten so, dass ROT13 ein Objekt darstellt, mit einem Konvertierungsoperator für string.
So?
Edit: Verbessert.
#include <iostream> #include <string> #include <mutex> template<typename T> struct identity final {typedef T type;}; template<char c> bool constexpr isalpha() { return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z'; } #define ret_expr(func) ( func )? \ (c + 13 > ( c <= 'Z' ? 'Z' : 'z' ) )? c - 13 : c + 13 \ : \ c//... oder einfach den Buchstaben zurückgeben template<char c> char constexpr rot13C() //Template Version (zur Compilezeit) { return ret_expr(isalpha<c>()); } char rot13C(char const c) //Normale Funktion (Laufzeit) { return ret_expr(std::isalpha(c)); } std::string rot13str(std::string const& s) { std::string rval( s ); for(auto &c : rval) c = rot13C(c); return rval; } template<char...c> struct rot13 { static char constexpr value[] = { rot13C<c>()..., '\0' }; operator std::string() { return rot13str( value ); } operator typename identity<char const(&)[sizeof value]>::type () const //selbst gebastelt, sonst geht auch die boost::move_details Version { static char arr[sizeof value]{}; static std::once_flag f; std::call_once(f, memcpy, arr, rot13str(value).c_str(), sizeof(value)); return arr; } }; template<char...c> char constexpr rot13<c...>::value[]; #define ROT13_1(str,pos) str [ pos < sizeof str ? pos : sizeof str - 1 ] #define ROT13_2(str,x) ROT13_1(str,x), ROT13_1(str,x + 1) #define ROT13_4(str,x) ROT13_2(str,x), ROT13_2(str,x + 2) #define ROT13_8(str,x) ROT13_4(str,x), ROT13_4(str,x + 4) #define ROT13_16(str,x) ROT13_8(str,x), ROT13_8(str,x + 8) #define ROT13_32(str,x) ROT13_16(str,x), ROT13_16(str,x + 16) #define ROT13_64(str,x) ROT13_32(str,x), ROT13_32(str,x + 32) #define ROT13(str) rot13< ROT13_64( (str), 0) >() //Hier wird ein temporäres rvalue instanziiert int main() { char const* s = ROT13("Hallo w"); // rot13 normale Funktion std::cout << s << '\n'; }Klar, hier ist ROT13 selbst nicht ein Objekt, aber was ich meine dürfte klar sein.
Dazu kann man noch ROT5 mit reinpacken.
-
jetzt noch die überflüssigen '\0' Zeichen am Ende entfernen und eine Konvertierung nach const char(&)[N] statt const char* anbieten. Dann dürfte das sogar einigermaßen brauchbar sein.
-
Moinsen,
Warum nicht einfach alle Zeichenketten in einem pre build event mit einen separaten Programm verschlüsseln und nur die dekodier Funktion einbauen?
Grüße
-
camper schrieb:
jetzt noch die überflüssigen '\0' Zeichen am Ende entfernen und eine Konvertierung nach const char(&)[N] statt const char* anbieten. Dann dürfte das sogar einigermaßen brauchbar sein.
Mir fällt auf die Schnelle nur
operator typename identity<char const(&)[sizeof(value)]>::type () const //selbst gebastelt, sonst geht auch die boost::move_details Version { static char arr[sizeof value]{}; static std::once_flag f; std::call_once(f, memcpy, arr, value, sizeof(value)); return arr; }ein (
std::identitywurde btw afair aus dem Standard gebannt).
Die Template-Version (mit<size_t N>) scheint irgendwie nicht zu klappen.Man kann natürlich auch gleich das interne Array zurückgeben.
Was die überflüssigen Terminierungszeichen am Ende betrifft: Ich bin leider echt gar nicht vertraut mit Boost-Preprocessor (und will hier auch nur Standard einbeziehen), und wie es sonst gehen soll überlasse ich dem Meister.
Edit: Hab jetzt obigen Code editiert.
-
*push*
Camper, mach doch was! Also wie kann man das jetzt kuerzen? Mir faellt kein Spielchen mit dem PP ein.
EDit: Ich hab es mit dem ternaeren Operator im Makro versucht, ala#define ROT13_64(str,x) ROT13_32(str,x), (sizeof str > x + 32 + 16)? ROT13_32(str,x + 32) : ROT13_16(str, x + 32)Aber der Compiler meldet, dass nach dem aufloesen der Makros Operanden des Komma-Operators einfach ignoriert werden...