C 中的凯撒密码向二维字符串数组添加额外字符
Caesar Cipher in C adds extra characters to 2d string array
我在堆栈溢出上看到过类似的答案,但是none遇到了和我一样的问题。这个简单的凯撒密码加密函数的问题是,对于我的加密数组的位置 [2](并且仅在位置 [2]),一个 (^3) 符号,后跟位置 [3] 处的加密字符串被连接到它。
void encryptIDS(char login_ids[5][6])
{
int i = 0;
int j = 0;
int stop = 0;
int alphabet_count = 0;
int numbers_count = 0;
char lower_case[27] = {'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'};
char numbers[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9'};
char encrypted_string[5][6];
for (j = 0; j < 5; j++)
{
for (i = 0; i < 5; i++)
{
alphabet_count = 0;
numbers_count = 0;
stop = 0;
while (stop == 0)
{
if (login_ids[j][i] == lower_case[alphabet_count])
{
encrypted_string[j][i] = ((((login_ids[j][i]-'a')+7)%26)+'a');
stop = 1;
}
else if (login_ids[j][i] == numbers[numbers_count])
{
encrypted_string[j][i] = ((((login_ids[j][i] - '0')+7)%10)+'0');
stop = 1;
}
else
{
alphabet_count++;
numbers_count++;
}
}
}
}
printf("debug : %s\n", encrypted_string[0]);
printf("debug : %s\n", encrypted_string[1]);
printf("debug : %s\n", encrypted_string[2]);
printf("debug : %s\n", encrypted_string[3]);
printf("debug : %s", encrypted_string[4]);
}
login_ids的内容是"vc136","jc580","cl274","tm361,"ns792"
将它们打印出来时,它们都很好地加密,除了麻烦的第三个 "cj803"、"qj257"、"js941^3at038"、"at038"、"uz469"
这是非常令人困惑的,因为位置 [2] 处的字符串超过 6 个字符,这是不应该的。
感谢任何和所有反馈,包括对我的代码有多糟糕的评论,或者这个问题是否以任何方式滥用网站。谢谢你。
#include <stdio.h>
void encryptIDS(char login_ids[5][6]);
int main(void) {
char login_ids[5][6] = {{"vc136"},{"jc580"},{"cl274"},{"tm361"},{"ns792"}};
encryptIDS(login_ids);
return 0;
}
void encryptIDS(char login_ids[5][6])
{
int i = 0;
int j = 0;
int stop = 0;
int alphabet_count = 0;
int numbers_count = 0;
char lower_case[27] = {'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'};
char numbers[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9'};
char encrypted_string[5][6] = {0};
for (j = 0; j < 5; j++)
{
for (i = 0; i < 5; i++)
{
alphabet_count = 0;
numbers_count = 0;
stop = 0;
while (stop == 0)
{
if (login_ids[j][i] == lower_case[alphabet_count])
{
encrypted_string[j][i] = ((((login_ids[j][i]-'a')+7)%26)+'a');
stop = 1;
}
if(numbers_count < 10)
{
if (login_ids[j][i] == numbers[numbers_count])
{
encrypted_string[j][i] = ((((login_ids[j][i] - '0')+7)%10)+'0');
stop = 1;
}
}
alphabet_count++;
numbers_count++;
}
}
}
printf("debug : %s\n", encrypted_string[0]);
printf("debug : %s\n", encrypted_string[1]);
printf("debug : %s\n", encrypted_string[2]);
printf("debug : %s\n", encrypted_string[3]);
printf("debug : %s", encrypted_string[4]);
}
输出
debug : cj803
debug : qj257
debug : js941
debug : at038
debug : uz469
问题出在数字索引上,当字母需要 10 多次迭代才能找到匹配项时。我重新安排了while循环逻辑来防止越界索引,这是你期待的结果吗?
编辑 我 copy/pasted 你的代码到 codechef 中。com/ide 来修复它,但我没有修复所有 formatting/indenting。您应该在下次发布之前自行修复格式(仅供回答您的人参考)。
不要生气,但是您的代码正如您所怀疑的那样糟糕:)
但是,这是一个了解原因以及如何修复它的机会,所以我将详细解释:
您的代码有 4 个主要问题。
其中两个会破坏程序,并会导致程序打印垃圾或因分段错误而崩溃,具体取决于程序运行时的内存布局。
其他两个让您的程序打印出正确的答案,但由于浪费内存和处理器周期而使其效率极低。
如果这是你要评分的作业,你会失去分数,如果你是自学,这是一种糟糕的编程习惯。
问题一:
正如评论中已经指出的那样,您必须始终以 NULL 终止 C 中的字符串。
如果你不这样做,像 printf
这样使用它们的函数将继续打印内存内容,直到它们遇到随机 NULL 值或直到你的程序崩溃。
所以,在你的外部 for
循环中,你必须添加这样一行:
for (j = 0; j < 5; i++) {
//code to do the cypher
encrypted_string[j][5] = '[=10=]'; //add terminator to string
}
或者,您可以按照 Bwebb 向您展示的方式初始化数组:
encrypted_string[5][6] = { '[=11=]' };
这将预先在所有数组单元格中置零。但是,如果您使用此方法,请注意不要覆盖其中一个循环中字符串的最后一个单元格![=22=]
问题二:
Bwebb 还指出,您将 alphabet_count
和 numbers_count
一起递增,但使用 numbers_count
来索引较小的数组。
这意味着对于从 k 到 z 的任何字母,您的程序将访问它在执行第二次 if
检查时不应触及的内存。
但是,如果您解决以下两个问题并正确构建代码,此问题将自行消失。
问题三:
你用两个大数组浪费内存:字母数组和数字数组。
你不需要它们!既然你正确计算了密码,你肯定已经知道字母和数字在计算机中是如何表示的,所以你不需要将你的字符串与这些数组的内容一一比较。
你知道字母是一个连续的范围,所以只用一个 if
.
问题四:
你在 while
循环上浪费了时间。
这是问题 3 中所述的同一问题的一部分 - 您不需要循环!
比较一次,看当前字符是否在字母范围内,如果不在,再比较一次,看是否在数字范围内。
如果您仅修复问题 1 和 2,您的代码将正常工作,但如果您修复问题 3 和 4,您的代码将更短且更易于阅读和理解,因此出现任何其他错误的可能性将大大降低英寸
操作方法如下:
//this is the inner loop, the outer loop over j stays the same
for (i = 0; i < 5; i++) {
//check if this is a letter - a range between a and z inclusive:
if (encrypted_string[j][i] >= 'a' && encrypted_string[j][i] <= 'z') {
encrypted_string[j][i] += 7; //encrypt through shift by 7
//rotate to beginning of alphabet if needed:
if (encrypted_string[j][i] > 'z') encrypted_string[j][i] -= 26;
} else if (/* do the same thing for numbers) {
...
}
}
请注意,我将您的加密计算分为两行:这也是为了便于阅读和理解。
您仍然可以使用原来的计算:
encrypted_string[j][i] = ((((login_ids[j][i] - 'a') + 7) % 26) + 'a');
但是可读性是任何好的代码的一个重要方面。
我在堆栈溢出上看到过类似的答案,但是none遇到了和我一样的问题。这个简单的凯撒密码加密函数的问题是,对于我的加密数组的位置 [2](并且仅在位置 [2]),一个 (^3) 符号,后跟位置 [3] 处的加密字符串被连接到它。
void encryptIDS(char login_ids[5][6])
{
int i = 0;
int j = 0;
int stop = 0;
int alphabet_count = 0;
int numbers_count = 0;
char lower_case[27] = {'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'};
char numbers[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9'};
char encrypted_string[5][6];
for (j = 0; j < 5; j++)
{
for (i = 0; i < 5; i++)
{
alphabet_count = 0;
numbers_count = 0;
stop = 0;
while (stop == 0)
{
if (login_ids[j][i] == lower_case[alphabet_count])
{
encrypted_string[j][i] = ((((login_ids[j][i]-'a')+7)%26)+'a');
stop = 1;
}
else if (login_ids[j][i] == numbers[numbers_count])
{
encrypted_string[j][i] = ((((login_ids[j][i] - '0')+7)%10)+'0');
stop = 1;
}
else
{
alphabet_count++;
numbers_count++;
}
}
}
}
printf("debug : %s\n", encrypted_string[0]);
printf("debug : %s\n", encrypted_string[1]);
printf("debug : %s\n", encrypted_string[2]);
printf("debug : %s\n", encrypted_string[3]);
printf("debug : %s", encrypted_string[4]);
}
login_ids的内容是"vc136","jc580","cl274","tm361,"ns792" 将它们打印出来时,它们都很好地加密,除了麻烦的第三个 "cj803"、"qj257"、"js941^3at038"、"at038"、"uz469" 这是非常令人困惑的,因为位置 [2] 处的字符串超过 6 个字符,这是不应该的。 感谢任何和所有反馈,包括对我的代码有多糟糕的评论,或者这个问题是否以任何方式滥用网站。谢谢你。
#include <stdio.h>
void encryptIDS(char login_ids[5][6]);
int main(void) {
char login_ids[5][6] = {{"vc136"},{"jc580"},{"cl274"},{"tm361"},{"ns792"}};
encryptIDS(login_ids);
return 0;
}
void encryptIDS(char login_ids[5][6])
{
int i = 0;
int j = 0;
int stop = 0;
int alphabet_count = 0;
int numbers_count = 0;
char lower_case[27] = {'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'};
char numbers[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9'};
char encrypted_string[5][6] = {0};
for (j = 0; j < 5; j++)
{
for (i = 0; i < 5; i++)
{
alphabet_count = 0;
numbers_count = 0;
stop = 0;
while (stop == 0)
{
if (login_ids[j][i] == lower_case[alphabet_count])
{
encrypted_string[j][i] = ((((login_ids[j][i]-'a')+7)%26)+'a');
stop = 1;
}
if(numbers_count < 10)
{
if (login_ids[j][i] == numbers[numbers_count])
{
encrypted_string[j][i] = ((((login_ids[j][i] - '0')+7)%10)+'0');
stop = 1;
}
}
alphabet_count++;
numbers_count++;
}
}
}
printf("debug : %s\n", encrypted_string[0]);
printf("debug : %s\n", encrypted_string[1]);
printf("debug : %s\n", encrypted_string[2]);
printf("debug : %s\n", encrypted_string[3]);
printf("debug : %s", encrypted_string[4]);
}
输出
debug : cj803
debug : qj257
debug : js941
debug : at038
debug : uz469
问题出在数字索引上,当字母需要 10 多次迭代才能找到匹配项时。我重新安排了while循环逻辑来防止越界索引,这是你期待的结果吗?
编辑 我 copy/pasted 你的代码到 codechef 中。com/ide 来修复它,但我没有修复所有 formatting/indenting。您应该在下次发布之前自行修复格式(仅供回答您的人参考)。
不要生气,但是您的代码正如您所怀疑的那样糟糕:)
但是,这是一个了解原因以及如何修复它的机会,所以我将详细解释:
您的代码有 4 个主要问题。
其中两个会破坏程序,并会导致程序打印垃圾或因分段错误而崩溃,具体取决于程序运行时的内存布局。
其他两个让您的程序打印出正确的答案,但由于浪费内存和处理器周期而使其效率极低。
如果这是你要评分的作业,你会失去分数,如果你是自学,这是一种糟糕的编程习惯。
问题一:
正如评论中已经指出的那样,您必须始终以 NULL 终止 C 中的字符串。
如果你不这样做,像 printf
这样使用它们的函数将继续打印内存内容,直到它们遇到随机 NULL 值或直到你的程序崩溃。
所以,在你的外部 for
循环中,你必须添加这样一行:
for (j = 0; j < 5; i++) {
//code to do the cypher
encrypted_string[j][5] = '[=10=]'; //add terminator to string
}
或者,您可以按照 Bwebb 向您展示的方式初始化数组:
encrypted_string[5][6] = { '[=11=]' };
这将预先在所有数组单元格中置零。但是,如果您使用此方法,请注意不要覆盖其中一个循环中字符串的最后一个单元格![=22=]
问题二:
Bwebb 还指出,您将 alphabet_count
和 numbers_count
一起递增,但使用 numbers_count
来索引较小的数组。
这意味着对于从 k 到 z 的任何字母,您的程序将访问它在执行第二次 if
检查时不应触及的内存。
但是,如果您解决以下两个问题并正确构建代码,此问题将自行消失。
问题三:
你用两个大数组浪费内存:字母数组和数字数组。
你不需要它们!既然你正确计算了密码,你肯定已经知道字母和数字在计算机中是如何表示的,所以你不需要将你的字符串与这些数组的内容一一比较。
你知道字母是一个连续的范围,所以只用一个 if
.
问题四:
你在 while
循环上浪费了时间。
这是问题 3 中所述的同一问题的一部分 - 您不需要循环!
比较一次,看当前字符是否在字母范围内,如果不在,再比较一次,看是否在数字范围内。
如果您仅修复问题 1 和 2,您的代码将正常工作,但如果您修复问题 3 和 4,您的代码将更短且更易于阅读和理解,因此出现任何其他错误的可能性将大大降低英寸
操作方法如下:
//this is the inner loop, the outer loop over j stays the same
for (i = 0; i < 5; i++) {
//check if this is a letter - a range between a and z inclusive:
if (encrypted_string[j][i] >= 'a' && encrypted_string[j][i] <= 'z') {
encrypted_string[j][i] += 7; //encrypt through shift by 7
//rotate to beginning of alphabet if needed:
if (encrypted_string[j][i] > 'z') encrypted_string[j][i] -= 26;
} else if (/* do the same thing for numbers) {
...
}
}
请注意,我将您的加密计算分为两行:这也是为了便于阅读和理解。
您仍然可以使用原来的计算:
encrypted_string[j][i] = ((((login_ids[j][i] - 'a') + 7) % 26) + 'a');
但是可读性是任何好的代码的一个重要方面。