[文本加密]
有一种加密方法为:其使用一个字母串(可以含重复字母,字母个数不超过50)作为密钥,假定密明单词率为feather,则先去掉密钥单词中的重复字母得到单词串feathr,然后再将字母表中的其它字母以反序追加到feathr的后面:
加密字母的对应关系如下:
其中第一行为原始英文字母,第二行为对应加密字母,其它字符不进行加密。编写一个程序,用这种密码加密文件。假定要加密的文件名为encrypt.txt及加密后的文件名为output.txt,并假定输入文件中字母全为小写字母,并且输入密也全为小写字母,
[输入形式]
从标准输入中输入密钥串,并从文件encrypt.txt中读入要加密的内容。
[输出形式]
加密后结果输出到文件output.txt中。
[思路分析]
- 首先,将文件打开,并读入密钥 ,定义两个字符数组分别接收文本和输出文本;
- 定义对密钥的处理函数merge(),将密钥中的重复字母合并;此函数中,需要注意,在找到重复字母时,将其删除以后,后面的字符串整体前移一位,此时数组的指针需要减一,否则会导致跳过一位字符,缺省对它的判断;
- 在处理完密钥以后,用connect()函数将密码表补齐;该函数内需要先定义一个字符变量,赋初值为‘z’,让其自减以此来遍历26个英文字母,然后调用judge()函数判断当前字母是否在密钥中已经出现过,如果没有出现过,就将其接在密钥后面,如果已经出现过,则字符变量自减,密钥数组的指针减一保持在本位,以此来判断下一个字母是否出现过;
- 在获得密码表以后,调用change()加密函数,将原文通过密码表的规则进行加密,保存在里一个数组里面,进而进行输出。此处需要注意的是,在寻找对应密码时,可以通过实际字母在字母表中的位置来寻找对应的密码;
- 处理完文本后,输出,关闭文件。
[代码实现]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include<stdlib.h>
void merge(char a[]) //删除重复字母
{
for(int i=0;i<strlen(a);i++) //遍历密钥每个字母
{
if (a[i] == '\n') //遇到换行时将其换为空格方便strlen调用,并且break跳出循环
{
a[i] = '\0';
break;
}
for(int j=i+1;j<strlen(a);j++) //寻找当前字母的后面有没有重复
if (a[i] == a[j]) //后边有重复
{
for (int k = j; k <= strlen(a); k++) //后面的重复字母后边的每一个字母前移
a[k] = a[k + 1];
j--; //此时如果不j--,则会跳过一个字母,该字母不被判断
}
}
}
int judge(char a[], char b) //判断此时字母是否在密钥中出现过
{
for (int i = 0; i < strlen(a); i++)
if (a[i] == b)
return 0; //没有出现过返回0
return 1;
}
void connect(char a[]) //将密钥后面补齐字母
{
char t = 'z'; //字符变量循环每个字母
for (int i = strlen(a); i < 26; i++)
{
if (judge(a, t)) //判断不重复时将其拼在密钥后边
a[i] = t;
else //重复时需要重复判断当前字母跟下一字符变量是否相同,所以i--防止遍历下一个字母
i--;
t--; //字符变量自减,循环26个字母
}
}
void change(char a[], char b[]) //将文本每个字母按规则替换
{
for (int i = 0; i < strlen(b); i++)
if (b[i] >= 'a' && b[i] <= 'z')
b[i] = a[b[i] - 97];
}
int main()
{
FILE* fin = fopen("encrypt.txt", "r");
FILE* fout = fopen("output.txt", "w");
char a[1000], b[1000];
gets(a); //获得密钥
merge(a); //处理重复字母
connect(a); //补齐密钥
fgets(b, 1000, fin); //获得文本
change(a, b); //加密文本
fputs(b, fout); //输出文本
fclose(fin);
fclose(fout);
return 0;
}