15 49.0138 8.38624 1 0 4000 1 http://www.houseninetytwo.com 300 true 0

# cs50 Pset2: Caesar’s cipher solution explained

Oh Jeebus, so last week I completed the Mario task which wasn’t actually too hard.

Then I moved on because the Credit task was a little bitch. One of my old school friends Nick has been trying to help me on Linked in (whilst he’s travelling/working remotely LOL) he told me to break the problem down and solve EACH section separately first. I was completely stuck so I decided to leave the “MORE” comfortable tasks and focus on completing the “LESS” comfortable ones first.

So this “LESS” comfortable one also F’d me up. I was on this one for about 2 weeks. I started avoiding it and put it off for a while because I found it too difficult. I finally managed to finish it after crying myself to sleep every night from the feelings of inadequacy (kidding). I ended up researching  a shit ton online for the ‘key’ section because I was so stuck.

I will explain in this walkthrough my solutions of how I completed this problem set step by step.

## The Caesar Cipher

For pset2 the task was to create a Caesar cipher which would be a Key to ‘encrypting’  a word. It is known as the “shift cipher” as the letters of one alphabet are shifted a number of steps against another alphabet to create a secret message. It was created by Julius Caesar so that he could communicate secretly with his army.

First of all the cs50 provided a walkthrough teaches you how to use a function properly and put in this new ‘argument’ thing I have never seen before…

```int main(int argc, string argv[]) { } ```

I was like wtf is this shit? I spent about a week confused despite reading up and watching the lectures multiple times. NOW I finally get it. So the first argument/parameters entered is defining how many strings are in the array of argv. The amount should be an integer NOT a character so you put the int in front to define the type. argv[0] will be the program name that you type into the terminal which would be

`./caesar`

so we should be looking for argv[1] which would be the next one in the array which would also be used as the key.

`./caesar [key]`

This means we need to re-call for the argv[1] and put it into a new variable to use in the program as the key number. Let’s call this k

`int k = argv[1]`

This thing is in the requirements we must use an integer as the key so even if a number is inputted it will be considered a ‘string’ because so we need to convert it to a number. This is where atoi comes in.

`int k = atoi(argv[1]);`

As atoi is declared in stdlib.h library as the HINTS section explains to you in this set I needed to include it into the top bit.

`#include <stdlib.h>`

There should also only be 2 arguments in the array anymore would corrupt the algorithm as you only need the program name then the key so I did an if statement argc doesn’t = 2 then the error requirement status would appear stating the format you need to input for the program to work.

```if (argc != 2) { printf("Usage: ./caesar k\n"); return 1; }```

Then I needed to actually ask for the specific word to encrypt from the user. I did this by using get_string.

`string s = get_string("plaintext: "); // get text`

Then in order to cypher the word I needed to:

• Iterate through each letter one by one to figure out whether it’s lowercase or uppercase.
• I would do this by converting it into it’s ASCII value and checking if it’s between the smallest & largest value.
• Turning it into ASCII value will also help me shift the alphabet a couple of characters across easier.
• I also needed to keep it within A-Z boundaries so when I shift the whole alphabet and some of them go beyond Z it would need to circle back around and count in from A again.
• I need to minus the lower ASCII value (a or A) so it starts from 0 and goes up to 25 so it’s easier to modulo it by 26
• I need to re-add the ASCII value on to find it’s place in ratio to the beginning of the lower ASCII.
• Any other characters will be kept the same and re-print out without ciphering.

First, I need to figure out each individual character of the string I get from “get_string”.

```for (int i = 0, n = strlen(s) ; i < n; i++) { }```

strlen(STRING) is the string length so if n is the total length of the word given then we can iterate n times so that we check out each individual character of the string and then i++ helps move it onto the next one.

Then I needed to figure out whether the individual character is uppercase or lowercase I did so by doing an if statement to show that if it is in between ‘A’ and ‘Z’ or ‘a’ and ‘z’ then it would convert it using the key and print out the new letter. Then the rest that isn’t in the alphabet at all will just print out as it is.

```if (s[i] >= 'a' && s[i] <= 'z') { } //```

So for this one, I would be doing lowercase as I am using the characters in the context of numerical values it automatically changes to it’s ASCII value. So if I was to move the character say 4 to the right. I would need to add on how many extras it would along in ASCII terms. It usually is the same.

This is where I got REALLY stuck. The pset provided this caesar’s algorithm thing as this equation.

`c[i]=(p[i]+k)mod26`

I’m like okay so for my code it would be

`new cipher letter = (s[i] + k) % 26`

But it wouldn’t work! I decided to put in actual letters to see what would come out. So imagine the key was 2 and I wanted to convert a lowercase b that is 98. We would simply add 98+2 and that would make 100. Then I would 100 % 26 = 22. Um nope.

I did some digging and found this post by Johny Zaguirre and he explains what modulo is in terms of a ‘bucket’. Which was way easier to digest. I was honestly, searching for days what it was.  This is what he said…

```Imagine we have a bucket that holds 10 cups of water. Modulo will dump out the water each time it gets full. If we give module 22 cups, or 22 % 10, modulo will say: max is 10 filling up 10 out of 10, cup is full so dump it out filling up 10 out of 10, cup is full so dump it out filling up to 2...not a full cup so return giving us 2.```

So the same thing in terms of the alphabet is…
```2 % 26 fill up to 2...not the entire alphabet so return giving us 2```

Thank you, Johny my gawd. I was racking my brains in trying to understand what purpose modulus had in life. It seems it IS rather useful.

So how would I cipher the text still? Because clearly just doing (text + key) % 26 does not work. Well I’ve somehow worked this out step by step from learning actually what the bloody modulo thing does lol.

I need to work out how many steps from the beginning of the alphabet is the g minus the starting point of the lower ASCII.  Then I need to + the key onto that and then modulo that by 26 to make sure we’re not going past the alphabet and that whatever is left over we count back in from the beginning of the alphabet and add on the ASCII equivalent  = WTF am I talking about.

Let’s try using some actual letters as examples.

```cipher key = 2 letter I want to cipher = g g in ASCII = 103 we know that g + key = 103 + 2 = 105```

What we need to know is where is g in respect to the beginning of the alphabet. As it is lowercase we will be using ‘a’ as the beginning which has the ASCII value of 97 we need to get back to the beginning of the alphabet so we have to minus the ‘a’ to get back to 0.

```g - a = 103 - 97 = 6 ```

Brings us back to the beginning of the alphabet to know how far is g from the start. It is 6 from the start.

Then we want to add the key onto that to see how much it has been shifted.

`6 + 2 = 8`

Because we want to keep it within the alphabetical boundaries and as there are 26 characters we modulo the 8 by 26. Just incase it goes over 26 we want to know how much extra is left over. If there is any left over then that would be how many characters in from 0 again. Just like how the bucket overflows scenario stated earlier.

`8 % 26 = 8`

Then because it has been shifted 8 times from the beginning we have to start it off from where ‘a’ starts which isn’t 0 in the ASCII chart. It is 97. So we add that to 97.

`8 + 97 = 105`

So here you have it…

`(s[i] - 'a' + k) % 26) + a`

I tried that and it didnt work. FML I think I have to use BODMAS so I rejigged the brackets in the code and it worked HUZZAH!!!!!

` (((s[i] - 'a') + k) % 26) + 'a')`

This one killed me and I’m only on pset2 of 9. Despite dying over modulo maths I actually love doing this. It’s so fun!

The rest of the code was easy. I printed out the characters that weren’t alphabets and then return 0 and ended the program.

Here is my GitHub which I managed to connect to the cs50 IDE or my code:

Source: photo by Sergi Kabrera on Unsplash

Bexa

An avid explorer, learner and adventure finder. Loves being a typical tourist as well as going off on the beaten track. Favourite thing about blogging is having a place to store findings, thoughts, experiences. City girl by nature but nature lover by heart.

• 3rd October 2018 at 7:40 pm

Hey Bexa! I’m so glad you found my article helpful. It totally brightened my day!

Kind Regards,
*Johnny Yzaguirre 😉

• 13th February 2019 at 2:14 pm
Jin

Hi, thanks so much for your post; im really struggling to understand caesar and this post made it easier. I do have one question for the part on “Then because it has been shifted 8 times from the beginning we have to start it off from where ‘a’ starts which isn’t 0 in the ASCII chart. It is 97. So we add that to 97.” What does this mean? I am struggling to understand why we need to add +97 again after %26. Thank you so much!

• 2nd April 2019 at 2:07 am
asdf

I found out after completing this that you can substitute islower() for s[i] >= ‘a’ && s[i] <= 'z' or isupper() for the upper cases

• 15th April 2019 at 10:13 am
andrea

But If I submit a string like this 50x I don’t receive an error like the staff’s solution sandbox.
https://sandbox.cs50.io/c469d529-beed-4ca8-b9f6-06f6bf76ef2b

• 26th April 2019 at 12:52 pm

What happens when the user enters a key like 12xyz? The code ignores the alphabetical part of the key, even though it should be showing an error.

• 25th May 2019 at 6:58 pm
Elena

Thanks for your explanation of how you performed the calculation! It saved me so much time.

• 2nd June 2019 at 10:09 am
Ork

Dear Bexa,

that’s a very nice solution. Mine was more complicated:

HOWEVER, yours in not exactly correct, because if we input non-integer as a code, it won’t give us an error, but it should:

\$ ./your_compiled_solution abc
plaintext: text_to_be_encrypted
ciphertext: text_to_be_encrypted
\$

So it accepted “abc”, but it shouldn’t.

To solve this I used this:

if (isdigit(argv[1][j]) && argv[1][j] >= 0)

===
And my solution for encrypting letters which is more complicated than yours:

// Encrypting
for (int i = 0, n = strlen(text); i = ‘a’ && text[i] ‘z’)
{
printf(“%c”, ‘a’ + ((text[i] + number % 26) % ‘z’) – 1);
}
else
{
printf(“%c”, text[i] + (number % 26));
}
}

else if (text[i] >= ‘A’ && text[i] ‘Z’)
{
printf(“%c”, ‘A’ + ((text[i] + number % 26) % ‘Z’) – 1);
}
else
{
printf(“%c”, text[i] + (number % 26));
}
}

else
{
printf(“%c”, text[i]);
}
}

• 3rd June 2019 at 5:21 pm
gavin

this is life saving

• 4th June 2019 at 9:49 am

Hey thanks for your write up. Im going through the same thoughts…sitting in the library today thinking what have I got myself into? And…I barely understand the “help” pieces on the side!! Anyway, very nice to know Im not the only one with confused feelings and to take the task step by step.

• 19th July 2019 at 5:50 am
Parag Jain

Just a question. I applied same as you did but it is giving successful result even on ./caesar 20x and on ./caesar hello though 20x and hello are non integer… What should I do ?

• 29th July 2019 at 9:59 am

Hey Prag Jain,

ORK gave a really good reply in a couple of comments above you that resolves this issue

• 8th August 2019 at 1:15 pm
Max

Hi everyone! I’ve just got completely confused with tis task. The thing is my programm can’t manage right all the cases of user input. Here is what I mean:
when I type “./caesar h”, “./caesar 4 5”, “./caesar gh g” or “./caesar g7” for instance, it returns “Usage: ./caesar key”.
But when i type “./caesar 7g” programm keeps working, because it takes just “7” as an input. Not “7g”. What is the problem?
My code:
#include
#include
#include
#include
#include

int main(int argc, string argv[])
{

if(argc != 2)
{
printf(“You are stupid. \nUsage: ./caesar key \n”);
return 1;
}
else
{
int i = atoi(argv[1]);
if(i == 0)
{
printf(“You are stupid. \nUsage: ./caesar key \n”);
}
else
{
printf(“%i \n”, i);
string pt = get_string(“Plaintext:”);
}
}
}

P.S. I understand that it looks messy and normal code has something to do with “ctype.h” library to check whether every char in argv[1] is digital. But i don’t know, how to use those functions