playfair.h
#ifndef PLAYFAIR_H
#define PLAYFAIR_H
#include <string>
#include <utility>
using namespace std;
class PlayFair
{
private:
char m_ch;
int m_position;
string m_key;
string m_letter;
void ToLower(string &str);
bool emptyKey() const;
void keySameLetter();
void deleteLetter();
void addLetter();
void initialize();
void changeMessage(string &str);
bool sameRow(char lch, char rch, pair<int,int> &p) const;
bool sameColumn(char lch, char rch, pair<int, int> &p) const;
bool isRight(int po);
bool isBottom(int po);
void sameRowInsert(pair<int,int> &p, string &str);
void sameColumnInsert(pair<int, int> &p, string &str);
void nonSameInsert(pair<int, int> &p, string &str);
public:
explicit PlayFair(){};
explicit PlayFair(const string &str);
explicit PlayFair(const char *ch);
PlayFair& operator = (const PlayFair &p);
bool operator ==(const PlayFair &p);
bool operator !=(const PlayFair &p);
string encrypt(string str);
void setKey(string &key);
void setKey(char *ch);
};
#endif
pffun.cpp
#include <iostream>
#include <cctype>
#include "playfair.h"
PlayFair::PlayFair(const string &str):m_key(str)
{
initialize();
}
PlayFair::PlayFair(const char *ch):m_key(ch)
{
initialize();
}
void PlayFair::ToLower(string &str)
{
string::iterator ite = str.begin();
for (; ite != str.end(); ++ite)
{
if (isupper(*ite))
*ite = tolower(*ite);
}
}
bool PlayFair::emptyKey() const
{
return m_key.empty();
}
void PlayFair::keySameLetter()
{
if (!emptyKey())
{
string::iterator fite, site;
fite = m_letter.begin();
for (int i = 0; i < m_letter.size(); ++i)
{
fite = m_letter.begin() + i;
site = fite + 1;
for (int j = i + 1; j < m_letter.size(); ++j)
{
if (*fite != *site)
++site;
else
{
site = m_letter.erase(site);
fite = site - 1;
}
}
}
}
}
void PlayFair::deleteLetter()
{
string::iterator ite = m_key.begin();
for (; ite != m_key.end(); ++ite)
{
m_letter[*ite-97] = ' ';
}
}
void PlayFair::addLetter()
{
if (!emptyKey())
{
m_position = m_key.size();
string::iterator ite = m_letter.begin();
for (; ite != m_letter.end(); ++ite)
{
if (*ite != ' ')
m_key.insert(m_key.end(), *ite);
}
m_ch = m_key[m_position];
m_key.erase(&(m_key[m_position]));
}
}
void PlayFair::initialize()
{
m_letter = "abcdefghijklmnopqrstuvwxyz";
ToLower(m_key);
keySameLetter();
deleteLetter();
addLetter();
}
bool PlayFair::operator ==(const PlayFair &p) //左操作数不可以是常对象
{
return (m_key == p.m_key);
}
bool PlayFair::operator != (const PlayFair &p)
{
return !(m_key == p.m_key);
}
PlayFair& PlayFair::operator =(const PlayFair &p)
{
if (*this == p)
return *this;
else
{
string::const_iterator ite = p.m_key.begin();
for (; ite != p.m_key.end(); ++ite)
m_key.insert(m_key.end(), *ite);
}
return *this;
}
void PlayFair::changeMessage(string &str)
{
string::iterator fite, site;
fite = str.begin();
site = fite + 1;
for (; fite != str.end() && site != str.end();)
{
if (*fite == *site)
{
if (*site == 'z')
site = str.insert(site, 'a');
else
site = str.insert(site, *site+1);
fite = site + 1;
site = fite + 1;
}
else
{
++fite;
++site;
}
}
if (!str.empty() && str.size() % 2)
{
if (*(str.end() - 1) == 'z')
str.insert(str.end(), 'a');
else
str.insert(str.end(), *(str.end()-1)+1);
}
}
string PlayFair::encrypt(string str)
{
if (!emptyKey())
{
string result;
ToLower(str);
changeMessage(str);
pair<int, int> po;
string::iterator fite, site;
fite = str.begin();
for (; fite != str.end(); fite += 2)
{
site = fite + 1;
if (sameRow(*fite, *site, po))
sameRowInsert(po, result);
else
{
if (sameColumn(*fite, *site, po))
sameColumnInsert(po, result);
else
nonSameInsert(po, result);
}
}
return result;
}
else
return "";
}
bool PlayFair::sameRow(char lch, char rch, pair<int,int> &p) const
{
p.first = m_key.find(lch);
if (p.first == string::npos)
p.first = m_position;
p.second = m_key.find(rch);
if (p.second == string::npos)
p.second = m_position;
if (p.first / 5 == p.second / 5)
return true;
else
return false;
}
bool PlayFair::sameColumn(char lch, char rch, pair<int, int> &p) const
{
p.first = m_key.find(lch);
if (p.first == string::npos)
p.first = m_position;
p.second = m_key.find(rch);
if (p.second == string::npos)
p.second = m_position;
if (p.first % 5 == p.second % 5)
return true;
else
return false;
}
inline bool PlayFair::isRight(int po)
{
return (po % 5 == 4);
}
inline bool PlayFair::isBottom(int po)
{
return (po / 5 == 4);
}
void PlayFair::sameRowInsert(pair<int,int> &p, string &str)
{
if (isRight(p.first))
str.insert(str.end(), m_key[p.first-4]);
else
str.insert(str.end(), m_key[p.first+1]);
if (isRight(p.second))
str.insert(str.end(), m_key[p.second-4]);
else
str.insert(str.end(), m_key[p.second+1]);
}
void PlayFair::sameColumnInsert(pair<int, int> &p, string &str)
{
if (isBottom(p.first))
str.insert(str.end(), m_key[p.first-20]);
else
str.insert(str.end(), m_key[p.first+5]);
if (isBottom(p.second))
str.insert(str.end(), m_key[p.second-20]);
else
str.insert(str.end(), m_key[p.second+5]);
}
inline void PlayFair::nonSameInsert(pair<int, int> &p, string &str)
{
str.insert(str.end(), m_key[p.first/5*5+p.second%5]);
str.insert(str.end(), m_key[p.second/5*5+p.first%5]);
}
void PlayFair::setKey(string &str)
{
m_key = str;
initialize();
}
void PlayFair::setKey(char *ch)
{
m_key = ch;
initialize();
}