密码算法问题

时间:2021-01-08 10:45:49

标签: c++ string algorithm

任务:此密码将每个字母移动多个字母。如果移位使您越过字母表的末尾,只需旋转回到字母表的前面即可。

例如: string = "ABC Def Ghi 999 -*%/&()[]" shift(你输入的数字) = 1(可以是任意整数)

程序应该这样打印:Bcd Efg Hij -*%/&()[]

我用 void 函数做了这个,但是一旦我尝试用字符串函数做同样的事情,它就不起作用了。它只是处理字符串的第一个元素然后返回值。对于这种特殊情况 我的程序打印出来像“Bbc Def Ghi 999 -*%/&()[]”

有什么办法可以解决这个问题吗?

#include <iostream>
#include <cmath>

using namespace std;

string Cipher(string password, int shift) {
    char Uppercase[26] = { 'A','B','C' ,'D' ,'E' ,'F' ,'G' ,'H' ,'I' ,'J' ,'K' ,'L' ,'M' ,'N' ,'O','P' ,'Q' ,'R' ,'S' ,'T' ,'U' ,'V' ,'W' ,'X' ,'Y','Z' };
    char Lowercase[26] = { 'a','b','c' ,'d' ,'e' ,'f' ,'g' ,'h' ,'i' ,'j' ,'k' ,'l' ,'m' ,'n' ,'o','p' ,'q' ,'r' ,'s' ,'t' ,'u' ,'v' ,'w' ,'x' ,'y','z' };

    for (int i = 0; i < password.length(); i++) {
        for (int k = 0; k < 26; k++) {
            int add = shift + k;

            if (password[i] == Uppercase[k]) {
                for (int i = 0; add > 25; i++) { // controlling add isn't bigger than 25
                    add -= 25;
                }
                password[i] = Uppercase[add]; // converting each letter
            }
            else if (password[i] == Lowercase[k]) {
                for (int i = 0; add > 25; i++) { // controlling add isn't bigger than 25 
                    add -= 25;
                }
                password[i] = Lowercase[add]; //converting each letter
            }
            else {
                k = 25; // if element of string is different from letters, program goes to next element 
            }
        }
    }
    return password;
}

int main() {
    cout << "Please enter an integer different from 0 and multiples of 25: ";
    string password = "Abc def ghi 999 -*%/&()[]";
    int shift;
    cin >> shift;
    cout<< Cipher(password, shift);
    system("pause>0");
}

2 个答案:

答案 0 :(得分:1)

您的加密问题可以通过使用现代 C++ 的一个语句来解决。

但是因为这个有点高级,所以我会给出详细的解释。


让我们先想想,做什么,然后如何实施。


什么:

  1. 只能转换字母字符
  2. 不得以未加密的方式输出任何字母字符(与输入相同)
  3. 在加密的情况下,加密后的信件应保留原始信件的大小写。意思是,如果位置 5 是一个大写字母,那么在加密字符串中,位置 5 的字母也应该是大写的
  4. 字母应移动指定的数量。

方法:

我们将首先使用 isalpha 函数检查原始字母是否为字母。

因此,对于字母的情况,我们将检查该字母是大写还是小写。实际上,我们只检查是否是大写字母。

因为如果不是,那么它一定是小写字母(因为它肯定是一个字母,我们之前做过检查,如果不是大写,那么它就是小写)。对于此检查,我们使用 isupper 函数。

然后我们将执行轮班操作。并转换回字母,考虑到情况。

我们假设是 ASCII。如果我们要将 ASCII 字母/字符转换为基于 0 的索引,我们需要执行以下操作:

如果我们查看 ASCII 表,那么我们会看到,'A' 等于 65,依此类推。因此,为了获得从 0 开始的索引,我们从字母中减去 65。然后我们有一个介于 0 和 25 之间的索引值。

然后我们添加移位值。当然可能有溢出。但是,这可以通过模 26 除法简单地纠正。

所以:26->0、27->1、28->2 等等。相当简单。但是,因为我们想稍后再有一个字母,所以我们将在这个结果上加 65。

对于小写字母,我们将执行几乎相同的操作,但使用 97 作为字母 'a' 的偏移量。

然后,我们可以通过使用三元或 conditional 运算符将所有东西放在一个表达式中。

std::isalpha(c) ? std::isupper(c) ? (c - 65 + shift) % 26 + 65 : (c - 97 + shift) % 26 + 97 : c

这是一个简短的

    // Check if letter/character is alpha
    if (std::isalpha(c)) {

        // Now check for upper or lower case
        if (std::isupper(c)) {

            // The character is uppercase
            c = (c - 65 + shift) % 26 + 65;
        }
        else {
            // The character is lower case
            c = (c - 97 + shift) % 26 + 97;
        }
    }
    else {
        // The character is not alpha
    }

和单衬一样,没有区别

所以,首先,检查 alpha。如果为真,则检查大写,如果为真,则对大写字母进行转换,否则对小写字母进行转换。如果不是字母,则保持不变。

然后,我们将所有这些作为 Lambda 表达式嵌入到 std::transform 语句中。请参阅 here 了解说明。

整个转换过程的结果将只有一个语句:

std::transform(password.begin(), password.end(), password.begin(), [shift](const char c)
    {return std::isalpha(c) ? std::isupper(c) ? (c - 65 + shift) % 26 + 65 : (c - 97 + shift) % 26 + 97 : c; });


最后,我们构建了一个用于演示目的的小型驱动程序:

#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>

int main() {

    // Our password
    std::string password = "Abc def ghi 999 -*%/&()[]";

    // Give instruction to the user
    std::cout << "\nPlease enter a postive integer: ";

    // Get number of shifts from user and check, if the value could be read
    if (int shift{}; std::cin >> shift && shift > 0) {

        // Now do the encryption
        std::transform(password.begin(), password.end(), password.begin(), [shift](const char c)
            {return std::isalpha(c) ? std::isupper(c) ? (c - 65 + shift) % 26 + 65 : (c - 97 + shift) % 26 + 97 : c; });

        // Show the result to the user
        std::cout << "\n\nEncrypted passphrase: \t" << password << '\n';
    }
    else std::cerr << "\n\n*** Error: Problem with input!\n\n";
    return 0;
}

而且,由于单行代码可能太高级了,让我们使用明确且更冗长的代码。只是为了完成:

#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>

int main() {

    // Our password
    std::string password = "Abc def ghi 999 -*%/&()[]";

    // Give instruction to the user
    std::cout << "\nPlease enter a postive integer: ";

    // Get number of shifts from user and check, if the value could be read
    if (int shift{}; std::cin >> shift && shift > 0) {

        // --------------Can be written in one statement -----------------------
        for (char& c : password) {
            // Check if letter/character is alpha
            if (std::isalpha(c)) {

                // Now check for upper or lower case
                if (std::isupper(c)) {

                    // The character is uppercase
                    c = (c - 65 + shift) % 26 + 65;
                }
                else {
                    // The character is lower case
                    c = (c - 97 + shift) % 26 + 97;
                }
            }
            else {
                // The character is not alpha
            }
            // ------------------------------------------------------------------
        }
        // Show the result to the user
        std::cout << "\n\nEncrypted passphrase: \t" << password << '\n';
    }
    else std::cerr << "\n\n*** Error: Problem with input!\n\n";
    return 0;
}

答案 1 :(得分:0)

在 k 循环中,您确定字母在字母表中的索引。但是,当例如i=1 然后 password[1] 代表字母“b”。现在,从 k==0 开始 k 循环,其中 Uppercase[0]Lowercase[0] 分别代表 'A' 和 'a',您直接以 else 条件结束,您的k-loop 不做任何事情就终止(你设置 k=25 并增加它)。这是一个固定版本(请注意,我还使用模运算符 % 来确保 0 < add < 26:

#include <iostream>
#include <cmath>

using namespace std;

string Cipher(string password, int shift) {
    char Uppercase[26] = { 'A','B','C' ,'D' ,'E' ,'F' ,'G' ,'H' ,'I' ,'J' ,'K' ,'L' ,'M' ,'N' ,'O','P' ,'Q' ,'R' ,'S' ,'T' ,'U' ,'V' ,'W' ,'X' ,'Y','Z' };
    char Lowercase[26] = { 'a','b','c' ,'d' ,'e' ,'f' ,'g' ,'h' ,'i' ,'j' ,'k' ,'l' ,'m' ,'n' ,'o','p' ,'q' ,'r' ,'s' ,'t' ,'u' ,'v' ,'w' ,'x' ,'y','z' };

    for (int i = 0; i < password.length(); i++) {
        for (int k = 0; k < 26; k++) {
            int add = (shift + k)%26;
            if (password[i] == Uppercase[k]) {
                password[i] = Uppercase[add]; // converting each letter
                break;
            }
            else if (password[i] == Lowercase[k]) {
                password[i] = Lowercase[add]; //converting each letter
                break;
            }
        }
    }
    return password;
}

int main() {
    cout << "Please enter an integer different from 0 and multiples of 25: ";
    string password = "Abc def ghi 999 -*%/&()[]";
    int shift;
    cin >> shift;
    cout<< Cipher(password, shift);
    system("pause>0");
}
相关问题