加密给定的文本字符串 - 凯撒密码 [关闭]
Posted
技术标签:
【中文标题】加密给定的文本字符串 - 凯撒密码 [关闭]【英文标题】:Encrypting a given string of text - Caesar cipher [closed] 【发布时间】:2017-02-18 19:42:32 【问题描述】:编辑:这被称为凯撒密码。 我试图制作一个主要目的是加密给定(短小写)字符串的程序。它将通过将所有字母 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;
现在的问题是我得到了一个糟糕的字符串,我什至不知道它是如何形成的。还有一个错误。
This is the result
【问题讨论】:
如果您不需要使用 char 数组,请考虑使用std::string
和 std::rotate
。
sizeof(cadena)
为 1。i <= sizeof(cadena);
将运行 2 次迭代。 f <= 26
将运行 27 次迭代
看起来您正在尝试创建Caesar cipher。你能确认你的最终目标是什么吗?我认为您不必旋转任何东西。
大概您希望cadena
的类型为std::string
而不是char
,对吧?
另外,一旦你将cadena
设为std::string
,你希望你的外循环类似于for (std::size_t i = 0; i < cadena.size(); ++i)
。
【参考方案1】:
让我们先快速浏览一下代码。
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
s 个字符的范围。这个结果是不确定的。程序可能会崩溃。程序可能会覆盖和损坏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");
清理第一阶段:
通过一个索引修复关闭。这很快:
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");
【讨论】:
我向上帝发誓。我从来没有想过这么棒的人能够居住在互联网上。非常感谢你!我确实计划使用字符串(我什至将它包含在标题中),但是当您说“我们找到它,停止查找”时,它并没有真正完成工作。我的意思是,文本字符串具有不同的字符,这些字符具有不同的值,反过来又具有不同的新值,所以我不太明白你的意思......我会在早上编辑程序并告诉你更多关于它的信息。谢谢!! @杂水坝有两个循环。外部循环遍历字符串中的所有字符。你是对的。你希望它继续下去。内部循环检查来自外部循环的字符ch
与abc
中的每个字符。 abc
中没有重复,因此只要ch
匹配abc
的元素,就无需检查ch
和abc
。 The break
statement 提前退出内循环,但不退出外循环。
另一个说明。由于abc
的排序很好,您可以use std::find
to perform a high-speed search for you。以上是关于加密给定的文本字符串 - 凯撒密码 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章