c - 频率分析?凯撒密码C

标签 c arrays file-io structure

这段代码我已经写完了,现在要求我使用频率分析来破解我不太清楚的代码。

据我了解,我必须先计算字符串中字母的频率,然后我会说将其与德语中出现频率最高的字母进行比较,然后用冒泡排序对其进行排序。它是否正确?

如果有人能给我想法或提示从哪里开始,我将不胜感激。提前谢谢你。

已编辑:大家好,我刚刚编辑了我的代码,频率分析现在似乎工作正常。如果你们可以对我的代码发表评论或批评,这将对我有所帮助。谢谢! 顺便说一句,它是德语,我改变了它。

#include <stdio.h> 
#include <conio.h> 
#include <string.h> 
#include <ctype.h>
#define MAX 100

struct Data
{
    char letter;
    int num;
};
typedef struct Data DATA;

void encode(char message[], int shift)      
{
    int i;
    FILE *pout;
    pout = fopen("Output_encode.txt", "w");
    if (pout == NULL)
    {
        printf("File could not be opened for writing!\n");
        exit(1);
    }



    for(i=0;i<strlen(message);i++) 
    { 
        if (!isalpha(message[i]))
            continue;                           
        // checking for upper case 
        if(isupper(message[i]))
            message[i]=((message[i]-'A') + shift) % 26 + 'A'; 
        else 
            //checking for lower case 
            if(islower(message[i]))  
                message[i]=((message[i]-'a') + shift) % 26 + 'a'; 
    }

    printf("\n\tEncoded text: %s\n", message);
    fprintf(pout, "%s\n", message);
    if (fclose(pout) != 0)
        printf("Error in closing file!\n");
}

void decode(char message[], int shift)
{
    int i;
    FILE *pout;

    pout = fopen("Output_decode.txt", "w");
    if (pout == NULL)
    {
        printf("File could not be opened for writing!\n");
        exit(1);
    }

    for(i=0;i<strlen(message);i++) 
    { 
        if (!isalpha(message[i]))
            continue;                           
        // checking for upper case 
        if(isupper(message[i]))
            message[i]=((message[i]-'A') + (26-shift)) % 26 + 'A'; 
        else 
            //checking for lower case
            if(islower(message[i]))  
                message[i]=((message[i]-'a') + (26-shift)) % 26 + 'a'; 
    }

    printf("\n\tDecoded text: %s\n", message);
    fprintf(pout, "%s\n", message); 
    if (fclose(pout) != 0)
        printf("Error in closing file!\n");
}

void textfile_decode()
{
    FILE *pin, *pout;
    char filename_in[MAX], filename_out[MAX];
    char text[MAX];
    char text3[MAX]={0};
    char table[26] = {'e','n','i','r','s','t','a','d','h','u','l','c','g','o','m','b','f','w','k','z','p','v','j','y','x','q'}; //Frequency letters in German dictionary
    DATA temptext, text2[26];
    int temp, position;
    int i, m, max, trial, l=0, n=0, k=0;

    printf("Enter name of input file: "); 
    scanf("%s", filename_in);
    pin = fopen(filename_in, "r");
    if (pin == NULL)
    {
        printf("File could not be opened for reading!");
    }

    printf("Enter name of output file: ");
    scanf("%s", filename_out);
    pout = fopen(filename_out, "w");
    if (pout == NULL)
    {
        printf("File could not be opened for writing!");
    }

    printf("\nOriginal Code:\n");
    while(!feof(pin))
    {
        fgets(text, MAX, pin);     //Read from textfile
        fputs(text, stdout);         //Show original code on console
    }
    printf("\n");
    if (pin == NULL)
    {
        printf("File could not be opened for reading!");
    }
    fclose(pin);
    pin = fopen(filename_in, "r");

    for (i = 0; i <= 25; i++)       
    {                               
        text2[i].letter = 'a' + i;  //Array elements A-Z     
        text2[i].num = 0;           //Number of letters (Frequency)
    }

    while(!feof(pin))
    {
        i = 0;
        fgets(text, MAX, pin);  //Read from textfile per line
        while(text[i] != '\0')
        {
            if(1 == isupper(text[i]))  // Replace capital letters with small
            {                          
                text[i] += 32;
            }
            switch(text[i]) //Counting letters (letter frequency)
            {
            case 'a': 
                text2[0].num += 1;
                break;
            case 'b': 
                text2[1].num += 1;
                break;
            case 'c':
                text2[2].num += 1;
                break;
            case 'd': 
                text2[3].num += 1;
                break;
            case 'e': 
                text2[4].num += 1;
                break;
            case 'f': 
                text2[5].num += 1;
                break;
            case 'g': 
                text2[6].num += 1;
                break;
            case 'h': 
                text2[7].num += 1;
                break;
            case 'i': 
                text2[8].num += 1;
                break;
            case 'j': 
                text2[9].num += 1;
                break;
            case 'k': 
                text2[10].num += 1;
                break;
            case 'l': 
                text2[11].num += 1;
                break;
            case 'm': 
                text2[12].num += 1;
                break;
            case 'n': 
                text2[13] .num+= 1;
                break;
            case 'o': 
                text2[14].num += 1;
                break;
            case 'p': 
                text2[15].num += 1;
                break;
            case 'q': 
                text2[16].num += 1;
                break;
            case 'r': 
                text2[17].num += 1;
                break;
            case 's': 
                text2[18].num += 1;
                break;
            case 't': 
                text2[19].num += 1;
                break;
            case 'u': 
                text2[20].num += 1;
                break;
            case 'v': 
                text2[21].num += 1;
                break;
            case 'w': 
                text2[22].num += 1;
                break;
            case 'x': 
                text2[23].num += 1;
                break;
            case 'y': 
                text2[24].num += 1;
                break;
            case 'z': 
                text2[25].num += 1;
                break;
            default: break;
            }   
            i++;    
        }
    }

    for(i = 0; i <= 26; i++)          // Sorting array text2 according to letter frequency
    {                                 
        temp = text2[i].num;
        for(m = i+1; m <= 27; m++)
        {
            if(text2[m].num > temp)
            {
                max = m;
                temp = text2[m].num;
            }
        }
        temptext = text2[max];
        text2[max] = text2[i];
        text2[i] = temptext;
    }
    fclose(pin);
    fclose(pout);

    pin = fopen(filename_in, "r");
    pout = fopen(filename_out, "w");

    do
    {
        k += 1;
    } while (text2[k].num == text2[k+1].num);        //Check--> How many letters have the same frequency

    trial = 2;

    while(!feof(pin))
    {
        fgets(text, MAX, pin);
        do
        {
            position = table[l] - text2[n].letter;        // determine letter position
            i = 0;
            do
            {
                if(0 !=isalpha(text[i]))
                {
                    if(0 != isupper(text[i]))         // Checking for uppercase
                    {
                        text3[i] = text[i];
                        text3[i] = text3[i] + position;
                        if(text3[i] > 90)        // If exceeds Alphabets, start again from 'A'
                        {
                            text3[i] = text3[i] - 26;
                        }
                        else if (text3[i] < 65)
                        {
                            text3[i] += 26;
                        }
                    }
                    else if (0 != islower(text[i]))         // checking for lowercase
                    {
                        text3[i] = text[i];
                        text3[i] = text3[i] + position;
                        if(text3[i] > 122)       // If exceeds Alphabets, start again from 'a'
                        {
                            text3[i] = text3[i] - 26;
                        }
                        else if(text3[i] < 97)
                        {
                            text3[i] += 26;
                        }
                    }
                }
                else
                {
                    text3[i] = text[i];      // All other non letters are simply replaced
                }
                i++;
            }while(text[i] != '\0' );

            if (trial== 2)
            {
                printf("\n");
                fputs(text3, stdout);
                printf("\nCode decrypted? (0)NO (1)YES : ");
                scanf("%d", &trial);
                printf("\n");
            }

            if (trial == 0 && n != k)      // Code not decrypted, letters have different frequency
            {                              
                n++;
                trial = 2;
            }
            if (trial == 0 && n == k)        // Code not decrypted, letters have same frequency
            {                                
                l++;
                n = 0;
                trial = 2;
            }
            if (trial == 3)         // First line of code is decrypted, following lines will decrypted using same shift position 
            {                      
                trial = 1;
            }
        }while(trial != 1);
        fputs(text3, stdout);       //Show on console window
        fputs(text3, pout);
        memset(text3,'\0',100);        // Reset text3 array
        memset(text,'\0',100);         // Reset text array
        trial = 3;        // First line of code decrypted, shift position is saved
    }
    fclose(pin);
    fclose(pout);

}


int main()
{ 
    int shift, choice1, choice2; 
    char message[MAX]; 

    do{
        printf("Selection: \n");
        printf("(1) Encode/Decode\n");
        printf("(2) Decode Textfile\n");
        printf("(3) End Programme\n");
        printf("User input: ");
        scanf("%d", &choice1);
        fflush(stdin);


        switch(choice1){
        case 1:
            printf("\nEnter message to be encrypted: "); 
            gets(message);
            printf("Enter shift amount (1-25): ");  
            scanf("%d", &shift); 
            printf("\nSelection: \n");
            printf("(1) Encode\n");
            printf("(2) Decode\n");
            printf("User input: ");
            scanf("%d", &choice2);
            switch(choice2)
            {
            case 1:
                encode(message, shift);
                break;
            case 2:
                decode(message, shift);
                break;
            }
            break;
        case 2:
            textfile_decode();
            break;
        }
        printf("\n\n");
    }while(choice1!=3);

    printf("\n");
    return 0; 
}

最佳答案

A Caesar ciphre通过移动 n 个位置来更改字符。

解决移位密码有两种非常简单的方法:

  1. 打印出所有 25 种可能的解决方案。手动选择包含可读文本的文本。

  2. 获取字符(不是单词)的出现频率。然后执行与消息所用语言的频率表最匹配的转换(你的情况是英语?)。

关于c - 频率分析?凯撒密码C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19764689/

相关文章:

c - 这是测试缓冲区溢出的好方法吗?

c - 十进制转二进制

c++ - 如何在 C 中获取 char 数组的前 x 个元素? boost-libraries 有改进的方法吗?

c++ - 快速了解 C++ 数组类构造函数

c - 结构体为其成员分配内存

C 通过读取系统调用在我的缓冲区中查找换行符

codeigniter 上传 encrypt_name 唯一性

c - write函数在Unix上需要unistd.h,windows呢?

java - 具有重写的fileInputFormat的MapReduce无法输出结果

c - shell脚本: write to file