A Ceasar cipher encrypts a message by rotating each letter by k spaces. Since there is only one series of steps to take to encrypt and decrypt the message, it's not the most secure form of encryption. But todays exercise will do just that; shift a message by a designated number of spaces in the ASCII in C. Note: This exercise is part of Problem Set 2 in the CS50 course offered on edX.org.
Image may be NSFW.
Clik here to view.
First, the program should accept the number of spaces for the cipher as a command line argument. The user should then be prompted to enter the message they would like encrypted. Then they should have their new secret message printed as output.
Here's an example of how our program should run by the end:
Image may be NSFW.
Clik here to view.
There are some unique challenges in this exercise that you'll need to consider:
1. Using command line arguments
In order to access command line arguments in c, main
will need to accept 2 arguments: int argc
and char *argv[]
.
#include <stdio.h>
int main(int argc, char *argv[]) {
return 0;
}
The argc
integer contains a count of the number of arguments passed in the command line (including the program's name). argv[]
is an array of pointers to a string. argv[0]
will be the program's name and argv[1]
would be the value entered directly afterwards.
You'll need to use these 2 arguments to ensure that there were not too few or too many arguments given. Also, any arguments passed will be a string, you'll need to convert the string argument to an integer using the atoi function.
2. isalpha, isupper, islower
You'll need to make sure that the characters you encrypt are alphabetical. If the character is not alphabetical, it should be printed as is. You'll also need to be familiar with the isupper
and islower
functions in order to complete the exercise. Try running man isaplha
to learn more about what these functions do and how they can be included in your program.
3. not printing special characters
If the character Y
were entered as part of the message and a number of 2
, we want the alphabet to rotate back to the letter A so that 'Y' + 2 = 'A'
. If we just normally added 'Y' + 2
the result would be the number 91
which is ASCII character [
which is not what we want. Make sure that all characters are encrypted to alphabetical characters.
4. looping through chars
In order to loop through each character of the user's message, you'll need to take advantage of the strlen function.
And so, here is my solution to the Caesar cipher challenge in C.
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#define upperStart 65
#define lowerStart 97
int checkConsoleArgs(int);
string getCipherChars(string, int);
char encryptChar(int, int);
int main (int argc, string argv[]) {
// see if cipher was passed as argument during execute
checkConsoleArgs(argc);
// convert string arg to integer
int cipherNum = atoi(argv[1]);
printf("What would you like to encrypt?\n");
string decodedString = GetString();
// pass the string input and the cipher number to encrypt
getCipherChars(decodedString, cipherNum);
return 0;
}
int checkConsoleArgs (int consoleArgsCount) {
// this program was executed juuuuust right!
if(consoleArgsCount == 2) {
return 0;
// this program was executed with too few console arguments.
} else if(consoleArgsCount < 2) {
printf("This program requires a cipher as a console argument. Please try again.\n");
return 1;
// this program was executed with too many console arguments.
} else {
printf("Please enter only one cipher for the encryption.\n");
return 1;
}
}
string getCipherChars(string decodedString, int cipherNum){
int decodedStringLen = strlen(decodedString);
int newChar;
for(int i = 0; i < decodedStringLen; i++) {
newChar = decodedString[i];
// encrypt chars if it's alphabetical
if(isalpha(newChar)) {
encryptChar(newChar, cipherNum);
// print other chars as is.
} else {
printf("%c", newChar);
}
}
printf("\n");
return 0;
}
char encryptChar(newChar, cipherNum) {
char encryptedChar;
int indexStart;
// if uppercase char, set the index to start at uppercase ASCII start
if isupper(newChar) {
indexStart = upperStart;
// if lowercase char, set the index to start at lowercase ASCII start
} else {
indexStart = lowerStart;
}
// find alpha index of cipher
cipherNum = ((newChar - indexStart) + cipherNum) % 26;
// convert back to ASCII index of cipher
encryptedChar = indexStart + cipherNum;
printf("%c", encryptedChar);
return 0;
}