需要帮助调试我的 C++ 编程(文本 ascii 操作)
need help on debugging my c++ programming (text ascii manupulation)
我最近做了一个C++程序,它基于vigenere密码技术对文本进行加密。
我认为加密部分工作正常,但在某些情况下解密功能似乎无法输出正确答案。我希望是否有人可以查看代码并告诉我它有什么问题。
命令对话框:
输入加密密钥:
魔法
输入1号信息:
我喜欢 C 编程
消息加密:
u rwxq i rdomzcymovi
解密:
我爱 c pXogramming
在这种情况下,它以某种方式输出了 "X" 而不是 "r" ...............
代码如下:
Secret.h:
#ifndef CPP_TUTORIALS_SECRET_H
#define CPP_TUTORIALS_SECRET_H
#include <iostream>
using namespace std;
class Secret {
private:
string message;
string key;
bool toEncrypt;
bool toDecrypt;
public:
bool isToDecrypt() const {
return toDecrypt;
}
Secret(const string &message = "", const string &key = "", bool toEncrypt = false);
~Secret();
void setToDecrypt(bool toDecrypt);
void encrypt();
void decrypt();
void display();
};
#endif //CPP_TUTORIALS_SECRET_H
Secret.cpp
#include "Secret.h"
Secret::Secret(const string &message, const string &key, bool toEncrypt) {
Secret::message = message;
Secret::key = key;
Secret::toEncrypt = toEncrypt;
}
Secret::~Secret(){
}
void Secret::setToDecrypt(bool toDecrypt) {
Secret::toDecrypt = toDecrypt;
}
void Secret::display() {
cout << message << endl;
}
void Secret::encrypt() {
if(toEncrypt) {
int keyAscii[key.length()];
int count = 0;
for(unsigned int i = 0; i < key.length(); i++) {
keyAscii[i] = key.at(i);
}
for(unsigned int i = 0; i < message.length(); i++) {
if (message.at(i) > 64 && message.at(i) < 91) {
message.at(i) = (char)((message.at(i) - 65 + (keyAscii[count] - 97)) % 26 + 97);
}
else if (message.at(i) > 96 && message.at(i) < 123) {
message.at(i) = (char)((message.at(i) - 97 + (keyAscii[count] - 97)) % 26 + 97);
}
else{
message.at(i) = message.at(i);
}
count++;
if(count == key.length()) {
count = 0;
}
}
}
}
void Secret::decrypt() {
if(toDecrypt) {
int keyAscii[key.length()];
int count = 0;
for(unsigned int i = 0; i < key.length(); i++) {
keyAscii[i] = key.at(i);
}
for(unsigned int i = 0; i < message.length(); i++) {
if (message.at(i) > 96 && message.at(i) < 123) {
message.at(i) = (char)((message.at(i) - 97) % 26 - (keyAscii[count] - 97) + 97);
}
else {
message.at(i) = message.at(i);
}
count++;
if (count == key.length()) {
count = 0;
}
}
}
}
main.cpp
#include <limits>
#include "Secret.h"
void calcMsgAmount(int &pArraySize);
void inputKey(string &key);
void encryptMsg(Secret &secret, string &msg, const string &key, bool toEncrypt, int index);
int main() {
int arraySize;
string key;
string msg;
calcMsgAmount(arraySize);
inputKey(key);
Secret secrets[arraySize];
for(int i = 0; i < arraySize; i++){
encryptMsg(secrets[i], msg, key, true, i);
}
cout << endl << "Message encrypted: " << endl;
for(Secret i: secrets){
i.display();
i.setToDecrypt(true);
if(i.isToDecrypt()){
i.decrypt();
cout << endl << "Decrypted: " << endl;
i.display();
}
cout << endl << endl;
}
return 0;
}
void calcMsgAmount(int &pArraySize) {
cout << "Enter the amount of messages you want to input: " << endl;
while(!(cin >> pArraySize)){
cout << endl << "There's something really wrong with your input, please enter again." << endl;
cout << "Enter the amount of messages you want to input: " << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
void inputKey(string &key){
cout << "Enter the key for encrytion: " << endl;
cin.ignore();
getline(cin, key);
}
void encryptMsg(Secret &secret, string &msg, const string &key, bool toEncrypt, int index){
cout << "Enter message No. " << index + 1 << ": " << endl;
getline(cin, msg);
secret = Secret(msg, key, toEncrypt);
secret.encrypt();
}
非常感谢
根据wikipediaVigenere Cipher的解密例程是
(C - K) mod 26
你在Secret::decrypt()
中写的是
message.at(i) = (char)((message.at(i) - 97) % 26 - (keyAscii[count] - 97) + 97);
即C % 26 - K
。
我把行改成了
message.at(i) = (char)((26 + (message.at(i) - 97) - (keyAscii[count] - 97)) % 26 + 97);
看来是对的。我还没有真正理解为什么前 26 个是必需的,但是没有它代码就不起作用(带有 % 和负数的东西)
P.S。至于调试部分,你可能已经注意到,who 字母显示为错误的大写字母,它们的 ascii 码更小,所以你解密例程中有负数。之后你根据维基百科检查你的代码:)
问题来自两个问题的解密:
- 首先是计算应该与加密对称,即消息的模 26 - 密钥(正如 effenok 已经指出的那样)
- 第二个是,在解密中你可以在 char 级别,message-key 可以是负数,这可能不会给你以 26 为模的预期结果(例如 -2 % 26 是 -2 这样你就超出您预期的字母范围)。简单的技巧是在进行模运算之前加 26,以确保它是在正数上完成的。
这里的函数稍微紧凑一些,大小写的区别:
void Secret::encrypt() {
if(toEncrypt) {
for(unsigned int i = 0; i < message.length(); i++) {
if(isalpha(message[i])){
char start = isupper(message[i]) ? 'A' : 'a';
message[i] = (message[i] - start + (tolower(key[i%key.length()]) - 'a') + 26) % 26 + start;
}
}
}
}
void Secret::decrypt() {
if(toDecrypt) {
for(unsigned int i = 0; i < message.length(); i++) {
if (isalpha(message[i]) ){
char start = isupper(message[i]) ? 'A':'a';
message[i] = (message[i] - start - (tolower(key[i%key.length()]) - 'a') + 26) % 26 + start;
}
}
}
}
我最近做了一个C++程序,它基于vigenere密码技术对文本进行加密。
我认为加密部分工作正常,但在某些情况下解密功能似乎无法输出正确答案。我希望是否有人可以查看代码并告诉我它有什么问题。
命令对话框:
输入加密密钥: 魔法
输入1号信息: 我喜欢 C 编程
消息加密: u rwxq i rdomzcymovi
解密: 我爱 c pXogramming
在这种情况下,它以某种方式输出了 "X" 而不是 "r" ...............
代码如下:
Secret.h:
#ifndef CPP_TUTORIALS_SECRET_H
#define CPP_TUTORIALS_SECRET_H
#include <iostream>
using namespace std;
class Secret {
private:
string message;
string key;
bool toEncrypt;
bool toDecrypt;
public:
bool isToDecrypt() const {
return toDecrypt;
}
Secret(const string &message = "", const string &key = "", bool toEncrypt = false);
~Secret();
void setToDecrypt(bool toDecrypt);
void encrypt();
void decrypt();
void display();
};
#endif //CPP_TUTORIALS_SECRET_H
Secret.cpp
#include "Secret.h"
Secret::Secret(const string &message, const string &key, bool toEncrypt) {
Secret::message = message;
Secret::key = key;
Secret::toEncrypt = toEncrypt;
}
Secret::~Secret(){
}
void Secret::setToDecrypt(bool toDecrypt) {
Secret::toDecrypt = toDecrypt;
}
void Secret::display() {
cout << message << endl;
}
void Secret::encrypt() {
if(toEncrypt) {
int keyAscii[key.length()];
int count = 0;
for(unsigned int i = 0; i < key.length(); i++) {
keyAscii[i] = key.at(i);
}
for(unsigned int i = 0; i < message.length(); i++) {
if (message.at(i) > 64 && message.at(i) < 91) {
message.at(i) = (char)((message.at(i) - 65 + (keyAscii[count] - 97)) % 26 + 97);
}
else if (message.at(i) > 96 && message.at(i) < 123) {
message.at(i) = (char)((message.at(i) - 97 + (keyAscii[count] - 97)) % 26 + 97);
}
else{
message.at(i) = message.at(i);
}
count++;
if(count == key.length()) {
count = 0;
}
}
}
}
void Secret::decrypt() {
if(toDecrypt) {
int keyAscii[key.length()];
int count = 0;
for(unsigned int i = 0; i < key.length(); i++) {
keyAscii[i] = key.at(i);
}
for(unsigned int i = 0; i < message.length(); i++) {
if (message.at(i) > 96 && message.at(i) < 123) {
message.at(i) = (char)((message.at(i) - 97) % 26 - (keyAscii[count] - 97) + 97);
}
else {
message.at(i) = message.at(i);
}
count++;
if (count == key.length()) {
count = 0;
}
}
}
}
main.cpp
#include <limits>
#include "Secret.h"
void calcMsgAmount(int &pArraySize);
void inputKey(string &key);
void encryptMsg(Secret &secret, string &msg, const string &key, bool toEncrypt, int index);
int main() {
int arraySize;
string key;
string msg;
calcMsgAmount(arraySize);
inputKey(key);
Secret secrets[arraySize];
for(int i = 0; i < arraySize; i++){
encryptMsg(secrets[i], msg, key, true, i);
}
cout << endl << "Message encrypted: " << endl;
for(Secret i: secrets){
i.display();
i.setToDecrypt(true);
if(i.isToDecrypt()){
i.decrypt();
cout << endl << "Decrypted: " << endl;
i.display();
}
cout << endl << endl;
}
return 0;
}
void calcMsgAmount(int &pArraySize) {
cout << "Enter the amount of messages you want to input: " << endl;
while(!(cin >> pArraySize)){
cout << endl << "There's something really wrong with your input, please enter again." << endl;
cout << "Enter the amount of messages you want to input: " << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
void inputKey(string &key){
cout << "Enter the key for encrytion: " << endl;
cin.ignore();
getline(cin, key);
}
void encryptMsg(Secret &secret, string &msg, const string &key, bool toEncrypt, int index){
cout << "Enter message No. " << index + 1 << ": " << endl;
getline(cin, msg);
secret = Secret(msg, key, toEncrypt);
secret.encrypt();
}
非常感谢
根据wikipediaVigenere Cipher的解密例程是
(C - K) mod 26
你在Secret::decrypt()
中写的是
message.at(i) = (char)((message.at(i) - 97) % 26 - (keyAscii[count] - 97) + 97);
即C % 26 - K
。
我把行改成了
message.at(i) = (char)((26 + (message.at(i) - 97) - (keyAscii[count] - 97)) % 26 + 97);
看来是对的。我还没有真正理解为什么前 26 个是必需的,但是没有它代码就不起作用(带有 % 和负数的东西)
P.S。至于调试部分,你可能已经注意到,who 字母显示为错误的大写字母,它们的 ascii 码更小,所以你解密例程中有负数。之后你根据维基百科检查你的代码:)
问题来自两个问题的解密:
- 首先是计算应该与加密对称,即消息的模 26 - 密钥(正如 effenok 已经指出的那样)
- 第二个是,在解密中你可以在 char 级别,message-key 可以是负数,这可能不会给你以 26 为模的预期结果(例如 -2 % 26 是 -2 这样你就超出您预期的字母范围)。简单的技巧是在进行模运算之前加 26,以确保它是在正数上完成的。
这里的函数稍微紧凑一些,大小写的区别:
void Secret::encrypt() {
if(toEncrypt) {
for(unsigned int i = 0; i < message.length(); i++) {
if(isalpha(message[i])){
char start = isupper(message[i]) ? 'A' : 'a';
message[i] = (message[i] - start + (tolower(key[i%key.length()]) - 'a') + 26) % 26 + start;
}
}
}
}
void Secret::decrypt() {
if(toDecrypt) {
for(unsigned int i = 0; i < message.length(); i++) {
if (isalpha(message[i]) ){
char start = isupper(message[i]) ? 'A':'a';
message[i] = (message[i] - start - (tolower(key[i%key.length()]) - 'a') + 26) % 26 + start;
}
}
}
}