Implementation, Ceaser Cipher in C++ I'm working on learning C++ coming from python. I'm doing some projects to help me out understanding the language a bit more.

My code works I just want to know if there is anything that I can improve on it or best practices in C++, maybe something that I should have done differently.

// Ceaser Cipher implementation

#include &lt;iostream&gt;
#include &lt;string&gt;




char shiftF(char ch, int shift, const char type)
{
    if (type == 'e')
    {
        return ch == 'z' || ch == 'Z' ? ch - 25 : ch + shift;
    }
    else if (type == 'd')
    {
        return ch == 'z' || ch == 'Z' ? ch - 25 : ch - shift;
    }
}


std::string encode(std::string str, int shift, char type)
{
    std::string tempMsg;
    for (auto ch : str)
    {
        if (isalpha(ch))
        {
            tempMsg += shiftF(ch, shift, type);
        }
        else if (isspace(ch))
        {
            // There is probably a better way to do this.
            tempMsg += " "; 
        }
        else if (isalnum(ch))
        {
            continue;
        }
    }
    return tempMsg;
}


int main(int argc, char *argv[])
{
    int choice;
    std::cout &lt;&lt; "What do you want to do? 1.Encrypt, 2.Decrypt: ";
    std::cin &gt;&gt; choice;
    std::string result;
    const char dec = 'd';
    const char enc = 'e';

    if (choice == 1)
    {
        int key;
        std::cout &lt;&lt; "Enter encryption shift: ";
        std::cin &gt;&gt; key;

        std::string msg;
        std::cout &lt;&lt; "Enter a message: ";

        // This doesn't work for some reason?
        // std::cin.clear();
        // std::cin.sync();

        std::cin.ignore();
        std::getline(std::cin, msg);

        result = encode(msg, key, enc);
    }

    else if (choice == 2)
    {
        int key;
        std::cout &lt;&lt; "Enter decryption shift: ";
        std::cin &gt;&gt; key;

        std::string msg;
        std::cout &lt;&lt; "Enter a message: ";

        std::cin.ignore();
        std::getline(std::cin, msg);

        result = encode(msg, key, dec);
    }
    else
    {
        std::cout &lt;&lt; "Wrong option, exiting!";
    }

    std::cout &lt;&lt; "Message encoded: " &lt;&lt; result;
}
Your functions are doing too much. Remember: one function, one responsibility. That is, the encode function actually both encodes and decodes and that behavior is controlled via its arguments. In particular, the choice of behavior is offloaded to shiftF based on a char. There is no error if that char is anything other than 'd' or 'e'. This is something that we should absolutely try to avoid: we want to catch as many problems as we can at compile-time, but even runtime errors are preferred to silent errors!

On closer inspection, there is no need for such a complication. In fact, the only difference between encoding and decoding is the sign of shift. So we could write:

std::string encode(const std::string&amp; str, int shift)
{
    std::string tempMsg;

    std::transform(str.cbegin(), str.cend(), std::back_inserter(tempMsg), [&amp;](char ch) -&gt; char
    { 
        if (isspace(ch))
            return ' ';

        return ch == 'z' || ch == 'Z' ? ch - 25 : ch + shift; 
    });

    return tempMsg;
}

std::string decode(const std::string&amp; str, int shift)
{
    return encode(str, -1 * shift);
}


What is happening here?


We pass the input message str as a const-ref and not by-value as in your original code. When you pass by-value, the object gets copied and in this case there is no reason for it. In this case, you could actually even pass the object by-reference only, and modify it in-place but we're not doing it here.
We use a standard function std::transform with a lambda function that encapsulates the logic of shiftF. You need to include &lt;algorithm&gt; for this use.
The third argument for std::transform is std::back_inserter found from &lt;iterator&gt;, which takes care of inserting at the back of the string tempMsg.
Conceptually, the division of encoding and decoding into separate functions is cleaner and more logical. Whenever you can implement another function in terms of other functions, it's likely a good idea because you don't have to repeat yourself leading to less maintenance decreasing the chances for bugs.


Once you adopt this approach, you can get rid of the const char variables from your main program, and just call the correct encode or decode function inside your if-statement. As a side remark, you could also return meaningful error codes in your main. For example, if the choice is invalid, return from the else-branch e.g., EXIT_FAILURE.