编辑:这被称为凯撒密码。 我试图制作一个主要目的是加密给定(短小写)字符串的程序。它会通过将所有字母 n 空格向右移动(加密)或向左移动(解码)来实现。
这是我到目前为止所写的内容(已编辑)
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
char abc[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'};
void code(int n) {
string cadena;
cout << "Introduzca la cadena a cifrar : " << '\n';
cin >> cadena;
for (int i(0); i < cadena.length; i++) {
for (int f(0); f < strlen(abc); f++) {
if (cadena[i] == abc[f]) {
int w;
w = f + n;
if (w > strlen(abc)) {
w -= strlen(abc);
}
cadena[i] = abc[w];
}
}
}
cout << cadena << '\n';
system("pause");
}
void decode(int n) {
string cadena;
cout << "Introduzca la cadena a cifrar : " << '\n';
cin >> cadena;
for (int i(0); i < cadena.length; i++) {
for (int f(0); f < strlen(abc); f++) {
if (cadena[i] == abc[f]) {
int w;
w = f - n;
if (w < 0) {
w--;
w = strlen(abc) - w;
}
cadena[i] = abc[w];
}
}
}
cout << cadena << '\n';
system("pause");
}
int main() {
int n;
cout << "Introduzca el numero del cesar " << '\n';
cin >> n;
cout << "Desea usted cifrar o descifrar?" << '\n';
cout << "Introduzca c para cifrar o d para descifrar" << '\n';
char chos;
cin >> chos;
if (chos == 'c')
code(n);
else
decode(n);
return 0;
}
现在问题是我收到了一个糟糕的字符串,我甚至不知道它是如何形成的。还有一个错误。
答案 0 :(得分:3)
让我们先快速浏览一下代码。
char abc[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' };
这很好。它不处理大写,但是一个很好的开始
void code(int n)
{
char cadena;
定义一个孤独的角色。我们稍后会看到这不是你想要的。
char * cadena_ptr = &cadena;
在正常情况下,这是一个好主意,但只有一个字符,没那么有用
cout << "Introduzca la cadena a cifrar : " << '\n';
cin >> cadena;
这是事情开始出错的地方。由于cadena
的定义方式,代码只读了一个且只有一个字符。
for (int i(0); i <= sizeof(cadena); i++)
如前所述cadena
是一个字符,因此i <= sizeof(cadena)
与i <= 1
相同。这导致循环的2次迭代。一个用于i=0
(0<=1
),另一个用于i=1
(1<=1
)。这意味着循环将超出cadena
个字符的范围。结果未定义。程序可能崩溃。程序可能会覆盖并损坏cadena
周围的数据。程序可能会吃你邻居的猫。所有这些都是完全有效的,但前两个比第三个更有可能。
{
for (int f(0); f <= 26; f++)
这也超出了界限范围。这个循环也可能没有必要。在2017年,您不太可能看到不会将所有字符存储在升序连续块中的字符编码。也就是说,这个暴力循环消除了与乱序字符顺序混乱的遗留或bizzaro字符编码相冲突的可能性。
我会坚持使用这个循环,因为问题不是关于ASCII算法。
{
if (*cadena_ptr == abc[f])
{
int w;
w = f + n;
if (w >= 26)
{
w -= 26;
}
*cadena_ptr = abc[w];
整个块看起来很好,一旦索引问题得到解决就应该可以工作。但是有一个改进。一旦找到一场比赛,你就可以停止寻找更多。还应该更换the magic number 26的大量使用。
}
}
}
cout << cadena << '\n';
system("pause");
}
清理阶段1:
通过一个索引修复关闭。这很快:
for (int i(0); i < sizeof(cadena); i++)
{
for (int f(0); f < sizeof(abc); f++) // death to magic number!
接下来阅读多个角色:
正确的方法!使用a std::string
和range-based for
loop
void code(int n)
{
std::string cadena;
//char * cadena_ptr = &cadena; obsoleted by std::string
cout << "Introduzca la cadena a cifrar : " << '\n';
cin >> cadena;
for (char & ch:cadena)// loop through all characters in cadena
{
for (int f(0); f < sizeof(abc) ; f++)
{
if (ch == abc[f])
{
int w;
w = f + n;
if (w >= sizeof(abc))
{
w -= sizeof(abc);
}
ch = abc[w];
break;// we found it! Stop looking.
}
}
}
cout << cadena << '\n';
system("pause");
}
我不会浪费我的时间错误的方式。这是不对的。学习使用std::string
。
如果项目要求拒绝std::string
,请不要采用错误的方式。做一些完全不同的事!逐个读取字符,转换它们并打印它们。要加密直到找到无法转换的字符,我们可以执行以下操作:
bool goodchar(char & cadena, int n)
{
for (int f(0); f < sizeof(abc) ; f++)
{
if (cadena == abc[f])
{
int w;
w = f + n;
if (w >= sizeof(abc))
{
w -= sizeof(abc);
}
cadena = abc[w];
return true;
}
}
return false;
}
void code(int n)
{
char cadena;
cout << "Introduzca la cadena a cifrar : " << '\n';
cin >> cadena; // get first character
while (goodchar(cadena)) // keep looping until we find a character that's
// not in the list
{
cout << cadena << '\n';
cin >> cadena; // get next character
}
cout << '\n';
system("pause");
}