This Caesar cipher can take any integer and it will wrap around the correct number of times and still perform the encryption/decryption.
Let's say we have a text file named dog
.
~$ cat dog
The quick brown fox jumps over the lazy dog...
If the user enters a normal offset (1-26), it will perform like any other Caesar cipher.
~$ ./caesar dog 1
~$ cat dog
Uif rvjdl cspxo gpy kvnqt pwfs uif mbaz eph...
Negative numbers can be used to shift backwards.
~$ ./caesar dog -1
~$ cat dog
The quick brown fox jumps over the lazy dog...
Now, here's the beauty of it. Choosing an offset of 1 is no different then choosing an offset of, say, 53 or -51. This algorithm will correctly wrap around.
~$ ./caesar dog -51
~$ cat dog
Uif rvjdl cspxo gpy kvnqt pwfs uif mbaz eph...
~$ ./caesar dog 51
~$ cat dog
The quick brown fox jumps over the lazy dog...
I wrote this a long time ago and I posted it on some other programming site back in the day. I haven't really written much pure c
code since. I'm guessing there's plenty of room for improvement.
Compiles with:
gcc -ansi -pedantic -Wall -Werror -O3 -o caesar caesar.c
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* #define offset (-1) */ /* My chosen default offset */
#define lstart (0x61) /* Start of lowercase ASCII alphabet */
#define ustart (0x41) /* Start of uppercase ASCII alphabet */
#define nalpha 26 /* Number of letters in my alphabet */
int main(int argc, char **argv) {
int ec, wrap, offset;
FILE *fp;
if (argc != 3) {
fprintf(stderr, "Usage: %s <filename> <offset>\n", argv[0]);
return 1;
}
fp = fopen(argv [1], "r+b");
offset = atoi (argv[2]);
if(!fp) {
fprintf(stderr, "Error: could not open file!\n");
return 1;
}
while((ec = fgetc(fp)) != EOF) {
if(isalpha(ec)) {
if(islower(ec)) {
wrap = (ec + offset - lstart) % nalpha;
wrap = (wrap < 0) ? nalpha + wrap : wrap;
} else {
wrap = (ec + offset - ustart) % nalpha;
wrap = (wrap < 0) ? nalpha + wrap : wrap;
}
ec = islower(ec) ? wrap + lstart : wrap + ustart;
fseek(fp, -1L, SEEK_CUR);
fputc(ec, fp);
}
}
fclose(fp);
return 0;
}
Update: I will leave the code I originally posted above. Any modifications that I make will be posted below.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define NALPHA (26)
int main (int argc, char **argv) {
int ec, offset ;
FILE *fp ;
if (argc != 3) {
fprintf(stderr, "Usage: %s <filename> <offset>\n", argv[0]);
return 1;
}
fp = fopen(argv[1], "r+b");
offset = atoi(argv[2]);
if (!fp) {
fprintf(stderr, "Error: Could not open file: %s\n", argv[1]);
return 1;
}
while ((ec = fgetc(fp)) != EOF) {
if (isalpha(ec)) {
const int ascii_offset = islower (ec) ? 'a' : 'A';
int wrap = (ec + offset - ascii_offset) % NALPHA;
if (wrap < 0) {
wrap += NALPHA ;
}
ec = wrap + ascii_offset;
}
fputc(ec, stdout);
}
fclose(fp);
return 0;
}