Szyfr Polibiusza

Szyfr Polibiusza

Program: napisać program implementujący szyfr Polibiusza.

Z hasłem (podrozdział 4.2, wykład 1). Program czyta dane ze standardowego wejścia, przetwarza (szyfruje/deszyfruje) i wynik wypisuje na standardowe wyjście. W wierszu poleceń podajemy akcję (szyfrowanie albo deszyfrowanie) oraz hasło.

Film:

Kod programu:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

int main()
{
    char answer = 0;
    int i,j,k=0,l,pozycjaUnikat=0,czyJest,licznik,przerwij=0;
    char haslo[10];
    char unikat[10]=" ";
    char macierz[5][5];

    printf("SZYFR POLIBIUSZA\n\n");
    printf("Pierw trzeba wygenerowac tablice!\n");
    printf("Podaj HASLO ktore bedzie stanowic klucz (maksymalnie 10 znakow): ");
    /////////////////////////////////////////////Generowanie tablicy z unikatowymi znakami z podanego przez uzytkownika hasla
    do{
        for(k=0;k<sizeof(haslo);k++)
        {
            haslo[k]=0;
        }
        scanf("%10s", haslo);
        przerwij=0;
        for(k=0;k<sizeof(haslo);k++)
        {
            haslo[k]= toupper(haslo[k]);
            if (haslo[k]== 'J')
                haslo[k]= 'I';
            if((int)haslo[k]!=0 && ((char)haslo[k]<=64 ||(char)haslo[k]>=91))
                przerwij=1;
        }

        if(przerwij==0)
        {
            k=0;
            while(haslo[k])
            {
                czyJest = 0;
                haslo[k]= toupper(haslo[k]);
                if (haslo[k]== 'J')
                    haslo[k]= 'I';
                for(l=0;l<sizeof(unikat);l++)
                {
                    if (unikat[l]==haslo[k])
                        czyJest = 1;
                }
                if (czyJest == 0)
                {
                    unikat[pozycjaUnikat]=haslo[k];
                    pozycjaUnikat++;
                }
                k++;
            }
            /////////////////////////////////////////////Ujednolicenie macierzy znakami spacji
            for (i = 0; i<5; i++)
            {
                for (j = 0; j<5; j++)
                {
                    macierz[i][j]=' ';
                }
                j=0;
            }

            /////////////////////////////////////////////Wygenerowanie tablicy znakow
            /////////////////////////////////////////////W pierwszej kolenosci dodanie znakow z hasla
            printf("\nGeneruje tablice.\n");
            i=0;
            j=0;
            for (licznik = 0; licznik<sizeof(unikat); licznik++)
            {
                if(unikat[licznik]!=0)
                {
                    macierz[i][j]=unikat[licznik];
                    j++;
                }
                if(j==5)
                {
                    j=0;
                    i++;
                }
            }
            /////////////////////////////////////////////Uzupelnienie tablicy pozostalymi znakami alfabetu
            int pierwszy_ascii;
            int zapamietane_i=0;
            int zapamietane_j=0;
            for (pierwszy_ascii = 65; pierwszy_ascii<=90; pierwszy_ascii++)
            {
                if(pierwszy_ascii!=74)
                {
                    czyJest = 0;
                    for (i = 0; i<5; i++)
                    {
                        for (j = 0; j<5; j++)
                        {
                            if(zapamietane_i==0 && zapamietane_j==0 &&macierz[i][j]==' ')
                            {
                                zapamietane_i=i;
                                zapamietane_j=j;
                            }

                            int ii=(int)macierz[i][j];
                            if(pierwszy_ascii==ii)
                            {
                                czyJest=1;
                            }
                        }
                        j=0;
                    }
                    if(czyJest==0)
                    {
                        macierz[zapamietane_i][zapamietane_j]=pierwszy_ascii;
                    }
                }
                zapamietane_i=0;
                zapamietane_j=0;
            }

            /////////////////////////////////////////////Wyœweitlenie tablicy
            printf("\nWyswietlam wygenerowana tablice.\n\n");
            for (i = 0; i<5; i++)
            {
                for (j = 0; j<5; j++)
                {
                    printf(" %c",macierz[i][j]);
                }
                printf("\n");
                j=0;
            }
        }
        else
        {
            printf("\nNiepoprawne haslo, podaj litery!\n\n");
        }

    }while(przerwij==1);

    printf("\nMENU\n");
    printf("K. Kodowanie\n");
    printf("O. Odkodowanie\n");
    printf("E. Wyjdz z programu\n");
    printf("Wybierz opcje: ");

    /////////////////////////////////////////////Petla switch pozwalajaca na kodowanie/odkodowywanie
    int a;
    do{
        scanf(" %c", &answer);
        switch (answer)
        {
            case 'K':
                printf("\nWybrano kodowanie.\n");
                printf("Podaj slowo do zaszyfrowania: ");
                scanf("%10s", haslo);
                printf("\nZakodowane slowo to: ");
                k=0;
                while(haslo[k])
                {
                    if((int)haslo[k]==74)
                        haslo[k]=73;
                    haslo[k]= toupper(haslo[k]);
                    k++;
                }

                for (licznik=0;licznik<sizeof(haslo);licznik++)
                {
                   for (i = 0; i<5; i++)
                    {
                        for (j = 0; j<5; j++)
                        {
                            if(haslo[licznik]==macierz[i][j])
                            {
                                printf("%d%d ",i+1,j+1);
                            }
                        }
                        j=0;
                    }
                    i=0;
                }
                for(a=0;a<sizeof(haslo);a++)
                {
                    haslo[a]=0;
                }

                printf("\n\nWybierz kolejna opcje z menu: ");
            break;
            case 'O':
                printf("\nWybrano odkodowywanie.\n");
                printf("\n(Aby wyjsc z tej funkcji wcisnij 'E')\n");
                printf("\nPodaj kody liczbowe dzielac je spacja (limit 20 znakow): ");
                char dataBuffer[20];
                int start;
                int koniec;
                int licznik_cyfer;
                for(i=0;i<sizeof(dataBuffer);i++)
                {
                    dataBuffer[i]=' ';
                }
                while (1)
                {
                    start=0;
                    koniec=0;
                    int petla_i=0;
                    int petla_j=0;
                    licznik_cyfer=0;
                    if (fgets(dataBuffer, 20, stdin) && dataBuffer[strlen(dataBuffer) - 1] == '\n' && dataBuffer[0]!='E')
                    {
                        for(i=0;i<sizeof(dataBuffer);i++)
                        {
                            if(dataBuffer[i]!=32 && dataBuffer[i]!=10 && dataBuffer[i]!=0)
                                licznik_cyfer++;
                            else if(dataBuffer[i]==32 && licznik_cyfer>0)
                            {
                                koniec=i;
                                char subbuff[5];
                                memcpy( subbuff, &dataBuffer[start], koniec );
                                subbuff[licznik_cyfer] = '\0';
                                start=i+1;
                                if(licznik_cyfer!=2 || (char)subbuff[0]>=54 || (char)subbuff[1]>=54 || (char)subbuff[0]<=48 || (char)subbuff[1]<=48)
                                {
                                    printf("\nJeden z argumentow jest niewlasciwy!\nPodaj jeszcze raz: ");
                                    break;
                                }
                                else
                                {
                                    for (petla_i = 0; petla_i<5; petla_i++)
                                    {
                                        for (petla_j = 0; petla_j<5; petla_j++)
                                        {
                                            if((char)subbuff[0]-48==petla_i+1 && (char)subbuff[1]-48==petla_j+1)
                                            {
                                                printf("%c ",macierz[petla_i][petla_j]);
                                                break;
                                            }
                                        }
                                        petla_j=0;
                                    }
                                    petla_i=0;
                                }
                                licznik_cyfer=0;
                            }
                        }
						for(i=0;i<sizeof(dataBuffer);i++)
                        {
                            dataBuffer[i]=32;
                        }
                    }
                    else
                    {
                        fputs("Wyjscie z funkcji odkodowywania.\n", stderr);
                        printf("\n\nWybierz kolejna opcje z menu: ");
                        break;
                    }
                }
            break;
            case 'E':
                printf("\nWylaczam program.\n");
            break;
        }
    }while(answer!='E');
    return 0;
}

Słowniczek pojęć:

Klasyczna szachownica Polibiusza jest kwadratową tabelą, w której pierwszy wiersz zawiera współrzędne pionowe (kolumn), a pierwsza kolumna współrzędne poziome (wierszy). Metoda rozwidlania polega na dodaniu (jako drugiego od góry) wiersza bez współrzędnej poziomej. Do komórek tego wiersza wpisuje się słowo-klucz, które może zawierać najwyżej 8 liter. Pozostałe pola tego wiersza pozostawia się niewypełnione. Cyfry będące współrzędnymi pionowymi niewypełnionych komórek wpisuje się jako współrzędne poziome wierszy od trzeciego w dół. Powstaje tabela, która ma 10 kolumn, a liczba wierszy zależy od długości słowa-klucza. Następnie wypełnia się powstałą szachownicę pozostałymi literami alfabetu (z pominięciem liter z klucza) i ewentualnie innymi znakami. Można to robić najprościej – wierszami alfabetycznie lub według metody ustalonej między osobami, które będą używać tabeli. Liczba znaków, które można w zmieścić w takiej tabeli można opisać wzorem: liczba znaków w tabeli = 10 × liczba wierszy ze współrzędnymi + liczba znaków słowa-klucza.