c - 凯撒密码帮助,找出空格、整数和特殊字符
问题描述
我正在尝试在 C 中创建凯撒密码,但在加密和解密空格、整数和特殊字符(如!
、$
、#
等)时遇到问题。我有一个简单的代码来计算字符串部分并转换它们。任何建议都会很可爱!让我的代码变得更好的建议也会有所帮助。
这是我的代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
// Ascii codes: 'a'=97, 'b' = 98, and so on.
void encrypt()
{
char message[500], c;
int i;
int key;
printf("Enter a message to encrypt: ");
scanf("%s", &message);
printf("Enter key: ");
scanf("%d", &key);
for (i = 0; message[i] != '\0'; i++) {
c = message[i];
if (c >= 'a' && c <= 'z') {
c = c + key;
if (c > 'z') {
c = c - 'z' + 'a' - 1;
}
message[i] = c;
} else if (c >= 'A' && c <= 'Z') {
c = c + key;
if (c > 'Z') {
c = c - 'Z' + 'A' - 1;
}
message[i] = c;
}
}
printf("Encrypted message: %s", message);
}
void decrypt()
{
char message[500], c;
int i;
int key;
printf("Enter a message to decrypt: ");
scanf("%s", &message);
printf("Enter key: ");
scanf("%d", &key);
for (i = 0; message[i] != '\0'; i++) {
c = message[i];
if(c >= 'a' && c <= 'z') {
c = c - key;
if (c < 'a') {
c = c + 'z' - 'a' + 1;
}
message[i] = c;
} else if(c >= 'A' && c <= 'Z') {
c = c - key;
if(c < 'A') {
c = c + 'Z' - 'A' + 1;
}
message[i] = c;
}
}
printf("Decrypted message: %s", message);
}
int main()
{
encrypt();
return 0;
}
解决方案
Caesar cipher-wikipedia中描述了该算法。您已经发现值的变化将需要您考虑距离范围末端的偏移量,这很好。遇到问题的地方,在这两种情况下都是对字符的(移位)的加减key
以及随后的大于'z'
或小于的测试'a'
:
c = c + key;
if (c > 'z') {
和
c = c - key;
if (c < 'a') {
如果添加或减去key
(移位值)不会导致值大于'z'
或小于'a'
,(并且不能保证它们会或不会基于key
大小),则您根本不会应用任何编码或解码,除非您的条件测试为真。
该算法要求(x + n)
or(x - n)
结果必须介于 之间0 - 25
。(请参阅链接中的算法)这是% 26
用于防止值超过时的方法25
,但您还必须确保该值是非负的。您可以通过添加和加上一点代数来满足这个要求,26
从而得出一个涵盖所有情况的表达式(一个代表大写,一个代表小写)。例如:
#define SIZE 26
...
int encipher (int c, int shift)
{
if ('A' <= c && c <= 'Z')
/*
* c = 'A' + (c - 'A' + 'Z' - shift + 1 - 'A') % SIZE;
* c = 'A' + (c - 'A' - shift + 'Z' - 'A' + 1) % SIZE;
* where ('Z' - 'A' + 1 == SIZE)
*/
c = 'A' + (c - 'A' - shift + SIZE) % SIZE;
else if ('a' <= c && c <= 'z')
c = 'a' + (c - 'a' - shift + SIZE) % SIZE;
return c;
}
和解码:
int decipher (int c, int shift)
{
if ('A' <= c && c <= 'Z')
/*
* c = 'A' + (c - 'A' - ('Z' - shift + 1 - 'A')) % SIZE;
* c = 'A' + (c - 'A' - 'Z' + shift - 1 + 'A') % SIZE;
* c = 'A' + (c - 'Z' + shift - 1) % SIZE;
* where (c - 'Z' < 0) for (shift - 1 < SIZE)
*/
c = 'A' + (c - 'Z' + shift - 1 + SIZE) % SIZE;
else if ('a' <= c && c <= 'z')
c = 'a' + (c - 'z' + shift - 1 + SIZE) % SIZE;
return c;
}
添加一个简短的示例,允许您输入班次(您的key
)和要编码和解码的文本(最多 1024 个字符,1023 + 空字符),您可以这样做:
#include <stdio.h>
#include <string.h>
#define SIZE 26
#define MAXC 1024
int encipher (int c, int shift)
{
if ('A' <= c && c <= 'Z')
/*
* c = 'A' + (c - 'A' + 'Z' - shift + 1 - 'A') % SIZE;
* c = 'A' + (c - 'A' - shift + 'Z' - 'A' + 1) % SIZE;
* where ('Z' - 'A' + 1 == SIZE)
*/
c = 'A' + (c - 'A' - shift + SIZE) % SIZE;
else if ('a' <= c && c <= 'z')
c = 'a' + (c - 'a' - shift + SIZE) % SIZE;
return c;
}
int decipher (int c, int shift)
{
if ('A' <= c && c <= 'Z')
/*
* c = 'A' + (c - 'A' - ('Z' - shift + 1 - 'A')) % SIZE;
* c = 'A' + (c - 'A' - 'Z' + shift - 1 + 'A') % SIZE;
* c = 'A' + (c - 'Z' + shift - 1) % SIZE;
* where (c - 'Z' < 0) for (shift - 1 < SIZE)
*/
c = 'A' + (c - 'Z' + shift - 1 + SIZE) % SIZE;
else if ('a' <= c && c <= 'z')
c = 'a' + (c - 'z' + shift - 1 + SIZE) % SIZE;
return c;
}
int main (void) {
int n = 0, shift;
char text[MAXC],
encode[sizeof text],
decode[sizeof text];
fputs ("enter shift: ", stdout); /* just use text for both inputs */
if (!fgets (text, MAXC, stdin))
return 1;
if (sscanf (text, "%d", &shift) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
fputs ("\ninput : ", stdout);
if (!fgets (text, MAXC, stdin))
return 0;
text[strcspn(text, "\n")] = 0; /* trim trailing \n */
do /* encode text */
encode[n] = encipher(text[n], shift);
while (text[n++]);
n = 0;
do /* decode encoded text */
decode[n] = decipher(encode[n], shift);
while (encode[n++]);
printf ("encode: %s\ndecode: %s\n", encode, decode);
}
(注意:在加密的实践中,编码很少表示为以 nul 结尾的字符串。这里由于结果仅限于 ASCII 字符,这便于输出并且适合练习,但通常您只会存储编码值和字符数的计数)
示例使用/输出
用字母检查大写和小写:
$ ./bin/ceasar_cipher
enter shift: 3
input : ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz
encode: XYZABCDEFGHIJKLMNOPQRSTUVW xyzabcdefghijklmnopqrstuvw
decode: ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz
检查维基百科示例:
$./bin/ceasar_cipher
enter shift: 3
input : THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
encode: QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD
decode: THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
如果您还有其他问题,请仔细查看并告诉我。
推荐阅读
- perl - Perl 问题。需要一种方法来替换同一行上的两个变量
- reactjs - 当其中一些必须是全宽时,如何在具有 2 列的反应原生 FlatList 中呈现项目
- mongodb - 从 Scala 中的 mongoDB 读取
- python - 字符串 '\' 替换为 '/'
- python - 使用 Python 类在属性更新时触发程序终止
- javascript - 第一次安装组件后 componentDidUpdate 未触发(React)
- ios - 技术上是否可以截取 iOS 音频以添加 DSP 声音过滤?
- python - ValueError:logits 和标签必须具有相同的形状 ((None, 14) vs (None, 1))
- mysql - 计算 mysql group 上未重复的元素
- spring - 弹簧和不同的方式来避免使用新的