C语言中的Caesar Cipher在2D字符串数组中添加了额外的字符

时间:2018-12-11 22:13:53

标签: c caesar-cipher

我在堆栈溢出上看到了类似的答案,但是没有一个问题和我一样。我使用这种简单的凯撒密码加密功能的问题是,对于我的加密数组的位置[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个以上的字符,不应包含。 感谢所有反馈,包括对我的代码的糟糕程度的评论,或者此问题是否以任何方式滥用了网站。谢谢。

2 个答案:

答案 0 :(得分:1)

别生气,但是您的代码令人怀疑:)

但是,这是一个学习原因以及如何解决它的机会,因此,我将详细解释int细节:

您的代码有四个主要问题。
其中两个中断程序,并导致其打印垃圾或由于分段错误而崩溃,具体取决于程序运行时的内存布局。 另外两个让您的程序打印出正确的答案,但是却浪费了内存和处理器周期,使效率极低。
如果这是一项作业的评分依据,您将失去分数,并且如果您正在自学,这将是不好的编程习惯。

问题1:
正如注释中已经指出的那样,您必须始终使用NULL将C中的字符串终止。 如果您不这样做,那么像printf这样使用它们的函数将一直打印内存内容,直到遇到随机的NULL值或您的程序崩溃为止。

因此,在外部for循环中,您必须添加如下一行:

for (j = 0; j < 5; i++) {
    //code to do the cypher

    encrypted_string[j][5] = '\0'; //add terminator to string
}

或者,您可以按照Bwebb显示的方式初始化数组:

encrypted_string[5][6] = { '\0' };

这将提前在所有数组单元中放入零。但是,如果使用此方法,请注意不要覆盖其中一个循环中字符串的最后一个单元格!

问题2:
Bwebb也指出,您可以同时增加alphabet_countnumbers_count,但是使用numbers_count来索引较小的数组。

这意味着对于从k到z的任何字母,您的程序都将在执行第二次if检查时访问它不应接触的内存。

但是,如果您解决以下两个问题并正确构造代码,则该问题将自行消失。

问题3:
您浪费了两个大数组:字母数组和数字数组。
您不需要它们!由于正确计算了密码,因此您必须已经知道计算机中字母和数字的表示方式,因此不需要将字符串与这些数组的内容一一比较。

您知道字母是一个连续范围,因此只需使用一个if

问题4:
您浪费了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');

但是可读性是任何好的代码的重要方面。

答案 1 :(得分:0)

#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

问题在于数字索引,当字母花了十多次迭代才能找到匹配项时。我重新安排了while循环逻辑以防止超出范围的索引,这是您期望的结果吗?

编辑,我将您的代码复制/粘贴到了codechef.com/ide中以进行修复,但是我没有解决所有的格式/缩进问题。在下一次发布之前,您应该自行修复格式(对于回答您的人只是一个FYI)。