Caesar-Verschlüsslung?

04/30/2013 23:21 CashOrSmash#1
Hey ich habe mich an die Caesar-Verschlüsslung gesetzt und komm nicht weiter... :(
Das Problem ist das der keine Sätze verschlüsselt warum auch immer..
Da ich neu in C++ bin freu ich mich über Tipps aandd Tricks :D

Code:
#include <iostream>
#include <string>
using namespace std;

string crypt(string text,int chiffre) {
    for(unsigned int i = 0; i < text.length(); i++) {
        text[i] = text[i] + chiffre;
    }
    return text;
}

string decrypt(string text,int chiffre) {
    for(unsigned int i = 0; i < text.length(); i--) {
        text[i] = text[i] - chiffre;
    }
    return text;
}

int main()
{
    string textc = "";
    string textd = "";
    char input = '0';
    int chiffre = 0;
    bool exit = false;

    do{
        cout << "Caesar-Chiffre" << endl << endl;
        cout << "<1> Crypt" << endl;
        cout << "<2> Decrypt" << endl;
        cout << "<3> Exit" << endl;
        cout << endl << "Input : ";
        cin >> input;

        switch(input) {
            case '1' : cout << endl << "Text : ";
                       cin >> textc;
                       fflush(stdin);
                       cout << endl << "Chiffre : ";
                       cin >> chiffre;
                       fflush(stdin);
                       cout << endl << endl << crypt(textc,chiffre) << endl;
                       fflush(stdin);
                       getchar();
                       break;
            case '2' : cout << endl << "Text : ";
                       cin >> textd;
                       cout << endl << "Chiffre : ";
                       cin >> chiffre;
                       cout << endl << endl << decrypt(textd,chiffre) << endl;
                       fflush(stdin);
                       getchar();
                       break;
            case '3' : exit = true;
                       break;
           default : cout << endl << "Fuck off choose a option from the list!" << endl << endl;
                     break;
                     }
        }while(exit == false);

    return 0;
}

Danke im vorraus :)
04/30/2013 23:46 Schlüsselbein#2
Das liegt daran, dass operator>> von std::cin bis zum Leerzeichen einliest.
Ausserdem zum Code:

1. Benutz beim Parameter const std::string& statt std::string.
2. Benutz am besten direkt std::transform aus dem header 'algorithm'
3. Gewöhn dir das globale 'using namespace std;' ab
4. Prüfe generell beim Einlesen via std::cin::operator>> auf Erfolg
Code:
if(std::cin >> var) { // continue... }
5. Lass das 'fflush(stdin);' weg (ruft laut Standard undefiniertes Verhalten hervor)
6. statt 'exit == false' einfach '!exit'

Das ist mir auf den ersten Blick aufgefallen.





Gruß
04/30/2013 23:59 CashOrSmash#3
Ok Danke :) Falls ihr noch was findet schreibt es bitte ! :)
05/01/2013 00:45 Master674b#4
Quote:
Originally Posted by Schlüsselbein View Post
Das liegt daran, dass operator>> von std::cin bis zum Leerzeichen einliest.
Ausserdem zum Code:

1. Benutz beim Parameter const std::string& statt std::string.
2. Benutz am besten direkt std::transform aus dem header 'algorithm'
3. Gewöhn dir das globale 'using namespace std;' ab
4. Prüfe generell beim Einlesen via std::cin::operator>> auf Erfolg
Code:
if(std::cin >> var) { // continue... }
5. Lass das 'fflush(stdin);' weg (ruft laut Standard undefiniertes Verhalten hervor)
6. statt 'exit == false' einfach '!exit'

Das ist mir auf den ersten Blick aufgefallen.





Gruß
Punkt 1 ist nicht notwendig, bzw. klappt mit dem Implementationsprinzip so gar nicht, es wird immer auf eine Kopie hinauslaufen, von daher ists einfach Wurscht. Das mit std::transform ist natürlich grundsätzlich schon auch eine gute Lösung:

Code:
std::string encrypt(const std::string &str, char chiffre) {
    std::string result;
    std::transform(str.begin(), str.end(),
        std::back_inserter(result), [&] (char c) {
        return (c + chiffre) & 0xFF;
    });
    return result;
}
05/01/2013 00:59 snow#5
^Ich habe auch erst gedacht, dass er mit der const Reference den Parameter meint, aber der Rückgabewert erscheint mir logischer.

@TE: "endl << endl" - ich nehme an, du willst damit eine neue Zeile erzeugen? endl leert gleichzeitig auch den Buffer, braucht also wohl ein bisschen mehr Performance. Ich würde da einfach << "\n\n" << text nehmen, das ist die Escape-Sequenz für newline. :)

Und Schlüsselbein rät normalerweise ganz gerne von getchar ab, da man möglichst C und C++ nicht blind vermischen sollte. std::cin.get() sollte da auch funktionieren.

Wenn du Sätze einlesen willst: std::getline(std::cin, DEINSTRING);, ich weiß gerade nicht, welchen Rückgabewert das gibt, aber gefühlt bekommst du wie bei std::cin einen Return-Wert, der nicht 0 sein sollte, wenn alles gut ist.
05/01/2013 01:02 Master674b#6
Quote:
Originally Posted by snow911 View Post
^Ich habe auch erst gedacht, dass er mit der const Reference den Parameter meint, aber der Rückgabewert erscheint mir logischer.

@TE: "endl << endl" - ich nehme an, du willst damit eine neue Zeile erzeugen? endl leert gleichzeitig auch den Buffer, braucht also wohl ein bisschen mehr Performance. Ich würde da einfach << "\n\n" << text nehmen, das ist die Escape-Sequenz für newline. :)

Und Schlüsselbein rät normalerweise ganz gerne von getchar ab, da man möglichst C und C++ nicht blind vermischen sollte. std::cin.get() sollte da auch funktionieren.

Wenn du Sätze einlesen willst: std::getline(std::cin, DEINSTRING);, ich weiß gerade nicht, welchen Rückgabewert das gibt, aber gefühlt bekommst du wie bei std::cin einen Return-Wert, der nicht 0 sein sollte, wenn alles gut ist.
Benutze da meistens einfach std::cin.sync nach einer Input operation, dann funktioniert der Stream wieder (clear nicht vergessen für die error flags!) :p
05/01/2013 08:26 Delinquenz#7
Quote:
1. Benutz beim Parameter const std::string& statt std::string.
Ist wohl veraltet und sofern du einen string übergibst, der nicht const ist, wird, afaik auch eine temporäre Kopie erstellt. Habe im C++ Forum mal irgendwas darüber gelesen. Da gibts wohl eine bessere Alternative mit std::move, finde den Thread grade nicht mehr.
05/01/2013 08:48 Schlüsselbein#8
Quote:
Ich habe auch erst gedacht, dass er mit der const Reference den Parameter meint, aber der Rückgabewert erscheint mir logischer.
Nein, ich habe schon den Parameter gemeint. Ihr habt aber recht, das ist in dem Fall eigentlich egal.
Deshalb würde ich hier wie schon gesagt direkt std::transform benutzen oder etwas im Stile von:
Code:
template <class InputIt, class OutputIt>
OutputIt encrypt(InputIt beg, InputIt end, OutputIt result, int chiffre);
basteln. Damit spart man sich nicht nur kopiererei, sondern kann auch die Funktion auf jeden Container anwenden.
05/01/2013 13:05 Master674b#9
Quote:
Originally Posted by Delinquenz View Post
Ist wohl veraltet und sofern du einen string übergibst, der nicht const ist, wird, afaik auch eine temporäre Kopie erstellt. Habe im C++ Forum mal irgendwas darüber gelesen. Da gibts wohl eine bessere Alternative mit std::move, finde den Thread grade nicht mehr.
Jo std::move verschiebt quasi den inhalt und hinterlässt ein leeres aber valides objekt.

Passt z.B. hier, also bei sowas sollte man dann by value übergeben:

Code:
void storeMe(object o) {
   m_container.push_back(std::move(o)); // in den container moven
}

// object braucht natürlich move semantics damit das klappt!

object o;
storeMe(o); // copy ctor...

storeMe(std::move(o)); // move ctor...
// o ist nun "leer", bei nem string halt einfach kein inhalt mehr da, kann aber weiter verwendet werden

storeMe(object()); // move ctor weil temporary
Damit hast dann 0 kopien :p

Btw: Bei Rückgaben niemals mit std::move zurückgeben, das macht der Compiler automatisch, ihr stört damit nur NRVO. Die heutigen Compiler moven sowieso wo es nur geht ^^