#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;
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 *str_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;
for (cp=str; *cp; cp++)
{
c = *cp;
*cp = str[i];
str[i] = c;
}
return str;
}
/*********************************************************//**
* 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 )
{
ab
->str
= calloc(len
+1, sizeof(char) ); if ( !ab->str )
return 0; /* FALSE */
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 )
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://e...content-available-to-author-only...a.org/wiki/Caesar_cipher#Example
************************************************************/
char c_encrypt( 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://e...content-available-to-author-only...a.org/wiki/Caesar_cipher#Example (
************************************************************/
char c_decrypt( 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( 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(s[i], keyval, ab)) )
return NULL;
return s;
}
/*********************************************************//**
* Decrypt a given c-string that was encrypted with a given Caesar key.
************************************************************/
char *s_decrypt( 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(s[i], keyval, ab)) )
return NULL;
return s;
}
/*********************************************************//**
*
************************************************************/
int main( void )
{
Alphabet ab = {NULL, 0 }; /* our alphabet */
char text[ MAXINPUT ] = {'\0'}; /* text input */
int key = 0; /* shifting value */
/* initialize and shuffle the alphabet */
if ( !ab_init( &ab, NULL, ' ', 223 ) ) {
puts("\nalphabet initialization failed!"); goto exit_prog;
}
str_shuffle( ab.str );
printf("Alphabet (%u chars):\n%s\n\n", ab.
len, ab.
str );
/* 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(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(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();
ab_cleanup( &ab );
}