Deagle--Knight Geschrieben 16. März 2004 Teilen Geschrieben 16. März 2004 Hallo, ich versuche mich ein wenig in C++ weiterzubilden, da wir in der Berufsschule ja nicht ausm Knick kommen Folgendes. Ich möchte für unsere Community [RPG] ein Programm schreiben, welches die Texteingabe auf Knopfdruck umwandelt. Hierbei möchte ich die "Al-Bhed" Sprache aus Final Fantasy X benutzen. A - E ][ N - R B - P ][ O - Y C - S ][ P - B D - T ][ Q - W E - I ][ R - H F - W ][ S - M G - K ][ T - D H - N ][ U - O I - U ][ V - F J - V ][ W - X K - G ][ X - Q L - C ][ Y - A M - L ][ Z - G Ich habe dazu in Borland Builder C++ ein "Memo" Feld genommen und einen Button der das ebend umtauschen soll. Nur leider habe ich dazu nicht den wirklichen Durchblick wie ich das mache. Ich vermute nur mal über ASCII umtauschen ? zahlen und sonderzeichen müssen erhalten bleiben. Kennt jemand dazu einen halbwegs simplen Lösungsweg ? Danke im vorraus. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
need-some-blood Geschrieben 16. März 2004 Teilen Geschrieben 16. März 2004 du must die Zeichenketten in einzelne Buichstaben umwandeln und dann das Zeichen vertauschen. Schau mal hier. Der Quellcode der HTML-Seite ist recht überschaulich besonders die Funktionen atoe und etoa sind wichtig für dich. MVG need-some-blood Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Deagle--Knight Geschrieben 16. März 2004 Autor Teilen Geschrieben 16. März 2004 hmm ja, danke, die sache ist nur die, das es javascript ist. wie mache ich das nun in c++ ? kann mir das mal einer anhand des buchstaben A vorschreiben ? oder mich mal sanft draufstoßen ? Wie gesagt in der BS kommen wir echt nicht weiter seit 2 monaten hängen wir an Functionen / Zeiger und Pointern fest ... und OOP ist noch lange nicht in sicht :/ Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
FinalFantasy Geschrieben 16. März 2004 Teilen Geschrieben 16. März 2004 Du brauchst eine ASCII Tabelle. Die Alohanumerischen Zeichen (Gross und Kleinbuchstaben auch) liegen darin hintereinander. Somit kannst du abfragen: if( buchstabe > 60 && buchstabe < 128) (Unter der Annahme, dass die Ziechen zwischen ASCII-Code 60 und 128 liegen...) Somit werden nur Buchstaben und Zahlen verschoben, Sonderzeichen dagegen bleiben unbehandelt. Jetzt kannst du einzelne Zeichen vertauschen, indem du Eine Zahl dazu addierst. Angnommen A hat den ASCII-Wert 92, dann hat C logischerweise den ASCII-Wert 94. zeichen += 2; Macht also aus einem A ein C. Wenn alle Buchstaben gleichmässig verschoben werden, geht das so relativ einfach (Cäsarianische Verschlüsselung oder so ähnlich schimpft sich das auch) Falls jedem Zeichen zufällig ein anderes Zeichen zugeordnet ist, kommt du wohl um einen grossen Switch nicht herum: switch(ziechen) case 'A': zeichen = B; break; case 'B': zeichen = K; break; .... Durch die Zeichenkette loopen und einzelne Zeichen behandeln kannst du etwa so: for( int i = 0; i < strlen(string); i++) { switch (string[i]) { //für den Switchcase case 'A': string[i] = 'B'; } string[i] += 2; //für die andere Methode } [/PHP] Ich hoffe dass war einigermassen verständlich. Für weitere Fragen, kannst du mir ja mal eine PM schicken, falls es eilt... Edit: Achja, im Endeffekt benutzt du hier zwar Pointer (bei meinem Vorschlag) durch die [i] Zugriffe auf den String, das hat aber meiner Meinung/Empfinden nach noch nicht viel mit Pointerarithmetik zu tun. OOP ist für so ein kleines Programm eigentlich nur unnötiger Mehraufwand. Soll es denn ein Windowsprogramm oder eine Kommandozeilenprogramm werden? Mit Borland kenn ich mich nicht so wirklich aus, ich benutze das Visual Studio. Aber in diesem Forum geht es ja eigentlich nur um grundlegende Probleme in C/C++.... Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Deagle--Knight Geschrieben 16. März 2004 Autor Teilen Geschrieben 16. März 2004 jepp soll ein windows proggy werden. nur wie spreche ich die einzelnen zeichen im "memo feld" an ? das hackt irgendwie noch bei mir ... der rest scheint recht verständlich zu sein [php sei dank ] Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
nic_power Geschrieben 16. März 2004 Teilen Geschrieben 16. März 2004 Hallo, Original geschrieben von FinalFantasy Falls jedem Zeichen zufällig ein anderes Zeichen zugeordnet ist, kommt du wohl um einen grossen Switch nicht herum: switch(ziechen) case 'A': zeichen = B; break; case 'B': zeichen = K; break; .... Das geht auch ganz wunderbar ohne einen riesiges Switch-Statement! Pseudocode im Anhang. Verwende zwei Arrays und benutze den ASCII-Wert als Index in das Array. Das erste Array (array1) wird für die Konvertieren von A->E, B->P, C->S usw. verwendet: array1[A]=B; array1=P; array1[C]=S etc. Analog für die Rückrichtung array2=A; array2[P]=B; array2=C etc. Vorinitialisieren solltest Du mit array[A]=A, array=b etc; füllen läßt sich das Ganze mit einer Schleife (du musst die Zuweisungen also nicht einzeln vornehmen). string1="ABC"; string2="BPS"; for(i=0; i<strlen(string1); i++) { array1[string1]=string2; array2[string2]=string1; } Nic Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
FinalFantasy Geschrieben 16. März 2004 Teilen Geschrieben 16. März 2004 Genau das hab ich grad auch ausprogrammiert. *gg* Wenn du willst kann ich es dir ja mal schicken. Dann brauch ich deine E-Mail per PM. Ist aber in MFC/VisualStudio geschrieben. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Guybrush Threepwood Geschrieben 16. März 2004 Teilen Geschrieben 16. März 2004 Original geschrieben von Deagle][Knight jepp soll ein windows proggy werden. nur wie spreche ich die einzelnen zeichen im "memo feld" an ? Du sprichst die Zeichen nicht im Textfeld an, sondern du musst dir eine Variable anlegen und der dann das zuweisen was in deinem Textfeld steht. Dazu solltest du normalerweise die Funktion GetWindowText (oder so ähnlich) aufrufen können. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
FinalFantasy Geschrieben 16. März 2004 Teilen Geschrieben 16. März 2004 Wie funktioniert denn das bei Borland? Gibts da auch MFC, oder direkt über die WinAPI?? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Guybrush Threepwood Geschrieben 16. März 2004 Teilen Geschrieben 16. März 2004 Original geschrieben von FinalFantasy Wie funktioniert denn das bei Borland? Gibts da auch MFC, oder direkt über die WinAPI?? Das kommt drauf, also MFC (Microsoft Foundation Classes)wird es denke ich nicht geben, aber WinAPI ist eh viel schöner;) Es gibt aber, wenn ich mich recht erinnere, etwas ähnliches wie die MFc von Borland (OWL oder so). Außerdem gibt es ja noch den Borland Builder der im Prinzip wie Delphi funktioniert... Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Deagle--Knight Geschrieben 17. März 2004 Autor Teilen Geschrieben 17. März 2004 Uff ... also irgendwie blicke ich da nicht durch -.- mit diesem array und string ... was FinalFantasy ja benutzt hat und hier gepostet wird ... kann mir da mal einer ne genaue erklärung zu schreiben ? ... raff das irgendwie nicht und string1="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; string2="ypltavkrezgmshubxncdijfqow"; int i; for(i=0; i < strlen(sting1); i++) { array1[string1[i]]=string2[i]; array2[string2[i]]=string1[i]; } .... ist 100 % falsch, oder ? ... Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
FinalFantasy Geschrieben 18. März 2004 Teilen Geschrieben 18. März 2004 Also das war der Code meiner Methode: int CEncodeDlg::SwapChars(CString &text, char* from, char* to) { if( strlen(from) != strlen(to)) return -1; int counter = 0; for(int i = 0; i < text.GetLength(); i++) { for(unsigned int k = 0; k < strlen(from); k++) { if(from[k] == text.GetAt(i)) { text.SetAt(i, to[k]); counter++; break; } } } return counter; } [/PHP] und das der Aufruf: [PHP] SwapChars(m_text, "EPSTIWKNUVGCLRYBWHMDOFXQAGepstiwknuvgclrybwhmdofxqag", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); Die Idee ist folgende: Du übergibst der Mehode den Text, der codiert werden soll als Parameter, nämlich 'text'. Du willst jetzt einzelne Buchstaben durch andere austauschen, ja? Die beiden char* geben an, welche Buchstaben durch welche ersetzt werden sollen, nach dem Prinzip: der erste Buchstabe im Array 'from' wird ersetzt durch den ersten Buchstaben im Array 'to'. der zweite Buchstabe im Array 'from' wird ersetzt durch den zweiten Buchstaben im Array 'to'. ... Die erste if-Abfrage stellt nur sicher, dass die Arrays 'from' und 'to' gleich lang sind, so vermeide ich nur einen Access out of Bounds dieser beiden Arrays; Die äussere for-Schleife zählt von 0 bis je nachdem wie lange der Text 'text' ist. mit Text.GetAt(i) kriege ich den Buchstaben aus dem Text, der an i-ter Stelle steht, also alle von 0 bis Ende, weil die äussere for-Schleife i ja durch zählt. Also kriege ich bei jedem Schleifendruchlauf einen einzlenen Buchstaben aus 'text'. Die innere for-schleife, loopt nach dem selben Prinzip über das Array 'from' (welches das Array ist, in dem steht, welche Zeichen ersetzt werden). Mit from[k] kriege ich also den Buchstaben, der an k-ter Stelle in 'from' steht. Also auch wieder einem nach dem anderen. Die if-Abfrage darunter schaut jetzt, ob das Zeichen aus 'text' an i-ter Stelle gleich dem Zeichen aus 'from' an k-ter Stelle ist. Wenn das der Fall ist, muss ja das Zeichen ausgetauscht werden, weil ja in 'from' alle auszutauschenden Zeichen stehen. Das Zeichen dass dafür eingesetzt werden muss, steht ja in dem Array 'to' an gleicher Stelle, wie in dem Array 'from'. Also muss auch from[k] durch to[k] ersetzt werden. Austauschen tue ich das Zeichen mit text.SetAt(i, to[k]), also das i-te Zeichen in 'text' durch das k-te Zeichen in 'to' ersetzen. Der innere for-loop läuft ja über das ganze Array 'from'.... Wenn das Zeichen aber bereits ausgetauscht wurde, sagen wir gleich mal das erste, also E wird zu A, dann brauche ich ja über den Rest von 'from' nicht mehr loopen, und um das zu vermeiden, steht das break; da. Das kann man aber auch weglassen, dass spart nur ein bischen Performance. Ist jetzt ein bischen blöd, weil ich das Beispiel in MFC geschrieben habe, und da bekommt man halt den Inhalt von Textfeldern als CString zurück, deshalb hier nochmal der Code in reinem (Plattform- und Compilerunabhänigem Code) C-Code und als Funktion: int SwapChars(char *text, char* from, char* to) { if( strlen(from) != strlen(to)) return -1; int counter = 0; for(int i = 0; i < strlen(text); i++) { for(unsigned int k = 0; k < strlen(from); k++) { if(from[k] == text[i]) { text[i] = to[k]); counter++; break; } } } return counter; } [/PHP] Vielleicht führt das zu einem einfacherem Verständnis. Wenn du noch fragen hast, kannst du dich ja gern melden. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Knuddlbaer Geschrieben 18. März 2004 Teilen Geschrieben 18. März 2004 Mal ein bisschen C++ spielerei zu diesem Thema (kompletter Source) auch wenns keiner wissen wollte ) #include <string> #include <map> #include <algorithm> #include <iostream> #include <fstream> // Konvertiert x zu y. Wenn x nicht definiert ist wird x zurückgegeben //------------------------------------------------------------------------ // Konvertiert mit Hilfe einer map x zu y wenn definiert //------------------------------------------------------------------------ struct swapHelper : std::unary_function<char,char> { std::map<char,char> mymap; unsigned long counter; swapHelper(std::map<char,char> & yourmap) : counter(0) {mymap = yourmap;} char operator()(char x) { // Wenn für jedes vorkomemnde Zeichen etwas definiert ist: // return mymap[x]; std::map<char,char>::iterator pos = mymap.find(x); if(pos == mymap.end()) return x; else { ++counter; return pos->second; } } }; //------------------------------------------------------------------------ // Baut aus zwei strings eine map auf //------------------------------------------------------------------------ std::map<char,char> strToCharMap(const std::string & from,const std::string & to) { using namespace std; map<char,char> temp; string::const_iterator pos = from.begin(); string::const_iterator pos2 = to.begin(); for(;pos != from.end() && pos2 != to.end();++pos,++pos2) temp.insert(make_pair(*pos,*pos2)); return temp; } //------------------------------------------------------------------------ // Tauscht die in einer map stehenden Zeichen aus mit hilfe von iteratoren //------------------------------------------------------------------------ template<typename BegIn,typename EndIn,typename BegOut> long swapChars(const BegIn & beg,const EndIn & end,const BegOut & out,const std::string & from,const std::string & to) { using namespace std; if(from.size() != to.size()) return -1; map<char,char> myMap(strToCharMap(from,to)); swapHelper swhlp(myMap); std::transform(beg,end,out,swhlp); return swhlp.counter; } //------------------------------------------------------------------------ // //------------------------------------------------------------------------ template<typename BegIt,typename EndIt> long swapChars(const BegIt & beg,const EndIt & end,const std::string & from,const std::string & to) { return swapChars(beg,end,beg,from,to); } //------------------------------------------------------------------------ // //------------------------------------------------------------------------ long swapChars(std::string & text,const std::string & from,const std::string & to) { return swapChars(text.begin(),text.end(),from,to); } //------------------------------------------------------------------------ // //------------------------------------------------------------------------ using namespace std; int main(int argc, char * argv[]) { string temp("Hallo Welt"); string from(" EPSTIWKNUVGCLRYBWHMDOFXQAGepstiwknuvgclrybwhmdofxqag"); string to (" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); cout<<temp<<"\n"; // Einen std::string als Basis nehmen swapChars(temp,from,to); std::cout<<temp<<"\n"; // Beliegige Iteratoren verwenden (hier std::string::iterator) swapChars(temp.begin(),temp.end(),from,to); cout<<temp<<"\n"; // Auch Zeiger sind möglich char temp2[] = "Hallo Welt"; swapChars<char *,char *>(temp2,temp2+sizeof(temp2),from,to); std::cout<<temp2<<"\n"; ifstream in("t:\\in.txt",ios::in|ios::binary); ofstream out("t:\\out.txt",ios::out|ios::binary); if(!in || !out) return 20; istreambuf_iterator<char> beg(in); istreambuf_iterator<char> end; ostreambuf_iterator<char> beg2(out); // Wenn man das Ziel extra angibt werden auch forwarditeratoren möglich swapChars(beg,end,beg2,from,to); return 0; } [/PHP] Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
FinalFantasy Geschrieben 18. März 2004 Teilen Geschrieben 18. März 2004 Komplizierter gehts nicht? Willst ihn jetzt ganz verwirren?? Und was soll da jetzt der Vorteil gegenüber meiner Lösung sein, ausser dass es komplizierter ist?? :confused: Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Deagle--Knight Geschrieben 18. März 2004 Autor Teilen Geschrieben 18. März 2004 hatte ich erwähnt, das ich ein n00b bin ? gut danke - hab nun 2 möglichkeiten, werde die heute abend mal testen und mich dann wieder melden Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Knuddlbaer Geschrieben 18. März 2004 Teilen Geschrieben 18. März 2004 Ich habe nirgens geschrieben das es Vorteile hat. Ich hab einfach Lust gehabt es mal nachzubauen. Da es vllt. in diesem Forum auch noch andere gibt die C++ programmieren, könnte es interesannt sein zu sehen was passiert. Ziel dabei war es: - Leichtes Umdefinieren der "Art" wie die Zeichen geändert werden (also leichtes Austauschen) - Einsatz von Iteratoren (soll heissen z.B. alles verwenden zu können byteweise verwendet werden kann) - Für mich persönlich mal wieder mit prädikaten zu üben - Für mich persönlich mal wieder mit algorithm zu arbeiten - vllt. etwas interesse an C++ zu wecken. (Allerdings lassen sich viele vom ersten Blick gleich abschrecken) Sicherlich ist der Code da oben NICHT anfängerfreundlich. Hat ja aber auch keiner behauptet: Mal ein bisschen C++ spielerei zu diesem Thema (kompletter Source) Damit sollten also die C++ Freaks angesprochen werden. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
FinalFantasy Geschrieben 18. März 2004 Teilen Geschrieben 18. März 2004 Also ehrlich gesagt kann ich mit dem Code selber nicht viel Anfangen. Hab mich eigentlich noch nicht mit Templates befasst. Ne Erklärung wär vielleicht auch nicht schelcht. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Deagle--Knight Geschrieben 18. März 2004 Autor Teilen Geschrieben 18. März 2004 eben mal überflogen .... so wirklich für nen windos oberfläche ist der ja nicht - oder habe ich verpasst das es cout in ner windows oberfläche doch gibt O.o ??? edit: www.4insiders.net/projekte/albhed/screen1.jpg www.4insiders.net/projekte/albhed/screen2.jpg www.4insiders.net/albhed.exe so schauts dann aus, nur die funktion muss ebend noch rein ... danke aber erstmal für eure mühe Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
FinalFantasy Geschrieben 18. März 2004 Teilen Geschrieben 18. März 2004 Für Windowsoberflächen müsstest du nur die cout Aufrufe durch Zuweisungen an entsprechende Variablen ersetzen. Im Endeffekt gehts ja hier ums Prinzip. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
nic_power Geschrieben 18. März 2004 Teilen Geschrieben 18. März 2004 Hallo, warum so kompliziert? Wenn man - wie oben bereits erwähnt - die ASCII-Werte der chars direkt als Index in die Arrays verwendet, kann man sich die Suche nach dem passenden Char komplett sparen (der Beispielcode ist nicht getestet, ist kein C++ und soll auch nur das Prinzip verdeutlichen). Die Implementierung ist sehr kurz und mit ein paar Zeilen Code umzusetzen: char decToEnc[256], encToDec[256]; int encodeString(char *str) { int i; for(i=0; i<strlen(str); i++) printf("%c", decToEnc[str[i]]); } int decodeString(char *str) { int i; for(i=0; i<strlen(str); i++) printf("%c", encToDec[str[i]]); } int main() { char *str1="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char *str2="EPSTIWKNUVGCLRYBWHMDOFXQAG"; unsigned char i; /* Arrays vorinitialisieren */ for(i=0; i<255; i++) { decToEnc[i]=encToDec[i]=i; } /* Uebersetzungstabellen erstellen */ for(i=0; i<strlen(str1); i++) { decToEnc[str1[i]]=str2[i]; encToDec[str2[i]]=str1[i]; } encodeString("HELLO WORLD\n"); decodeString("NICCY XYHCT\n"); } [/php] Nic Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Knuddlbaer Geschrieben 18. März 2004 Teilen Geschrieben 18. März 2004 Original geschrieben von FinalFantasy Also ehrlich gesagt kann ich mit dem Code selber nicht viel Anfangen. Hab mich eigentlich noch nicht mit Templates befasst. Ne Erklärung wär vielleicht auch nicht schelcht. #include <string> #include <map> #include <algorithm> #include <iostream> #include <fstream> //------------------------------------------------------------------------ // Konvertiert mit Hilfe einer map x zu y wenn definiert //------------------------------------------------------------------------ struct swapHelper : std::unary_function<char,char> { std::map<char,char> mymap; unsigned long counter; // Konstruktor.Nimmt eine map entgegen und kopiert sie lokal fürs weiterarbeiten // counter wird auf 0 gesetzt swapHelper(std::map<char,char> & yourmap) : counter(0) {mymap = yourmap;} char operator()(char x) { // Wenn für jedes vorkomemnde Zeichen etwas definiert ist: // return mymap[x]; std::map<char,char>::iterator pos = mymap.find(x); if(pos == mymap.end()) // Wenn das Zeichen nicht in der Map steht return x; // original zurückgeben else // Ansonsten { ++counter; // den Zähler erhöhen return pos->second; // und das Zeichen durch das getauscht werden soll zurückgeben } } }; // Das Konstrukt da oben wird für std::transform benötigt. In C wäre es einfach ein Funktionszeiger. // Da ich aber eine map brauche die mit die "Übersetzung" hält und ich einen Counter am ende // auslesen will habe ich eine Klasse genommen die im Konstruktur die map bekommt und mir // den Counter zählt. // std::transform ruft den operator() auf von dem was es übergeben bekommt.Somit kommt // char operator()(char x) ins Spiel. // Das ganze von std::unary_function abgeleitet ermöglicht es einfach in Tranform zu verwenden. // Das könnte dem Objekt auch noch massig Funktionen dazu geben und es detailliert Informieren // wann es was zu tun hat. //------------------------------------------------------------------------ // Baut aus zwei strings eine map auf //------------------------------------------------------------------------ std::map<char,char> strToCharMap(const std::string & from,const std::string & to) { using namespace std; map<char,char> temp; string::const_iterator pos = from.begin(); string::const_iterator pos2 = to.begin(); // Über beide Strings laufen bis einer das ende Erreicht hat // (std::string hört nicht bei \0 auf) for(;pos != from.end() && pos2 != to.end();++pos,++pos2) temp.insert(make_pair(*pos,*pos2)); // Wertepaar speichern return temp; } // Mir ist keine rechte Idee gekommen wie ich die 2 Arrays verwende // Eine map hält ein Wertepaar das in einem Suchbaum gehalten wird. // Ich investiere hier die Zeit jedes Zeichen der 2 Strings als Wertepaar zu speichern. // Erleichtert mir später die Arbeit mit suchen und ersetzen. //------------------------------------------------------------------------ // Tauscht die in einer map stehenden Zeichen aus mit hilfe von iteratoren //------------------------------------------------------------------------ template<typename BegIn,typename EndIn,typename BegOut> long swapChars(const BegIn & beg,const EndIn & end,const BegOut & out,const std::string & from,const std::string & to) { using namespace std; if(from.size() != to.size()) return -1; map<char,char> myMap(strToCharMap(from,to)); // Map erzeugen und Compileroptimierung ausnutzen. // hier wird keiner map erstellt. // Anlegen des swapHelpers mit unserer Übersetzungstabelle swapHelper swhlp(myMap); // Würde man swapHelper swhlp(strToCharMap(from,to)); schreiben // könnte der Compiler die map gleich im Objekt erstellen // Und nun jedes einzelne Zeichen durch den swapHelper schicken std::transform(beg,end,out,swhlp); return swhlp.counter; // zurpückgeben wieviel Zeichen gezählt wurden } // Diese Routine macht die gleiche Arbeit wie Deine (mit ner menge Hilfe von aussen) // Als erstes wird auch hier die größe Überprüft (um kompatiebel zu bleiben mit Deiner Funktion) // Danach werden die Strings als Wertepaare gespeichert. (Spart später das immer wieder suchen der Zeichen) // Gefolgt wird das ganze vom Anlegen des swapHelpers. // Der kann auch so verwendet werden:: cout<<swhlp('H'); // Dieser sorgt einfach nur dafür das H in irgendwas anderes gewandelt wird. // Im Konstruktor bekommt der swapHelper die map übergeben in der steht was passieren soll // tansform: // transform erwartet den Anfang und das Ende der Quelle, den Start des Ziels und einem Objekt // das etwas macht. Das Ziel muß dabei genug Platz bieten. // transform geht nun zeichen für zeichen so vor: // Nimm ein Zeichen von Source übergebe es an swhlp() und schreibe das Ergebnis in Dest // Danach dest und source ein Zeichen weiterstellen // mit tranfsorm(text.begin(),text.end(),text.begin(),ptr_fun(toupper)); // könntest Du z.B. alle Zeichen in groß wandeln. // die Templates: // Die Templates sorgen dafür das man allerlei angeben kann. Der Compiler setzt den passenden Typen ein // durch die Templates wird es möglich iteratoren und zeiger zu verwenden. // iteratoren: // Eine Abstraktion von Zeigern die speziell auf eine Klasse angepasst sind. // Bei einer verketteten Liste wird zum nächsten Element gesprungen // bei einer Datei zum nächsten Zeichen... // Ähneln im prinzip sehr stark den Zeigern //------------------------------------------------------------------------ // //------------------------------------------------------------------------ template<typename BegIt,typename EndIt> long swapChars(const BegIt & beg,const EndIt & end,const std::string & from,const std::string & to) { return swapChars(beg,end,beg,from,to); } // Wenn jemand kein extra Ziel hat wird hier einfach in den gleichen Bereich zurückgeschrieben // aus dem gelesen wurde. //------------------------------------------------------------------------ // //------------------------------------------------------------------------ long swapChars(std::string & text,const std::string & from,const std::string & to) { return swapChars(text.begin(),text.end(),from,to); } // Wenn jemand einen std::string übergeben hat wird dieser mit seinen Iteratoren an die obrige // Methode gegeben. // Somit spart man sich das immer wieder neu schreiben der Methode. // Damit der Anwender aber nicht swapCharString swapChar2Iter swapChar3Iter etc. aufrufen // muss wurde das hier überladen. Zu beachten bei templates: Die überladungen müssen // vor der verwendung bekannt gemacht werden! //------------------------------------------------------------------------ // //------------------------------------------------------------------------ using namespace std; int main(int argc, char * argv[]) { // String zum testen string temp("Hallo Welt"); // Übersetzungsstrings string from(" EPSTIWKNUVGCLRYBWHMDOFXQAGepstiwknuvgclrybwhmdofxqag"); string to (" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); // Original auf dem Bildschrim ausgeben cout<<temp<<"\n"; // Einen std::string als Basis nehmen // und diesen "Übersetzen" swapChars(temp,from,to); std::cout<<temp<<"\n"; // Beliegige Iteratoren verwenden (hier std::string::iterator) // Hier wird gezeigt wie man iteratoren verwenden kann // z.B. könnte die Basis auch vector<char> sein oder list<char> o.ä. swapChars(temp.begin(),temp.end(),from,to); cout<<temp<<"\n"; // Hier ein Beispiel geben wie man Zeiger verwenden kann // wenn man CString hat könnte man das z.B. so machen char temp2[] = "Hallo Welt"; // dem Compiler helfen zu erkennen um welchen Typ es sich handelt // dann den Start und das Ende des zu bearbeitenden Bereichs angeben swapChars<char *,char *>(temp2,temp2+sizeof(temp2),from,to); std::cout<<temp2<<"\n"; // Eine Datei zum lesen und eine zum schreiben öffnen (binär) ifstream in("t:\\in.txt",ios::in|ios::binary); ofstream out("t:\\out.txt",ios::out|ios::binary); //prüfen ob beide Dateien geöffnet sind if(!in || !out) return 20; // Ermöglicht es Dateien fast wie Zeiger zu verwenden // dieser Zeiger funktioniert aber nur in eine richtung! istreambuf_iterator<char> beg(in); // Erzeugt sowas wie einen virtuellen Zeiger der sich fast wie char* verhält istreambuf_iterator<char> end; // und an den Anfang der Datei zeigt. Wenn das ende der Datei erreicht ist wird einfach nur ein leerer "Zeiger" zurückgegeben ostreambuf_iterator<char> beg2(out);// das ganze noch mal für die Ausgabe datei // Die Datei kopieren und dabei übersetzen swapChars(beg,end,beg2,from,to); return 0; } [/PHP] Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Deagle--Knight Geschrieben 18. März 2004 Autor Teilen Geschrieben 18. März 2004 öhm, was soll ich den mit den beiden text datein ? oder gehört das auch zum allgemeinen verständnis :confused: ich werd dann erstmal FinalFantasy'S lösung ausprobieren - bevor ich das komplexe mir in den kopf haue ... Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Knuddlbaer Geschrieben 18. März 2004 Teilen Geschrieben 18. März 2004 Original geschrieben von nic_power Hallo, warum so kompliziert? Wenn man - wie oben bereits erwähnt - die ASCII-Werte der chars direkt als Index in die Arrays verwendet, kann man sich die Suche nach dem passenden Char komplett sparen Stimmt... Viel zu kompliziert da oben ( Nimmt man mal das was Du gemacht hast ins prädikat auf ist man noch genauso flexiebel (iteratoren...) , es schaut besser aus ist schlanker.... Naja, einfach besser ) #include <string> #include <algorithm> #include <vector> #include <functional> struct DeCode: std::unary_function<char,char> { std::vector<char> dec; unsigned long counter; DeCode(const std::string & from,const std::string & to) : counter(0) { dec.resize(256); for(int i = 0;i < 256;++i) dec.push_back(i); std::string::const_iterator pos2 = to.begin(); for(std::string::const_iterator pos = from.begin();pos != from.end() && pos2 != to.end();++pos,++pos2) dec[*pos] = *pos2; } char operator()(char x) { return dec[x]; } }; struct EnCode: std::unary_function<char,char> { std::vector<char> enc; unsigned long counter; EnCode(const std::string & from,const std::string & to) : counter(0) { enc.resize(256); for(int i = 0;i < 256;++i) enc[i] = i; std::string::const_iterator pos2 = to.begin(); for(std::string::const_iterator pos = from.begin();pos != from.end() && pos2 != to.end();++pos,++pos2) { enc[*pos2] = *pos; } } char operator()(char x) { return enc[x]; } }; int main() { char *str1="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char *str2="EPSTIWKNUVGCLRYBWHMDOFXQAG"; EnCode enc(str1,str2); DeCode dec(str1,str2); std::string temp("HALLO WELT\n"); std::transform(temp.begin(),temp.end(),temp.begin(),enc); std::cout<<temp; std::transform(temp.begin(),temp.end(),temp.begin(),dec); std::cout<<temp; } Allerdings stehe ich hier auch schon wieder in Versuchung das Füllen des vectors auszulagern und nurnoch den Vector zu übergeben. Dann noch nen Wrapper drum damit ich diesen Aufruf verstecke... Und bin bis auf die Map wieder da wo ich vorhin war :/ [/PHP] Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Knuddlbaer Geschrieben 18. März 2004 Teilen Geschrieben 18. März 2004 [quäl] #include <string> #include <algorithm> #include <vector> #include <functional> namespace { void fillVec(std::vector<char> & vec,const std::string & from,const std::string & to) { vec.resize(256); for(int i = 0;i < 256;++i) vec[i] = i; std::string::const_iterator pos2 = to.begin(); for(std::string::const_iterator pos = from.begin();pos != from.end() && pos2 != to.end();++pos,++pos2) vec[*pos] = *pos2; } } struct DeCode: std::unary_function<char,char> { std::vector<char> dec; unsigned long counter; DeCode(const std::string & from,const std::string & to) : counter(0) { fillVec(dec,from,to); } char operator()(char x) { return dec[x]; } }; struct EnCode: std::unary_function<char,char> { std::vector<char> enc; unsigned long counter; EnCode(const std::string & from,const std::string & to) : counter(0) { fillVec(enc,to,from);} char operator()(char x) { return enc[x]; } }; int main() { char *str1="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char *str2="EPSTIWKNUVGCLRYBWHMDOFXQAG"; EnCode enc(str1,str2); DeCode dec(str1,str2); std::string temp("HALLO WELT\n"); std::transform(temp.begin(),temp.end(),temp.begin(),enc); std::cout<<temp; std::transform(temp.begin(),temp.end(),temp.begin(),dec); std::cout<<temp; } [/PHP] [/quäl] Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
maxim_42 Geschrieben 18. März 2004 Teilen Geschrieben 18. März 2004 Habs auch mal probiert. Ist schon lange her das ich in C/C++ was gemacht hab... In main.h: #include <string> class tauscher { public: static void enc (std::string& zuTauschen); static void dec (std::string& zuTauschen); tauscher(const std::string& orign,const std::string& verschluesselt); private: static char encryptor[255]; static char decryptor[255]; static char charEncrypt (char zuTauschen); static char charDecrypt (char zuTauschen); };[/PHP] In main.cpp: [PHP] #include "main.h" #include <iostream> #include <string> char tauscher::encryptor[255] ={0}; //Alle Elemente im Feld mit 0 initialisieren char tauscher::decryptor[255] ={0}; //****** ctor ******* tauscher::tauscher(const std::string& orign,const std::string& verschluesselt) { unsigned int limit = orign.length()<= verschluesselt.length()? orign.length(): verschluesselt.length(); for ( int i = 0 ; i<limit ; i++){ encryptor[(unsigned int)orign[i]]=verschluesselt[i]; // Im ersten Durchlauf (bei i=0), steht dann im Array encryptor unter dem Index 65 (Ascii-Wert für 'A') // das Zeichen 'E' // wenn der tauscher-Aufruf in main(() z.B. so aussieht: //tauscher::tauscher ("ABCDEFGHIJKLMNOPQRSTUVWXYZ","EPSTIWKNUVGCLRYBWHMDOFXQAG"); decryptor[(unsigned int)verschluesselt[i]] =orign[i]; //Analog, nur eben umgekehrt } } //****** ctor ******* char tauscher::charEncrypt(char zuTauschen) { return encryptor[(unsigned int) zuTauschen]; //für zuTauschen ='A' wird encryptor[65] zurückgegeben } //****** ctor ******* char tauscher::charDecrypt(char zuTauschen) { return decryptor[(unsigned int) zuTauschen]; } void tauscher::enc(std::string& zuTauschen){ for (unsigned int i =0; i< zuTauschen.length(); i++) { //Für jedes Zeichen im Strting zuTauschen char c= zuTauschen[i]; // c ist das Zeichen an der Stelle i im String zuTauschen if( c= charEncrypt(c) ){ // c ist 0, wenn encryptor[c] nicht durch den Konstruktor überschrieben wurde. // in dem Fall wird das Zeichen nicht verändert. zuTauschen[i]= c; } } } void tauscher::dec(std::string& zuTauschen){ for (unsigned int i =0; i< zuTauschen.length(); i++) { char c= zuTauschen[i]; if( c= charDecrypt(c) ){ zuTauschen[i]= c; } } } int main(){ tauscher::tauscher ("ABCDEFGHIJKLMNOPQRSTUVWXYZ","EPSTIWKNUVGCLRYBWHMDOFXQAG"); //Konstruktoraufruf std::string Ursprung = "ein DEB"; std::cout<<"Ursprung: " << Ursprung <<std::endl; tauscher::enc(Ursprung); //Aufruf der statischen Funktion enc std::cout<< "Getauscht: " << Ursprung <<std::endl<<std::endl; std::cout<< "Und zurück: "; tauscher::dec(Ursprung); std::cout<< Ursprung <<std::endl; return 1; }; Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.