简体   繁体   中英

C++ Encryption Program Not Working

I have been writing a very basic encryption program in C++ where the user is asked to enter a message, and then a number with the same number of digits as the number of characters in the message. Then it converts each character in the message to the ascii number, and then adds the each digit in the number to the ascii, and then converts back to a character and returns the encrypted string. And the progress happens in reverse to decrypt. When I tried to encrypt "hello", I got . Can someone please explain how I can fix this? I have not finished the code, but this is it so far:

#include <iostream>
using namespace std;

string encryptMsg(string msg)
{
    cout << "Enter a number that is " << msg.length() << " digits long: ";
    string codekey;
    cin >> codekey;
    char msgArr[msg.length()];
    int keyCode[msg.length()];
    int tempcount = 0;
    for(char& c : msg) {
        msgArr[tempcount] = c;
        tempcount++;
    };
    tempcount = 0;

    for(char& c : codekey) {
        keyCode[tempcount] = c;
        tempcount++;
    };
    double tempascii;
    for(int i = 0; i < (sizeof(msgArr)/sizeof(msgArr[0])); i++)
    {
        tempascii = msgArr[i];
        tempascii = tempascii + keyCode[i];
        msgArr[i] = tempascii;
    };
    string outmsg;
    for(int i = 0; i < (sizeof(msgArr)/sizeof(msgArr[0])); i++)
    {
        outmsg = outmsg + msgArr[i];
    };
    return outmsg;
}

string decryptMsg(string msg)
{
    char msgArr[msg.length()];
    int tempcount = 0;
    for(char& c : msg) {
        msgArr[tempcount] = c;
        tempcount++;
    };
    double tempascii;
    for(int i = 0; i < (sizeof(msgArr)/sizeof(msgArr[0])); i++)
    {
        tempascii = msgArr[i];
        tempascii = tempascii - 3;
        msgArr[i] = tempascii;
    };
    string outmsg;
    for(int i = 0; i < (sizeof(msgArr)/sizeof(msgArr[0])); i++)
    {
        outmsg = outmsg + msgArr[i];
    };
    return outmsg;
};

int main()
{
    string mode;
    string msg;
    cout << "Encryption Program" << endl;
    cout << "Would you like to encrypt or decrypt?" << endl;
    cin >> mode;
    if (mode == "encrypt" || mode == "Encrypt" || mode == "ENCRYPT" || mode == "1")
    {
        cout << "Encryption. ENTER MSG HERE: ";
        cin >> msg;
        cout << encryptMsg(msg);
    } else if (mode =="decrypt" || mode == "Decrypt" || mode == "DECRYPT" || mode == "2")
    {
        cout << "Decryption. ENTER MSG HERE: ";
        cin >> msg;
        cout << decryptMsg(msg);
    };
    return 0;
}

Thank you.

You have a number of potential problems reading data with cin . If any of your input contains whitespace (intentional or unintentional), your code breaks. (they same occurs if you use a type that doesn't consume leading whitespace, such as char ) Better to use line-oriented input such as getline to read user input to insure your '\\n' generated by pressing Enter is read and discarded.

Your code lacks any meaningful validation. You must validate all user input to insure there were no stream errors encountered, the user didn't cancel input by generating a manual EOF with Ctrl+C (or Ctrl+Z on windows -- but see: CTRL+Z does not generate EOF in Windows 10 )

Further, if you are reading digits into a string you will rely on for encryption, you need to validate that each character read into codekey was in fact a digit. (the functions in <cctype> , like isdigit() can help).

As explained in the comments char msgArr[msg.length()]; is wrong. The C++ standard does not include Variable Length Arrays (VLA's) like the C standard does. gcc offers VLA's as an extension to the standard but that makes your code non-portable.

If you simply want to encrypt the characters in msg in-place, there is no need for any other string or storage in encryptMsg -- just add your digit to the character in msg in place. For example, you could do something as simple as the following to encrypt msg in-place:

string encryptMsg(string& msg)
{
    string codekey;             /* string codekey, result */
    const char *k;              /* pointer to chars in codekey */

    cout << "Enter a number that is " << msg.length() << " digits long: ";
    if (!getline (cin, codekey)) {          /* read codekey */
        cerr << "error: invalid input - codekey\n";
        exit (EXIT_FAILURE);
    }
    if (codekey.length() < msg.length()) {  /* validate codekey length */
        cerr << "error: insufficient number of digits entered.\n";
        exit (EXIT_FAILURE);
    }
    k = codekey.c_str();        /* initialize k to 1st char in codekey */
    for (char& c : msg) {       /* loop over each char in msg */
        if (!isdigit(*k)) {     /* validate char is a digit */
            cerr << "error: non-numeric input '" << *k << "'\n";
            exit (EXIT_FAILURE);
        }
        c = c + (*k++ - '0');   /* add digit val to c, encrypting msg */
    }
    return msg;                 /* return encrypted result */
}

To preserve msg , you can simply declare outmsg as a string as well and assign outmsg = msg; and then encrypt the characters in outmsg with the digits entered in codekey , eg

string encryptMsg(string& msg)
{
    string codekey, outmsg = msg;   /* string codekey, outmsg */
    const char *k;                  /* pointer to chars in codekey */

    cout << "Enter a number that is " << msg.length() << " digits long: ";
    if (!getline (cin, codekey)) {          /* read codekey */
        cerr << "error: invalid input - codekey\n";
        exit (EXIT_FAILURE);
    }
    if (codekey.length() < msg.length()) {  /* validate codekey length */
        cerr << "error: insufficient number of digits entered.\n";
        exit (EXIT_FAILURE);
    }
    k = codekey.c_str();        /* initialize k to 1st char in codekey */
    for (char& c : outmsg) {    /* loop over each char in msg */
        if (!isdigit(*k)) {     /* validate char is a digit */
            cerr << "error: non-numeric input '" << *k << "'\n";
            exit (EXIT_FAILURE);
        }
        c += (*k++ - '0');   /* add digit val to c, encrypting msg */
    }
    return outmsg;           /* return encrypted outmsg */
}

Otherwise, C++ provides for simple allocation with new and delete , or you can simply use a string for codekey -- but then you will need an iterator to help iterate over the characters in codekey while simultaneously iterating over the characters in msg . It's up to you, but in these cases I find a simple allocation for the resulting message and using a simple character pointer to fill the encrypted string before assigning to a string to return is about as easy as anything else, eg

string encryptMsg(string& msg)
{
    char *tmp = new char[msg.length() + 1], /* allocate for length + 1 */
        *p = tmp;                           /* pointer to tmp */
    const char *k;                          /* pointer to use for key */
    string codekey, res;                    /* string codekey, result */

    cout << "Enter a number that is " << msg.length() << " digits long: ";
    if (!getline (cin, codekey)) {          /* read codekey */
        cerr << "error: invalid input - codekey\n";
        exit (EXIT_FAILURE);
    }
    if (codekey.length() < msg.length()) {  /* validate codekey length */
        cerr << "error: insufficient number of digits entered.\n";
        exit (EXIT_FAILURE);
    }
    k = codekey.c_str();        /* initialize k to 1st char in codekey */
    for (char& c : msg) {       /* loop over each char in msg */
        if (!isdigit(*k)) {     /* validate char is a digit */
            cerr << "error: non-numeric input '" << *k << "'\n";
            exit (EXIT_FAILURE);
        }
        *p++ = c + (*k++ - '0');    /* add digit val to c, store in tmp */
    }
    *p = 0;         /* nul-termiante tmp */
    res = tmp;      /* assign char array to string res */
    delete[] tmp;   /* free allocated memory */
    return res;     /* return encrypted result */
}

You can put a short example program together to validate the encrypt to insure it is doing what you intend it to do. Below, we enter "hello" as msg , encrypt and use "11111" as codekey to get the intended "ifmmp" returned by encryptMsg , eg

#include <iostream>
#include <string>
#include <cctype>
#include <limits>

using namespace std;

string encryptMsg(string& msg)
{ ... }

int main (void) {

    string mode, msg;

    cout << "mode: ";
    if (!getline (cin, mode)) { /* read mode (discarding trailing '\n') */
        cerr << "error: invalid input - mode\n";
        return 1;
    }
    for (char& c : mode)        /* convert mode to lowercase */
        c = tolower(c);
    if (mode == "encrypt" || mode == "1") { /* check mode */
        cout << "msg : ";           /* prompt for msg */
        if (!getline (cin, msg)) {  /* read msg */
            cerr << "error: invalid input - msg\n";
            return 1;
        }
        /* output encrypted result */
        cout << "res : " << encryptMsg(msg) << '\n';
    }
}

( note: all functions generate the same output, but in the final two msg is preserved unchanged)

Compile With Warnings Enabled

For all code you compile, you want to compile with Warnings Enabled , for gcc/g++ and clang, you can use -Wall -Wextra -pedantic for a fairly inclusive set of warnings, clang also offers -Weverything . VS ( cl.exe ) uses /W# where # is 1-4 , it also offers /Wall (which really means all), and you can disable specific warnings you don't want reported with /w#### where #### is the code for the warning to disable. Do not accept code until it compiles without warning.

Read an understand any warnings you get, they point out specific problems and the line on which the problem can be found. (g++ goes a bit overboard in producing a plethora of messages, but still, they identify the problem and line). You can learn a lot by listening what your compiler is trying to tell you.

Example Use/Output

$ ./bin/asciiencrypt3
mode: EnCRypt
msg : hello
Enter a number that is 5 digits long: 11111
res : ifmmp

Since this looks a lot like an assignment, you can tackle the remainder of the implementation from here. If you run into problems, add your updated code below your existing question , and I'm happy to help further.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM