Schwierigkeiten mit for-Schleife - Verschiebewert zusätzlich plus 1 für das erste Feld, plus 2 für das zweite Feld...



  • 😕

    und wieder Hallo,

    mittlerweile bin ich mit dem Versuch etwas weitergekommen:

    Wenn ich an die verschiebung++ anhänge, wird der erste Wert um den Verschiebewert - alle anderen plus 1 verschoben.

    Ich kann es nur sehr unelegant lösen, indem ich den kompletten Code ändere und die Felder einzeln ansteuere, z. B.:

    // erstes Element ausgeben
    std::cout << "1. Element" << zeichenkette[0] << std::endl;
    zeichenkette[0] = zeichenkette[0] +verschiebung +1;
    std::cout<< "1. Element verschoben: " <<zeichenkette[0] <<endl;

    Würde aber gerne mit einer for-Schleife eine elegantere Lösung finden. Zumal ich die Eingabelänge nicht begrenzen möchte.

    Die Aufgabe: String eingeben - Verschiebewert eingeben, das erste Feld um den Verschiebewert +1 erhöhen, das zweite um den Verschiebewert +2 usw.

    Bitte um Hilfe - habe augenscheinlich ein Verständnisproblem...

    Danke schonmal 🙂

    /*##############################################

    Ein einfaches Verschlüsselungsprogramm

    ##############################################*/

    #include <iostream>

    using namespace std;

    //die Funktion
    void caesar(string);

    //die Funktion zur Cäsar-Verschlüsselung

    void caesar(string kette)

    {

    int laenge, verschiebung;

    //die Länge der ursprünglichen Zeichenkette ermitteln

    laenge = kette.length();

    cout << "Caesar-Verschluesselung" << endl;

    //den Verschiebewert einlesen

    cout << "Bitte geben Sie den Verschiebewert ein: ";

    cin >> verschiebung;

    //jedes Zeichen um den angegebenen Wert verschieben

    for (int zaehler = 0; zaehler < laenge; zaehler++)

    cout << static_cast<char>(kette[zaehler] + verschiebung++);

    cout << endl << endl;

    }

    int main()

    {

    string eingabe;

    //Die ursprüngliche Zeichenkette einlesen

    cout << "Bitte geben Sie eine Zeichenkette ein (ohne Leerzeichen): ";

    cin >> eingabe;

    cout << "Die urspruengliche Zeichenkette ist: " << eingabe << endl << endl;

    //die Verschlüsselungen durchführen

    caesar(eingabe);

    return 0;

    }



  • Wie wäre es, wenn du mal endlich Codetags benutzt?



  • Code-Tags!

    Hier wäre meine Lösung 😉
    Schau dir einfach die crypt-Funktion an, um zu sehen, wie das geht. Die CesarChar Klasse sorgt nur dafür, dass das inkrementieren/dekrementieren korrekt abläuft.

    #include <iostream>
    #include <string>
    #include <vector>
    #include<limits>
    
    using namespace std;
    
    using std::vector;
    
    class CesarChar
    {
        char _char;
    
        bool CharIsLetter() const
        {
            return (_char >= 65 && _char <= 90) || (_char >= 97 && _char <= 122);
        }
    
        public:
    
            CesarChar(char ch = ' ') : _char(ch){}
    
            CesarChar operator+(unsigned amount) const
            {
                amount %= 26;
                CesarChar temp(*this);
                for (unsigned i = 0; i<amount; ++i)
                    ++temp;
                return temp;
            }
    
            CesarChar operator-(unsigned amount) const
            {
                amount %= 26;
                CesarChar temp(*this);
                for (unsigned i = 0; i<amount; ++i)
                    --temp;
                return temp;
            }
    
            CesarChar operator-=(unsigned amount)
            {
                amount %= 26;
                *this = *this-amount;
    
                return *this;
            }
    
            CesarChar& operator+=(unsigned amount)
            {
                amount %= 26;
                *this = *this+amount;
                return *this;
            }
    
            CesarChar& operator++()
            {
                if (!CharIsLetter())
                    return *this;
                switch (_char)
                {
                    case 'z':
                        _char = 'a';
                        break;
                    case 'Z':
                        _char = 'A';
                        break;
                    default:
                        ++_char;
                        break;
                }
                return *this;
            }
    
            CesarChar& operator--()
            {
                if (!CharIsLetter())
                    return *this;
                switch (_char)
                {
                    case 'a':
                        _char = 'z';
                        break;
                    case 'A':
                        _char = 'z';
                        break;
                    default:
                        --_char;
                        break;
                }
    
                return *this;
            }
    
            char ch() const {return _char;}
    };
    
    class CesarString
    {
        protected:
    
            vector<CesarChar> _string;
            vector<unsigned> _amounts;
            typedef reverse_iterator<vector<unsigned>::iterator> reverse_iterator_type;
    
        public:
    
            CesarString(string str = " ") : _string(str.begin(), str.end()), _amounts(0){}
            virtual ~CesarString(){}
    
            void crypt(unsigned amount)
            {
                for (vector<CesarChar>::iterator it = _string.begin(); it != _string.end(); ++it)
                    (*it) += amount;
                _amounts.push_back(amount);
            }
    
            void decrypt()
            {
                for (vector<CesarChar>::iterator jt = _string.begin(); jt != _string.end(); ++jt)
                    *jt -= _amounts.back();
                _amounts.pop_back();
            }
    
            void decrypt_all()
            {
                for (reverse_iterator_type it(reverse_iterator_type(_amounts.end()));
                 it != reverse_iterator_type(_amounts.begin());
                  ++it)
                {
                    for (vector<CesarChar>::iterator jt = _string.begin(); jt != _string.end(); ++jt)
                        *jt -= *it;
                    _amounts.pop_back();
                }
            }
    
            void print()
            {
                for (vector<CesarChar>::iterator it = _string.begin(); it != _string.end(); ++it)
                    std::cout << it->ch();
                cout << '\n';
            }
    };
    
    class VariableCesarString : public CesarString
    {
        public:
    
            VariableCesarString(std::string const& str) : CesarString(str){}
    
            void crypt(unsigned amount)
            {
                for (unsigned i(0); i<_string.size(); ++i)
                    _string[i] += amount+i+1;
                _amounts.push_back(amount);
            }
    
            void decrypt()
            {
                for (unsigned i(0); i<_string.size(); ++i)
                {
                    _string[i] -= _amounts.back()+i+1;
                }
                _amounts.pop_back();
            }
    
            void decrypt_all()
            {
                //kb die jetzt auch noch zu überschreiben
            }
    
    };
    
    int main()
    {
        std::string str;
        std::vector<unsigned> amounts;
        unsigned amount(0);
        std::cout << "String to crypt: ";
        getline(cin, str);
        while(1)
        {
            std::cout << "\nHow often to shift: ";
            std::cin >> amount;
            cin.ignore(256, '\n');
            if (!amount)
            {
                break;
            }
            amounts.push_back(amount);
        }
    
        VariableCesarString cstring(str);
    
        for (std::vector<unsigned>::iterator it(amounts.begin()); it != amounts.end(); ++it)
            cstring.crypt(*it);
    
        std::cout << "crypted version: ";
        cstring.print();
    
        cstring.decrypt();
    
        std::cout << "\ndecrypted version: ";
        cstring.print();
    }
    

    casts sind übrigens meist fehl am Platz - gerade bei Anfängern.



  • Ich sollte vllt. doch noch eine Erklärung abgeben:
    hier aus VariableCesarString::crypt:

    void crypt(unsigned amount)
            {
                for (unsigned i(0); i<_string.size(); ++i)
                    _string[i] += amount+i+1;
                _amounts.push_back(amount);
            }
    

    Mit der for-Schleife wird der gesamte Vektor durchgegangen und jedes Element um den übergebenen Wert (amount) erhöht, zusätzlich wird noch eine Erhöhung um i, also die Zählvariable und um 1, da die Zählvariable bei 0, du aber bei 1 anfangen wolltest, vorgenommen. Beim decrypten läuft das genau andersrum.



  • 👍
    Besonders Tobi vielen Dank.
    Dein Code ist super - für mich aber noch etwas viel. Aber deine crypt-Erklärung hat es gebracht - die kann ich einfach anpassen und in den code schreiben - dann klappt es.

    //jedes Zeichen um den angegebenen Wert verschieben

    for (int zaehler = 0; zaehler < laenge; zaehler++)

    cout << static_cast<char>(kette[zaehler] + verschiebung +(zaehler+1));

    Schönes Restwochenende.

    Ein Wort noch zu den Tags - ich gebe sie zwar ein, aber schon in der Vorschau wird alles automatisch eingerückt. Übrigens auch, wenn ich Tabs u. ä. oder die vorgegebenen Zeichen bei der Eingabe verwende...

    Ich würde das wirklich gerne abstellen...


Anmelden zum Antworten