caesar.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h> //strtol
  4. #include <stdbool.h>
  5. #include <assert.h>
  6. #include <argp.h>
  7. /*
  8. I believe that I found a bug
  9. echo "Probably the simplest case is to decrypt a short sentence." | ./caesar -s 4 | ./caesar -s 22
  10. jrobably the simplest case is to decrypt a short sentence.
  11. ��[joshua@dobby c]$
  12. */
  13. #define DEFAULT_SHIFT 1
  14. #define A_CHAR 65
  15. #define Z_CHAR 90
  16. #define A_LOWER_CHAR 97
  17. #define Z_LOWER_CHAR 122
  18. /* This program opens a file outputs the file in a caesar cipher. */
  19. char fileName [128];
  20. short int shift = DEFAULT_SHIFT;
  21. const char * argp_program_version = "0.1";
  22. const char * argp_program_bug_address = "jbranso@fastmail.com";
  23. error_t argp_err_exit_status;
  24. static const struct argp_option options [] =
  25. {
  26. {"file" , 'f', "FILE", 0, "Output the caesar cipher of a file." },
  27. {"shift", 's', "INT", 0, "Specify the shift of the cipher." },
  28. { 0 }
  29. };
  30. //define an argp parse function
  31. error_t argp_parser (int opt, char *arg, struct argp_state *state)
  32. {
  33. extern char fileName [];
  34. extern short int shift;
  35. switch (opt)
  36. {
  37. // if this parser function is called on an option that it doesn't recognize, then don't do anything.
  38. default:
  39. return ARGP_ERR_UNKNOWN;
  40. case 'f':
  41. {
  42. //printf ("file is %s\n", arg);
  43. memcpy (fileName, arg, strlen (arg));
  44. break;
  45. }
  46. case 's':
  47. {
  48. shift = (int) strtol (arg, NULL, 0);
  49. if (shift < 0)
  50. shift = abs (shift);
  51. else if (shift > 26)
  52. shift = shift % 26;
  53. break;
  54. }
  55. }
  56. return 0;
  57. }
  58. struct argp argp =
  59. {
  60. options, argp_parser, 0,
  61. "A simple program implementing a caesar cipher.\nThe default shift is 1."
  62. };
  63. /* a string containing the basic usage of this program. */
  64. /* This decrypts letters.
  65. print_shift('a', 1) -> 'b'
  66. print_shift('B', 1) -> 'C'
  67. */
  68. void print_shifted (char c)
  69. {
  70. extern short int shift;
  71. short int upper;
  72. short int lower;
  73. if (isupper (c))
  74. {
  75. lower = A_CHAR;
  76. upper = Z_CHAR;
  77. }
  78. else if (islower(c))
  79. {
  80. lower = A_LOWER_CHAR;
  81. upper = Z_LOWER_CHAR;
  82. }
  83. else
  84. {
  85. assert(-1);
  86. }
  87. // if we add the "corrective" shift, and the resulting char is not
  88. // a letter, then we need to do tweak things.
  89. if (((int) c + shift) > upper)
  90. {
  91. int subn = upper - (int) c;
  92. int newShift = shift - (subn + shift);
  93. c = (char) (lower + newShift);
  94. putchar (c);
  95. }
  96. else
  97. {
  98. putchar ((char) ((int) c + shift));
  99. }
  100. }
  101. void encrypt (int shift, FILE * stream)
  102. {
  103. char c;
  104. while ((c = getc(stream)) != EOF)
  105. {
  106. //if the char is a number or punctionation, etc, print it.
  107. if (!(isalpha ((int) c)))
  108. putchar(c);
  109. else
  110. print_shifted(c);
  111. }
  112. }
  113. int main (int argc, char **argv) {
  114. extern char fileName [];
  115. extern short int shift;
  116. argp_parse (&argp, argc, argv, 0, 0, 0);
  117. FILE * stream;
  118. if ((stream = fopen (fileName, "r")) == NULL)
  119. {
  120. stream = stdin;
  121. }
  122. encrypt (shift, stream);
  123. fclose (stream);
  124. return 0;
  125. }