凯撒密码扭曲(神秘错误)

时间:2015-10-14 20:50:42

标签: c++ encryption file-io

我被分配编写一个密码,该密码接收带有字符的文件,并用数字(1-10)更改所有字符。困难的部分是加密所需要的。 "每次处理新行时,键值增加1。但是,键每五(旋转值)行重置一次并返回其原始值"

例如:如果用户为密钥输入3,则1,2,3,4和5行分别用3,4,5,6和7加密。然后用3加密第6行,依此类推。

目前,我甚至无法让一个简单的班次正常工作。没有任何语法错误,它编译没有错误。但是,当我打开输出文件时,我的文本编辑器崩溃,因为我以某种方式创建了一个510mb文本文件.....我知道:/

所以我正在寻找你愿意给予的任何帮助。现在已经工作了几个多小时,并认为现在是时候寻求帮助了。如果您愿意花时间给出任何建议/解决方案,请提前感谢大家。 :)

/*
*File: Lab5
*Author: Nathaniel Goodhue
*Created on: 10/14/15
*Description: Encrypts an input message by
*shifting characters by a given number        
*/

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <fstream>

using namespace std;

/*
*Displays a menu that allows the user to set a shift key value,
*encrypt or decrypt a message, or quit
*/
void displayMenu()
{
   cout<<"1. Set the shift key value"<<endl;
   cout<<"2. Encrypt"<<endl;
   cout<<"3. Decrypt"<<endl;
   cout<<"4. Quit"<<endl;
}

/*
*gets the value that characters will be shifted by
*/
int getKeyValue(int &keyValue)
{
   keyValue = 0;
   do
   {
      cout<<"Enter the shift key value between 1 and 10: ";
      cin >>keyValue;
      if(keyValue >10 ||keyValue <1)
         cout<<"Key value must be between 1 and 10."<<endl;
   }
   while(keyValue >10 || keyValue <1);
   return keyValue;
}

/*
*gets the input and output file names
*/
void getFileNames(ifstream &fin1, ofstream &fout1, ifstream  &fin2, ofstream &fout2)
{
   fin1.open("inputMsg.txt");
   fout1.open("encryptedMsg.txt");
   fin2.open("encriptedMsg.txt");
   fout2.open("revertedMsg.txt");
}

/*
*shifts characters in input file by (int keyValue)
*/
void encrypt(int &keyValue, ifstream &fin1, ofstream &fout1)
{
   char ch;
   while(!fin1.eof())
   { 
      fin1.get(ch);
      while(ch != ' ')
      {
         fout1<<static_cast <char> (static_cast <int>(ch)+keyValue);
      }
   }
}

/*
*shifts characters back to original 
*/
void decrypt(int &keyValue, ifstream &fin2, ofstream &fout2)
{

   char ch;
   while(!fin2.eof())
   {
      fin2.get(ch);
      while(ch != ' ')
      {
         fout2<<static_cast <char> (static_cast <int>(ch)-keyValue);
      }
   }
}

int main()
{
   int menuChoice, keyValue;
   ifstream fin1;
   ofstream fout1;
   ifstream fin2;
   ofstream fout2;

   getFileNames(fin1, fout1, fin2, fout2);
   do{   
      displayMenu();
      cin >> menuChoice;
      if (menuChoice == 1)
      {
         getKeyValue(keyValue);
      }  
      else if (menuChoice == 2)
      {
     cout<<"Message successfully encrypted with "<<keyValue<<" as its key value"<<endl;
         encrypt(keyValue, fin1, fout1);
      }
      else if (menuChoice == 3)
      {
         cout<<"Message successfully decrypted with "<<keyValue<<" as its key value"<<endl;
         decrypt(keyValue, fin2, fout2);
      }
      else if(menuChoice > 4 || menuChoice < 1)
         cout<<"Invalid menu choice. Must be between 1 and 4";
   }
   while(menuChoice != 4);
   fin1.close();
   fout1.close();
   fin2.close();
   fout2.close();
   return 0;
}

另外我有4个文件的原因是因为需要decypher功能。

3 个答案:

答案 0 :(得分:1)

您的问题出在加密功能中。特别是这一点:

  fin1.get(ch);
  while(ch != ' ')
  {
     fout1<<static_cast <char> (static_cast <int>(ch)+keyValue);
  }

在第一次循环运行时,fin1.get(ch)ch设置为输入文件的第一个字符。然后输入一个while循环,将(加密的)第一个字符放入文件中,一遍又一遍,直到ch为空格。但是你读取了这个循环之外的下一个字符,所以永远不会达到结束循环的条件。

您需要一个简单的if语句来避免对空格进行加密。除此之外,你的当前代码总是会拾取(和加密)EOF,因为EOF位不会被设置,直到你尝试读取文件的结尾(这是在循环中完成的,所以不会和#39; t在你加密并附加到文件之前检查。您可以使用ifstream good()检查循环内是否存在任何问题(EOF或错误)和break(如果有),以避免EOF造成额外问题最后的角色:

void encrypt(int &keyValue, ifstream &fin1, ofstream &fout1)
{
   char ch;
   while(fin1.get(ch))
   {
      if(!fin1.good()) break;
      if (ch != ' ') fout1<<static_cast <char> (static_cast <int>(ch)+keyValue);
      else fout1<<' ';
   }
}

您也需要对解密进行类似的更改。另外,为了挑剔,我建议

cout<<"Message successfully encrypted with "<<keyValue<<" as its key value"<<endl;

并且成功加密/解密之后应该来到,而不是之前。

另一个问题是文件流在程序开始时全部打开并在结束时关闭的方式。如果您尝试在程序的同一运行中加密和解密消息,则会失败,因为fin2在实际写入消息之前打开encryptedMsg.txt。 <{1}}(将加密的消息写入该文件)需要先关闭。

我实际上只是建议您只在需要时打开流。不是在开头打开所有流并在结束时关闭所有流,而是在加密消息之前打开fout1(输入消息)和fin1(加密输出),然后立即关闭它们。同样,在解密之前立即打开fout1(加密消息作为输入)和fin2(解密版本),然后立即关闭它们。或者,更好的是,您可以重用流 - 只需要一个fout2对象和一个ifstream对象,每个对象在加密/解密之前和之后打开和关闭相应的文件。

答案 1 :(得分:0)

您的程序永远不会停止读取输入文件。如果您的输入文件不包含空格字符,那么此循环将永远运行,这就是导致输出非常大的原因。

while(ch != ' ')

将这两行更改为

while(fin1.good())

使其在文件结束处停止(EOF)。

答案 2 :(得分:0)

不要试图一次完成所有事情。从一个简单的程序开始读取文件并对其进行标准的凯撒转换。当且仅当您正确地工作时,每个行尾都使用步进键进入第二阶段。

这样做可以一次处理一些错误,而不是将它们全部集中在一起。您还可以更轻松地找出代码的哪一部分导致错误。