【问题标题】:Caesar's Cipher Code凯撒密码
【发布时间】:2011-12-11 10:34:37
【问题描述】:
#include <stdio.h>

void caesar (char cipher[], int shift);

int main () {

char cipher[50];
int shift;

  printf("Enter text to be encrypted IN CAPITAL LETTERS ONLY: ");
  scanf("%s", cipher);

  printf("How many shifts do you prefer? 1-10 only: ");
  scanf("%d", &shift);

  caesar (cipher, shift);

  return 0;
}

void caesar (char cipher[], int shift) {
  int i = 0;

  while (cipher[i] != '\0') {
    if ((cipher[i] += shift) >= 65 && (cipher[i] += shift) <= 90) {
      cipher[i] += (shift);
    } else {
      cipher[i] += (shift - 25); 
    }
    i++;
  }
  printf("%s", cipher);
}

我开始获得加密输出,但我担心我的陈述有问题。

例如:

  • 输入:ABCD,1 班
  • 输出:DEFG

【问题讨论】:

    标签: c string


    【解决方案1】:

    改变

    if ((cipher[i] += shift) >= 65 && (cipher[i] += shift) <= 90) ...
    

    if ((cipher[i] + shift) >= 65 && (cipher[i] + shift) <= 90) ...
    

    因为+= 修改了cipher[i]

    【讨论】:

      【解决方案2】:

      (我是通过 http://codereview.stackexchange.com 来到这里的,所以我仍然戴着代码审查的帽子)。

      对于处理字母的代码,我发现如果它在源代码中使用实际字母而不是数字代码更容易理解。 所以我建议改变

        cipher[i] += (shift - 25); 
      

      类似

        cipher[i] += (shift - ('Z' - 'A')); 
      

      大多数做凯撒密码的人转换字母,并通过标点符号、数字、空格等保持不变。 您可以考虑包含标准字符库

      #include <ctype.h>
      

      并使用函数 isalpha()、islower()、isupper() -- 特别是改变

      if ((cipher[i]) >= 'A' && (cipher[i]) <= 'Z') {
      

      类似

      if (isupper(cipher[i])) {
      

      .

      【讨论】:

        【解决方案3】:
        void caesar (char cipher[], int shift) {
          int i = 0;
        
          while (cipher[i] != '\0') {
            if (cipher[i] >= 'A' && cipher[i]<='Z') {
                char newletter = cipher[i] - 'A';
                newletter += shift;
                newletter = newletter % 26;
                cipher[i] = newletter + 'A';
            }
            i++;
          }
          printf("%s", cipher);
        }
        

        这将忽略任何不是大写字母的内容。

        如果字母的代码为 0-25,则进行移位将非常容易,因为我们可以仅使用 26 的余数来保存条件。 这就是我所做的,我减去'A',所以A字母将为0,然后我添加移位并计算余数,这样如果你将1加到'Z',你会得到'A'再等等。 最后我不得不再次添加“A”,因为在 ASCII 中,“A”并不是真正的 0。

        【讨论】:

          【解决方案4】:

          尝试替换

          if ((cipher[i] += shift) >= 65 && (cipher[i] += shift) <= 90) {
            cipher[i] += (shift);
           } else {
            cipher[i] += (shift - 25); 
           }
          

          if ((cipher[i] += shift) >= 65 && (cipher[i] = shift) <= 90) {
           // do nothing
           } else {
            cipher[i] = 'A' + ('Z' - cipher[i]) -1; 
           }
          

          使用“+=”将在评估时修改值。 这在您的代码中被评估了 3 次,这就是它提供 3 个班次的原因!

          【讨论】:

            【解决方案5】:

            小型工作版本,除负值外无移位范围:

            #include <stdio.h>
            
            void caesar (char cipher[], int shift);
            
            int main () {
            
              char cipher[50];
              int shift;
            
              printf("Plaintext (Caps only): ");
              scanf("%s", cipher);
            
              printf("Shift: ");
              scanf("%d", &shift);
            
              caesar (cipher, shift);
            
              return 0;
            }
            
            void caesar (char cipher[], int shift) {
            
              for(int i=0; cipher[i] != '\0'; i++)
                cipher[i] = 65 + (cipher[i]-65+shift)%26;
              printf("Cipher text: %s\n", cipher);
            }
            

            【讨论】:

              【解决方案6】:

              我修改了 LtWorf 以匹配我当前的项目。

              移位范围:-9 ~ +9

              void caesar(char cipher[], int shift) {
                int i = 0;
              
                while (cipher[i] != '\0') {
                  if (cipher[i] >= 'A' && cipher[i]<='Z') {
                      char newletter = cipher[i] - 'A' + 26;
                      newletter += shift;
                      newletter = newletter % 26;
                      cipher[i] = newletter + 'A';
                  } else if (cipher[i] >= '0' && cipher[i]<='9') {
                      char newletter = cipher[i] - '0' + 10;
                      newletter += shift;
                      newletter = newletter % 10;
                      cipher[i] = newletter + '0';
                  }
                  i++;
                }
                printf("%s\n", cipher);
              }
              

              【讨论】:

                【解决方案7】:

                C++ 的凯撒密码

                #include<iostream>
                #include<cctype>
                using namespace std;
                
                char cipher(char c, int k)
                {
                    if(isupper(c))
                        return char( 'A' + (c - 'A' + k ) % 26);
                
                    else if(islower(c))
                        return char( 'a' + (c - 'a' + k ) % 26);
                
                    else
                        return c;
                }
                
                int main()
                {
                    int k;
                    string str;
                    cin>>str>>k;
                    int l = str.size();
                
                    for(int i=0; i<l; i++)
                        cout<<cipher(str[i], k);
                }
                

                【讨论】: