fork download
  1. #include <stdio.h> /* printf(), sscanf(), stdin, EOF */
  2. #include <stdlib.h> /* calloc(), free(), srand(), rand() */
  3. #include <string.h> /* strchr(), strlen(), strcpy() */
  4. #include <limits.h> /* INT_MAX */
  5. #include <time.h> /* time() */
  6.  
  7. #define MAXINPUT (1024+1)
  8.  
  9. #define pressENTER() \
  10. do{ \
  11. char mYcHAr; \
  12. printf( "press ENTER..." ); \
  13. while ( (mYcHAr=getchar()) != '\n' && mYcHAr != EOF ) \
  14. ; \
  15. }while(0)
  16.  
  17. typedef struct Alphabet{
  18. char *str; /* c-string to hold the alphabet */
  19. int len; /* length of the alphabet */
  20. } Alphabet;
  21.  
  22. /*********************************************************//**
  23.  * Get a c-string from stdin (return str unchanged on error)
  24.  ************************************************************/
  25. char *stdin_getstring( char *str )
  26. {
  27. int lenstr = 0;
  28.  
  29. if ( !str || !fgets(str, MAXINPUT, stdin) )
  30. return str;
  31.  
  32. lenstr = strlen(str);
  33. if ( str[ lenstr - 1 ] == '\n' )
  34. str[ lenstr -1 ] = '\0';
  35.  
  36. return str;
  37. }
  38.  
  39. /*********************************************************//**
  40.  * Get an int from stdin (return INT_MAX on error).
  41.  ************************************************************/
  42. int stdin_getint( int *intvar )
  43. {
  44. int try = 0;
  45. char input[ MAXINPUT ] = {'\0'};
  46.  
  47. if ( !fgets(input, MAXINPUT, stdin) )
  48. return INT_MAX;
  49.  
  50. if ( EOF == (try=sscanf(input, "%d", intvar)) || try < 1 )
  51. return INT_MAX;
  52.  
  53. return *intvar;
  54. }
  55.  
  56. /*********************************************************//**
  57.  * Shuffle the contents of a given c-string.
  58.  ************************************************************/
  59. char *str_shuffle( char *str )
  60. {
  61. char *cp = NULL, c = '\0';
  62. int len = 0;
  63. int i = 0;
  64.  
  65. /* sanity check */
  66. if ( !str || !*str || (len = strlen(str)) < 2 )
  67. return str;
  68.  
  69. srand( time(NULL) );
  70.  
  71. for (cp=str; *cp; cp++)
  72. {
  73. i = rand() % len;
  74. c = *cp;
  75. *cp = str[i];
  76. str[i] = c;
  77. }
  78.  
  79. return str;
  80. }
  81.  
  82. /*********************************************************//**
  83.  * Initialize the alphabet either to str,
  84.  * or if str is NULL then from cstart to cstart+ablen-1
  85.  ************************************************************/
  86. int ab_init( Alphabet *ab, const char *str, const char cstart, const int ablen )
  87. {
  88. int i = 0, len = 0;
  89.  
  90. /* sanity check */
  91. if ( !ab )
  92. return 0; /* FALSE */
  93.  
  94. ab->len = 0;
  95.  
  96. /* when str exists and is not empty */
  97. if ( str && *str )
  98. {
  99. len = strlen( str );
  100. ab->str = calloc(len+1, sizeof(char) );
  101. if ( !ab->str )
  102. return 0; /* FALSE */
  103. strcpy(ab->str, str);
  104. ab->len = len;
  105. }
  106.  
  107. /* when str is NULL or empty, fill alphabet from cstart to (cstart+ablen-1) */
  108. else if (cstart > '\0' && ablen > 0 && cstart + ablen - 1 < 256)
  109. {
  110. ab->str = calloc(ablen+1, sizeof(char) );
  111. if ( !ab->str )
  112. return 0; /* FALSE */
  113.  
  114. for (i=0; i < ablen; i++)
  115. ab->str[i] = cstart + i;
  116. ab->len = ablen;
  117. }
  118.  
  119. /* error */
  120. else
  121. return 0; /* FALSE */
  122.  
  123. return 1; /* TRUE */
  124. }
  125.  
  126. /*********************************************************//**
  127.  * Cleanup the alphabet structure
  128.  ************************************************************/
  129. void ab_cleanup( Alphabet *ab )
  130. {
  131. if ( !ab )
  132. return;
  133.  
  134. if ( ab->str )
  135. free( ab->str );
  136. ab->len = 0;
  137. ab->str = NULL;
  138.  
  139. return;
  140. }
  141.  
  142. /*********************************************************//**
  143.  * Get the alphabet index of a given char ( -1 if char is not in alphabet )
  144.  ************************************************************/
  145. int abindex( const char c, const Alphabet *ab)
  146. {
  147. char *cp = NULL;
  148.  
  149. if ( !ab || !ab->str || !*(ab->str) )
  150. return -1;
  151.  
  152. return (cp = strchr(ab->str,c)) ? (int)(cp - ab->str) : -1;
  153. }
  154.  
  155. /*********************************************************//**
  156.  * Encrypt a given char with a given Caesar key.
  157.  * http://e...content-available-to-author-only...a.org/wiki/Caesar_cipher#Example
  158.  ************************************************************/
  159. char c_encrypt( const char c, const int keyval, const Alphabet *ab )
  160. {
  161. int idx = -1;
  162.  
  163. /* sanity checks */
  164. if (!ab || !ab->str || !*(ab->str) || -1 == (idx=abindex(c,ab)) || keyval < 0)
  165. return '\0';
  166.  
  167. return ab->str[ (idx + keyval) % ab->len ];
  168. }
  169.  
  170. /*********************************************************//**
  171.  * Decrypt a given char that was encrypted with a given Caesar key.
  172.  * http://e...content-available-to-author-only...a.org/wiki/Caesar_cipher#Example (
  173.  ************************************************************/
  174. char c_decrypt( const char c, const int keyval, const Alphabet *ab )
  175. {
  176. int idx = -1;
  177.  
  178. /* sanity checks */
  179. if (!ab || !ab->str || !*(ab->str) || -1 == (idx=abindex(c,ab)) || keyval < 0)
  180. return '\0';
  181.  
  182. idx = (idx - keyval) % ab->len;
  183. if ( idx < 0 )
  184. idx += ab->len;
  185.  
  186. return ab->str[ idx ];
  187. }
  188.  
  189. /*********************************************************//**
  190.  * Encrypt a given c-string with a given key, using the Caesar algorithm
  191.  ************************************************************/
  192. char *s_encrypt( char *s, const int keyval, const Alphabet *ab )
  193. {
  194. int i = 0;
  195.  
  196. /* sanity checks */
  197. if ( !ab || !ab->str || !*(ab->str) || !s || !*s || keyval < 0 )
  198. return NULL;
  199.  
  200. for (i=0; s[i]; i++)
  201. if ( '\0' == (s[i] = c_encrypt(s[i], keyval, ab)) )
  202. return NULL;
  203. return s;
  204.  
  205. }
  206.  
  207. /*********************************************************//**
  208.  * Decrypt a given c-string that was encrypted with a given Caesar key.
  209.  ************************************************************/
  210. char *s_decrypt( char *s, const int keyval, const Alphabet *ab )
  211. {
  212. int i = 0;
  213.  
  214. /* sanity checks */
  215. if ( !ab || !ab->str || !*(ab->str) || !s || !*s || keyval < 0 )
  216. return NULL;
  217.  
  218. for (i=0; s[i]; i++)
  219. if ( '\0' == (s[i] = c_decrypt(s[i], keyval, ab)) )
  220. return NULL;
  221. return s;
  222.  
  223. }
  224.  
  225. /*********************************************************//**
  226.  *
  227.  ************************************************************/
  228. int main( void )
  229. {
  230. Alphabet ab = {NULL, 0 }; /* our alphabet */
  231. char text[ MAXINPUT ] = {'\0'}; /* text input */
  232. int key = 0; /* shifting value */
  233.  
  234. /* initialize and shuffle the alphabet */
  235. if ( !ab_init( &ab, NULL, ' ', 223 ) ) {
  236. puts("\nalphabet initialization failed!");
  237. goto exit_prog;
  238. }
  239. str_shuffle( ab.str );
  240. printf("Alphabet (%u chars):\n%s\n\n", ab.len, ab.str );
  241.  
  242. /* get the text to be encrypted */
  243. printf("Text to be ciphered: ");
  244. if ( *stdin_getstring(text) == '\0' ) {
  245. puts("\nempty text was given, nothing to cipher");
  246. goto exit_prog;
  247. }
  248.  
  249. /* get a valid, positive Caesar key */
  250. do
  251. printf("Key (0 or positive): ");
  252. while ( INT_MAX == stdin_getint( &key ) || key < 0 );
  253.  
  254. /* encrypt given text with the given Caesar key */
  255. if ( NULL == s_encrypt(text, key, &ab) ) {
  256. puts("\tencryption error (perhaps an invalid char was found in text)");
  257. goto exit_prog;
  258. }
  259. printf("\nEncrypted text: %s\n", text );
  260.  
  261. /* decrypt given text using given Caesar key */
  262. if ( NULL == s_decrypt(text, key, &ab) ) {
  263. puts("\tdecryption error (perhaps an invalid char was found in text)");
  264. goto exit_prog;
  265. }
  266. printf("Decrypted text: %s\n\n", text );
  267.  
  268.  
  269. exit_prog:
  270. pressENTER();
  271. ab_cleanup( &ab );
  272. exit( EXIT_SUCCESS );
  273. }
  274.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty