维吉尼亚密码解密c语言实现
虽说用c语言写比较麻烦,但最后还是完成了!
/*
creator:bur@n
date:2020-10-13
*/
#include <stdio.h>
#include <string.h>
#define K 2
#define matrix 5
//声明一些函数
//交互性函数
void print_welcome();
//读写文件并操作函数
void read_operate_pwd(char addr1[],char addr2[]);
//确定密钥函数,返回密钥
void make_key(char string[],int str_num);
int main(){
int flag;
int i,j;
char addr1[20]="pwd.txt",addr2[20]="result.txt";
print_welcome();
scanf("%d",&flag);
//printf("输入打开的文件:\n");
//scanf("%s",addr1);
//printf("输入输出的文件:\n");
//scanf("%s",addr2);
switch(flag){
//进行解密操作
case 1:read_operate_pwd(addr1,addr2);break;
//退出
case 2:return 0;
}
return 0;
}
//交互性函数
void print_welcome(){
int i,j;
j=50;
for(i=0;i<j;i++){
printf("*");
}
printf("\n*");
for(i=0;i<j-2;i++){
printf(" ");
}
printf("*\n*");
printf(" 欢迎使用维吉尼亚加解密程序! *");
printf("\n*");
for(i=0;i<j-2;i++){
printf(" ");
}
printf("*\n");
for(i=0;i<j;i++){
printf("*");
}
printf("\n\n");
printf("请输入您选择的数字!\n\n");
printf("1解密 2退出\n\n");
}
//利用卡希斯基方法计算得到密钥的长度是5
void read_operate_pwd(char addr1[],char addr2[]){
int i,j,t;
int size,str_num;
int row;
i=0;
size=10000;
row=100000;
char str[size],ch;
char temp[K];
char string[row][K];
FILE *in,*out;
if((in=fopen(addr1,"r"))==NULL){
printf("打开文件%s失败!\n",addr1);
//exit(0);
}
if((out=fopen(addr2,"w"))==NULL){
printf("打开文件%s失败\n",addr2);
//exit(0);
}
//将字符串读入到数组里
ch=fgetc(in);
while(!feof(in)){
//将字符转换成小写字母存入数组中
if(ch>='a'&&ch<='z')
str[i]=ch;
else if(ch>='A'&&ch<='Z')
str[i]=ch+27;
ch=fgetc(in);
i++;
}
//将字符装入二维数组中,我们这里设定的是长度为3的字符
str_num=i;
for(i=0;i<str_num-(K-1);i++){
string[i][0]=str[i];
string[i][1]=str[i+1];
//string[i][2]=str[i+2];
//string[i][3]=str[i+3];
}
//将信息写入文件中,手动计算密钥长度
for(i=0;i<str_num-(K-1);i++){
for(j=i+1;j<str_num-(K-1)-i;j++){
if((string[i][0]==string[j][0])&&(string[i][1]==string[j][1])){
//将字符的首地址记录下来
fprintf(out,"i的首地址为:%d\nj的首地址为:%d\n",i,j);
fputs("字符为:",out);
for(t=0;t<K;t++)
fprintf(out,"%c",string[i][t]);
fputs("\n",out);
}
}
}
//str_num=608;
//将一个数组存入一个列为5的二维数组中
printf("更改程序matrix的值来做下一步!\n");
getchar();
getchar();
make_key(str,str_num);
}
//根据密钥长度判断密钥
void make_key(char str[],int str_num){
char str_group[matrix][300];
char ch;
int i,j,t,k;
float max;
int temp[matrix]={0},temp2[matrix];
float voca[matrix][26]={0};
int MI[matrix]={0};
FILE *fp;
float sum,temp1[26],sum1;
float static_fre[26]={0.0856,0.0139,0.0297,0.0378,0.1304,0.0289,0.0199,0.0528,\
0.0627,0.0013,0.0042,0.0339,0.0249,0.0707,0.0797,0.0199,0.0012,0.0677,0.0607,0.1045,\
0.0249,0.0092,0.0149,0.0017,0.0199,0.0008};
for(i=0;i<matrix;i++){
for(j=0;j<str_num;j++){
if(j%matrix==i){
str_group[i][temp[i]]=str[j];
temp[i]++;
}
}
}
//把各一维数组中的数字出现频度求出来
for(i=0;i<matrix;i++){
for(j=0;j<temp[i];j++){
voca[i][str_group[i][j]-'a']++;
}
}
for(i=0;i<matrix;i++){
for(j=0;j<26;j++){
voca[i][j]=voca[i][j]/temp[i];
//printf("%f\n",voca[i][j]);
}
//printf("\n");
}
for(t=0;t<matrix;t++){
for(i=0;i<26;i++){
for(j=0,sum=0;j<26;j++){
sum1=static_fre[j]*voca[t][(j+i)%26];
sum=sum+sum1;
}
temp1[i]=sum;
//printf("%f\n",sum);
}
max=temp1[0];
for(k=0;k<26;k++){
if(temp1[k]>max){
max=temp1[k];
temp2[t]=k;
}
}
printf("密钥分别是:%c\n",temp2[t]+97);
}
//printf("\n");
if((fp=fopen("mingwen.txt","w"))==NULL){
printf("打开文件mingwen.txt失败\n");
}
for(i=0;i<str_num;i++){
if((str[i]-temp2[i%matrix]-97)<0){
fprintf(fp,"%c",(str[i]-temp2[i%matrix]+26));
printf("%c",(str[i]-temp2[i%matrix]+26));
}
else{
fprintf(fp,"%c",(str[i]-temp2[i%matrix]));
printf("%c",(str[i]-temp2[i%matrix]));
}
}
fclose(fp);
}