我正在寻找一个类似的方法(使用Caesar Cipher对消息进行加密,由用户输入并显示):
void encrypt(char *message, int shift);
我的代码:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <string.h>
char num(char c)
{
const char upper_alph[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'};
const char lower_alph[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'};
if(isupper(c)) {
for(int i = 0; i < 26; i++)
if(upper_alph[i] == c)
return i;
} else {
for(int i = 0; i < 26; i++)
if(lower_alph[i] == c)
return i;
}
return 0;
}
void encrypt(char *message, int shift)
{
int i = 0;
const char upper_alph[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'};
const char lower_alph[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'};
while(message[i] != NULL)
{
if(isalpha(message[i]))
{
if(isupper(message[i])) {
printf("%c", upper_alph[(num(message[i])+shift)%26]);
} else {
printf("%c", lower_alph[(num(message[i])+shift)%26]);
}
} else {
printf("%c", message[i]);
}
i++;
}
}
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
int main()
{
//reverse();
//printf("\n\n");
int rc;
char mes[1024];
int sh = 0;
rc = getLine ("Enter message to be encrypted: ", mes, sizeof(mes));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", mes);
return 1;
}
encrypt(mes, 1);
fflush(stdin);
getchar();
return 0;
}
感谢任何帮助或尝试提供帮助的人。
:)
编辑:做了很多更正。仍然没有工作:/EDIT2:做了很多更正。获取访问冲突@“while(* message!='\ 0')”
EDIT3:将上面的代码更新为工作代码。谢谢大家的帮助!
答案 0 :(得分:2)
它不起作用,因为您没有为mes
分配内存:
char mes[512]; // Enough space!
使用std::string
更容易:
string mes;
int sh = 0;
cout << "Enter message to be encrypted: " << endl;
getline(cin, mes);
cout << "Enter a shift amount (1-25): " << endl;
cin >> sh;
encrypt(mes, sh);
将encrypt
功能更改为:
void encrypt(const string &message, int shift)
让你的角色保持在范围内:
upper_alph[(num(message[i])+shift)%26]
lower_alph[(num(message[i])+shift)%26]
答案 1 :(得分:2)
一个问题是你永远不会四处走动。考虑一下你是否通过任何正移位传递了像'Z'或'z'这样的东西,那么你只会在数组之外增加。
您需要执行以下操作:
upper_alph[(num(message[i])+shift)%26]
and
lower_alph[(num(message[i])+shift)%26]
您还需要为mes
分配内存:
char mes[1024];
我相信您的scanf
也不正确(c
是一个字符,s
是一个字符串):
scanf("%s", mes);
然而,使用%s
只能在获得空白区域之前阅读,更好的选择可能是使用getline()
读取整行。
答案 2 :(得分:2)
这些行上会出现“索引越界”错误:
if(isupper(message[i])) {
printf("%c", upper_alph[num(message[i])+shift]);
} else {
printf("%c", lower_alph[num(message[i])+shift]);
}
您需要提前计算索引,并确保它在0到25之间:
int shiftedIndex = (num(message[i]) + shift) % 26;
您是否知道您的代码仅适用于英语作为输入语言?
答案 3 :(得分:2)
这里存在一个基本问题,即OP不理解。也就是说,对于计算机来说,字母只是数字。我们这些人为这些数字赋予了意义,我们甚至无法确定哪些数字意味着什么(请参阅有关问题的评论,如ASCII,EBDIC和Unicode)。
Here is a table显示ASCII标准如何将数字映射到字母。
请注意,字符'a'是97,'b'是98,'c'是99,依此类推。大写字符从65开始并从那里上升。另请注意,字母“a”和“A”位于同一行!这意味着大写字母和小写字母的低5位的位模式是相同的。最后,由于计算机只将字符视为数字,因此可以对它们进行数字运算: -
'd' - 'a' == 3
100 - 97
第二点要注意的是,数学上Caeser密码只是模数的补充: -
encoded character = (plain text character + shift) mod 26
所以现在代码可以更有效地编写: -
void Encode (char *message, int shift)
{
while (*message)
{
char c = *message;
if (isalpha (c)) // check c is a letter
{
// get the letter index: this maps 'A' to 0, 'B' to 1, etc
// it also maps 'a' to 32 (97 - 65), 'b' to 33, etc
c -= 'A';
// this is 32 for lower case characters and 0 for upper case
char case_of_c = c & 32;
// map 'a' to 'A', 'b' to 'B'
c &= 31;
// the caeser shift!
c = (c + shift) % 26;
// restore the case of the letter
c |= case_of_c;
// remap the character back into the ASCII value
c += 'A';
// save the result of the shift
*message = c;
}
++message;
}
}