Λοιπόν, μιας και την έγραψα τη συνάρτηση της μετατόπισης, πρόσθεσα στον κώδικα και τον πίνακα tabula-recta που χρειάζεται ο Vigenere (με τα πολλά αλφάβητα, μετατοπισμένα συνεχώς μια θέση προς τα αριστερά, σε κάθε γραμμή του πίνακα).
Για να τεστάρω πως δημιουργείται σωστά ο πίνακας με τα αλφάβητα, περιόρισα την αλφάβητο μονάχα σε λατινικά κεφαλαία και προφανώς δεν την ανακατεύω (γενικώς έχω απενεργοποιήσει με σχόλια ότι είναι πιο σύνθετο, για να μπορώ να τεστάρω εύκολα τις προσθήκες).
Βασικά ο πίνακας tabrecta αρχικοποιείται με τόσα αλφάβητα (γραμμές) όσο είναι το μήκος του βασικού αλφάβητου (δλδ με ab.len, δλδ με 26 στον κώδικα που ακολουθεί). Κάθε επιτυχημένη δέσμευση μνήμης για το κάθε αλφάβητο ακολουθείται από αντιγραφή του βασικού αλφάβητου στη νέα μνήμη, και αμέσως κατόπιν μετατόπισή των χαρακτήρων του στη νέα μνήμη. Όλα αυτά γίνονται στην συνάρτηση...
- Κώδικας: Επιλογή όλων
int tabrecta_init( Alphabet **tabrecta, const Alphabet *ab );
Σημείωση πως ο διπλός δείκτης στο όρισμα tabrecta δεν σημαινει 2D πίνακας, αλλά pass by reference του μονού *tabrecta. Ο μονός *tabrecta είναι ήδη 2D με την ευρύτερη έννοια, γιατί είναι μονός πίνακας από struct Alphabet, όπου το κάθε struct Alphabet έχει μέσα του ένα c-string ( str ). Οπότε για παράδειγμα, η θέση [2][3] του 2D με την ευρύτερη έννοια πίνακα, είναι ο χαρακτήρας...
- Κώδικας: Επιλογή όλων
tabrecta[2].str[3];
Αυτό διότι η Alphabet είναι struct (το οποίο το χρησιμοποιώ στον Καίσαρα, ώστε ούτε να αναγκάζομαι να περνάω το μήκος της αλφαβήτου ως ξεχωριστό όρισμα στις συναρτήσεις, ούτε να το υπλογίζω από την αρχή μέσα σε κάθε συνάρτηση

)
Ο πίνακας με τα πολλά αλφάβητα χωρίς structs κλπ είναι έτσι...
- Κώδικας: Επιλογή όλων
char *tabrect[ length_of_alphabet];
Ενσωμάτωση και του Vigenere encryption/decryption θα βάλω όταν πάω σπίτι (αν είμαι σε θέση να γράψω κώδικα τότε

... αλλιώς από αύριο)...
- Κώδικας: Επιλογή όλων
#include <stdio.h> /* printf(), sscanf(), stdin, EOF */
#include <stdlib.h> /* calloc(), free(), srand(), rand() */
#include <string.h> /* strchr(), strlen(), strcpy() */
#include <limits.h> /* INT_MAX */
#include <time.h> /* time() */
#define MAXINPUT (1024+1)
#define pressENTER() \
do{ \
char mYcHAr; \
printf( "press ENTER..." ); \
while ( (mYcHAr=getchar()) != '\n' && mYcHAr != EOF ) \
; \
}while(0)
typedef struct Alphabet {
char *str; /* c-string to hold the alphabet */
int len; /* length of the alphabet */
} Alphabet;
/*********************************************************//**
* Get a c-string from stdin (return str unchanged on error)
************************************************************/
char *stdin_getstring( char *str )
{
int lenstr = 0;
if ( !str || !fgets(str, MAXINPUT, stdin) )
return str;
lenstr = strlen(str);
if ( str[ lenstr - 1 ] == '\n' )
str[ lenstr -1 ] = '\0';
return str;
}
/*********************************************************//**
* Get an int from stdin (return INT_MAX on error).
************************************************************/
int stdin_getint( int *intvar )
{
int try = 0;
char input[ MAXINPUT ] = {'\0'};
if ( !fgets(input, MAXINPUT, stdin) )
return INT_MAX;
if ( EOF == (try=sscanf(input, "%d", intvar)) || try < 1 )
return INT_MAX;
return *intvar;
}
/*********************************************************//**
* Shuffle the contents of a given c-string.
************************************************************/
char *s_shuffle( char *str )
{
char *cp = NULL, c = '\0';
int len = 0;
int i = 0;
/* sanity check */
if ( !str || !*str || (len = strlen(str)) < 2 )
return str;
srand( time(NULL) );
for (cp=str; *cp; cp++)
{
i = rand() % len;
c = *cp;
*cp = str[i];
str[i] = c;
}
return str;
}
/*********************************************************//**
*
************************************************************/
char *s_shift_left( char *s, int shiftby, const int len )
{
char *temp = NULL;
if ( !s || shiftby < 1 || len < 2 || (shiftby %= len) == 0 )
return s;
/*
if ( shiftby > len-1 )
shiftby %= len;
*/
if ( NULL == (temp = malloc( shiftby * sizeof(char) )) )
return s;
memcpy( temp, s, shiftby * sizeof(char) );
memmove( s, &s[ shiftby ], (len-shiftby) * sizeof(char) );
memcpy( &s[ len-shiftby ], temp, shiftby * sizeof(char) );
free( temp );
return s;
}
/*********************************************************//**
* Initialize the alphabet either to str,
* or if str is NULL then from cstart to cstart+ablen-1
************************************************************/
int ab_init( Alphabet *ab, const char *str, const char cstart, const int ablen )
{
int i = 0, len = 0;
/* sanity check */
if ( !ab )
return 0; /* FALSE */
ab->len = 0;
/* when str exists and is not empty */
if ( str && *str )
{
len = strlen( str );
ab->str = calloc(len+1, sizeof(char) );
if ( !ab->str )
return 0; /* FALSE */
strcpy(ab->str, str);
ab->len = len;
}
/* when str is NULL or empty, fill alphabet from cstart to (cstart+ablen-1) */
else if (cstart > '\0' && ablen > 0 && cstart + ablen - 1 < 256)
{
ab->str = calloc(ablen+1, sizeof(char) );
if ( !ab->str )
return 0; /* FALSE */
for (i=0; i < ablen; i++)
ab->str[i] = cstart + i;
ab->len = ablen;
}
/* error */
else
return 0; /* FALSE */
return 1; /* TRUE */
}
/*********************************************************//**
* Cleanup the alphabet structure
************************************************************/
void ab_cleanup( Alphabet *ab )
{
if ( !ab )
return;
if ( ab->str )
free( ab->str );
ab->len = 0;
ab->str = NULL;
return;
}
/*********************************************************//**
* Get the alphabet index of a given char ( -1 if char is not in alphabet )
************************************************************/
int abindex( const char c, const Alphabet *ab)
{
char *cp = NULL;
if ( !ab || !ab->str || !*(ab->str) )
return -1;
return (cp = strchr(ab->str,c)) ? (int)(cp - ab->str) : -1;
}
/*********************************************************//**
* Encrypt a given char with a given Caesar key.
* http://en.wikipedia.org/wiki/Caesar_cipher#Example
************************************************************/
char c_encrypt_caesar( const char c, const int keyval, const Alphabet *ab )
{
int idx = -1;
/* sanity checks */
if (!ab || !ab->str || !*(ab->str) || -1 == (idx=abindex(c,ab)) || keyval < 0)
return '\0';
return ab->str[ (idx + keyval) % ab->len ];
}
/*********************************************************//**
* Decrypt a given char that was encrypted with a given Caesar key.
* http://en.wikipedia.org/wiki/Caesar_cipher#Example (
************************************************************/
char c_decrypt_caesar( const char c, const int keyval, const Alphabet *ab )
{
int idx = -1;
/* sanity checks */
if (!ab || !ab->str || !*(ab->str) || -1 == (idx=abindex(c,ab)) || keyval < 0)
return '\0';
idx = (idx - keyval) % ab->len;
if ( idx < 0 )
idx += ab->len;
return ab->str[ idx ];
}
/*********************************************************//**
* Encrypt a given c-string with a given key, using the Caesar algorithm
************************************************************/
char *s_encrypt_caesar( char *s, const int keyval, const Alphabet *ab )
{
int i = 0;
/* sanity checks */
if ( !ab || !ab->str || !*(ab->str) || !s || !*s || keyval < 0 )
return NULL;
for (i=0; s[i]; i++)
if ( '\0' == (s[i] = c_encrypt_caesar(s[i], keyval, ab)) )
return NULL;
return s;
}
/*********************************************************//**
* Decrypt a given c-string that was encrypted with a given Caesar key.
************************************************************/
char *s_decrypt_caesar( char *s, const int keyval, const Alphabet *ab )
{
int i = 0;
/* sanity checks */
if ( !ab || !ab->str || !*(ab->str) || !s || !*s || keyval < 0 )
return NULL;
for (i=0; s[i]; i++)
if ( '\0' == (s[i] = c_decrypt_caesar(s[i], keyval, ab)) )
return NULL;
return s;
}
/*********************************************************//**
*
************************************************************/
int tabrecta_print( const Alphabet *tabrecta, const int dim )
{
int i = 0;
if ( !tabrecta )
return 0; /* FALSE */
for (i=0; i < dim; i++)
printf("%2d: %s\n", i, tabrecta[i].str );
return 1; /* TRUE */
}
/*********************************************************//**
*
************************************************************/
int tabrecta_cleanup( Alphabet **tabrecta, const int dim )
{
int i = 0;
if ( !tabrecta || !*tabrecta )
return 0; /* FALSE */
for (i=0; i < dim; i++)
if ( (*tabrecta)[i].str )
free( (*tabrecta)[i].str );
free( *tabrecta );
tabrecta = NULL;
return 1; /* TRUE */
}
/*********************************************************//**
*
************************************************************/
int tabrecta_init( Alphabet **tabrecta, const Alphabet *ab )
{
int i = 0;
/* sanity checks */
if ( !tabrecta || !ab || !*(ab->str) || ab->len < 0 )
return 0; /* FALSE */
/* allocate mem for ab->len alphabets */
*tabrecta = malloc( ab->len * sizeof(Alphabet) );
if ( !*tabrecta )
return 0; /* FALSE */
for (i=0; i < ab->len; i++) {
(*tabrecta)[i].str = malloc( (ab->len + 1) * sizeof(char) );
if ( !(*tabrecta)[i].str )
return 0; /* FALSE */
strcpy( (*tabrecta)[i].str, ab->str );
s_shift_left( (*tabrecta)[i].str, i, ab->len );
}
return 1; /* TRUE */
}
/*********************************************************//**
*
************************************************************/
int main( void )
{
Alphabet ab = {NULL, 0 }; /* the alphabet for Caesar */
Alphabet *tabrecta = NULL; /* tabula-recta for Vigenere */
char text[ MAXINPUT ] = {'\0'}; /* text input */
int key = 0; /* shifting value */
/* initialize and shuffle the Caesar alphabet */
/*
if ( !ab_init( &ab, NULL, ' ', 223 ) ) {
*/
if ( !ab_init( &ab, NULL, 'A', 26 ) ) {
puts("\nCaesar alphabet initialization failed!");
goto exit_prog;
}
/*
s_shuffle( ab.str );
*/
printf("Alphabet (%u chars):\n%s\n\n", ab.len, ab.str );
/* initialize the Vigenere tabula-recta */
if ( !tabrecta_init(&tabrecta, &ab) ) {
puts("\nVigenere tabula-recta initialization failed!");
goto exit_prog;
}
tabrecta_print( tabrecta, ab.len );
/* get the text to be encrypted */
printf("Text to be ciphered: ");
if ( *stdin_getstring(text) == '\0' ) {
puts("\nempty text was given, nothing to cipher");
goto exit_prog;
}
/* get a valid, positive Caesar key */
do
printf("Key (0 or positive): ");
while ( INT_MAX == stdin_getint( &key ) || key < 0 );
/* encrypt given text with the given Caesar key */
if ( NULL == s_encrypt_caesar(text, key, &ab) ) {
puts("\tencryption error (perhaps an invalid char was found in text)");
goto exit_prog;
}
printf("\nEncrypted text: %s\n", text );
/* decrypt given text using given Caesar key */
if ( NULL == s_decrypt_caesar(text, key, &ab) ) {
puts("\tdecryption error (perhaps an invalid char was found in text)");
goto exit_prog;
}
printf("Decrypted text: %s\n\n", text );
exit_prog:
pressENTER();
tabrecta_cleanup( &tabrecta, ab.len );
ab_cleanup( &ab );
exit( EXIT_SUCCESS );
}