0

编辑:这被称为凯撒密码。我试图制作一个主要目的是加密给定(短小写)字符串的程序。它可以通过将所有字母n 个空格向右(加密)或向左(解码)移动来实现。

这是我到目前为止所写的(已编辑)

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

char abc[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'};

void code(int n) {
  string cadena;
  cout << "Introduzca la cadena a cifrar : " << '\n';
  cin >> cadena;

  for (int i(0); i < cadena.length; i++) {
    for (int f(0); f < strlen(abc); f++) {
      if (cadena[i] == abc[f]) {
        int w;
        w = f + n;
        if (w > strlen(abc)) {
          w -= strlen(abc);
        }
        cadena[i] = abc[w];
      }
    }
  }
  cout << cadena << '\n';
  system("pause");
}

void decode(int n) {
  string cadena;
  cout << "Introduzca la cadena a cifrar : " << '\n';
  cin >> cadena;

  for (int i(0); i < cadena.length; i++) {
    for (int f(0); f < strlen(abc); f++) {
      if (cadena[i] == abc[f]) {
        int w;
        w = f - n;
        if (w < 0) {
          w--;
          w = strlen(abc) - w;
        }
        cadena[i] = abc[w];
      }
    }
  }
  cout << cadena << '\n';
  system("pause");
}

int main() {
  int n;
  cout << "Introduzca el numero del cesar " << '\n';
  cin >> n;
  cout << "Desea usted cifrar o descifrar?" << '\n';
  cout << "Introduzca c para cifrar o d para descifrar" << '\n';
  char chos;
  cin >> chos;
  if (chos == 'c')
    code(n);
  else
    decode(n);

  return 0;
}  

现在的问题是我得到了一个糟糕的字符串,我什至不知道它是如何形成的。还有一个错误。

这是结果

4

1 回答 1

3

让我们先快速浏览一下代码。

char abc[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' };

这很好。它不处理大写,但一个很好的开始

void code(int n)
{
    char cadena;

定义一个单独的字符。我们稍后会看到这不是您想要的。

    char * cadena_ptr = &cadena;

一般情况下,这是个好主意,但是用单个字符,就没那么有用了

    cout << "Introduzca la cadena a cifrar : " << '\n';
    cin >> cadena;

这就是事情开始出错的地方。由于cadena定义方式,代码仅读取一个且仅一个字符。

    for (int i(0); i <= sizeof(cadena); i++)

如前所述,cadena是一个字符,因此i <= sizeof(cadena)与 相同i <= 1。这导致循环的 2 次迭代。一个用于i=0( 0<=1),一个用于i=1( 1<=1)。这意味着循环将超出cadenas 一个字符的范围。这个结果是不确定的。程序可能会崩溃。程序可能会覆盖和损坏cadena. 程序可能会吃掉你邻居的猫。一切都是完全有效的,但前两个比第三个更有可能。

    {
        for (int f(0); f <= 26; f++)

这也超出了界限。这个循环也可能不是必需的。在 2017 年,您不太可能看到不将所有字符存储在升序连续块中的字符编码。也就是说,这种蛮力循环消除了与打乱字符顺序的遗留或 bizzaro 字符编码发生冲突的可能性。

我将坚持这个循环,因为这个问题并不是关于 ASCII 算术的。

        {
            if (*cadena_ptr == abc[f])
            {
                int w;
                w = f + n;
                if (w >= 26)
                {
                    w -= 26;
                }
                *cadena_ptr = abc[w];

整个块看起来不错,一旦索引问题得到解决,应该可以工作。不过,有一个改进。一旦找到匹配项,您就可以停止寻找更多匹配项。还大量使用了应该替换的幻数 26 。

            }
        }

    }
    cout << cadena << '\n';
    system("pause");
}

清理第一阶段:

通过一个索引修复关闭。这很快:

    for (int i(0); i < sizeof(cadena); i++)
    {
        for (int f(0); f < sizeof(abc); f++) // death to magic number!

下一读多于一个字:

正确的方式!使用基于std::string范围循环for

void code(int n)
{
    std::string cadena;
    //char * cadena_ptr = &cadena; obsoleted by std::string

    cout << "Introduzca la cadena a cifrar : " << '\n';
    cin >> cadena;

    for (char & ch:cadena)// loop through all characters in cadena
    {
        for (int f(0); f < sizeof(abc) ; f++)
        {
            if (ch == abc[f])
            {
                int w;
                w = f + n;
                if (w >= sizeof(abc))
                {
                    w -= sizeof(abc);
                }
                ch = abc[w];
                break;// we found it! Stop looking.
            }
        }
    }
    cout << cadena << '\n';
    system("pause");
}

我不会把时间浪费在错误的方式上。这是错的。学会使用std::string

如果项目要求说不std::string,请不要以错误的方式去做。做一些完全不同的事情!一个一个地读取字符,转换它们,然后打印它们。要加密直到找到无法转换的字符,我们可以执行以下操作:

bool goodchar(char & cadena, int n)
{
    for (int f(0); f < sizeof(abc) ; f++)
    {
        if (cadena == abc[f])
        {
            int w;
            w = f + n;
            if (w >= sizeof(abc))
            {
                w -= sizeof(abc);
            }
            cadena = abc[w];
            return true;
        }
    }
    return false;
}

void code(int n)
{
    char cadena;

    cout << "Introduzca la cadena a cifrar : " << '\n';
    cin >> cadena; // get first character

    while (goodchar(cadena)) // keep looping until we find a character that's 
                             // not in the list       
    {
        cout << cadena << '\n';
        cin >> cadena; // get next character
    }
    cout << '\n';
    system("pause");
}
于 2017-02-18T21:36:12.507 回答