Skip to content

Instantly share code, notes, and snippets.

@Latishfaction
Last active January 21, 2024 04:46
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Latishfaction/b76758b11105e25342c0aac201d6d7e6 to your computer and use it in GitHub Desktop.
Save Latishfaction/b76758b11105e25342c0aac201d6d7e6 to your computer and use it in GitHub Desktop.
CS50 (cs50x) pset2 Substitution Solution 2020
#include <stdio.h>
#include <cs50.h> // to get plain text
#include <string.h> // for strlen()
#include <ctype.h> // for string operation upper, lower
void Do_substitute(); // for further substitute
void alpha_arr_val(char pos, string key);
// to get the alphabet array value of each plain text element (ex:plaintext = h|alphabet array = 8 {a=0, b=1 .....z=26})
int main(int argc, string argv[])
{
if (argc == 2) // number of commands in terminal
{
if (strlen(argv[1]) == 26)
{
for (int i = 0; i < strlen(argv[1]) ; i++) // checking each element of string
{
if (! isalpha(argv[1][i])) // if contain non-alphabet
{
printf("Key must contain 26 characters.\n");
return 1;
}
for (int j = i + 1 ; j < strlen(argv[1]) ; j++) // checking to the next element of arg[i]
{
if (toupper(argv[1][j]) == toupper(argv[1][i])) // checking repeated element
{
printf("Key must not contain repeated alphabets.\n");
return 1;
}
}
}
Do_substitute(argv[1]);
}
else
{
printf("Key must contain 26 characters.\n");
return 1;
}
}
else
{
printf("Usage: ./substitution key\n");
return 1;
}
return 0;
}
void Do_substitute(string key)
{
string p = get_string("plaintext: ");
printf("ciphertext: ");
for (int i = 0; i < strlen(p); i++)
{
if (isalpha(p[i])) // checking p[i] is alphabet
{
char x = p[i];
if (islower(p[i]))
{
alpha_arr_val(tolower(x), key); // passing p[i] in lower-case
}
else
{
alpha_arr_val(toupper(x), key); // passing p[i] in UPPER-CASE
}
}
else
{
printf("%c", p[i]); // print the element as it is (such as space | , | special characters | ? | etc...)
}
}
printf("\n");
}
void alpha_arr_val(char pos, string key) // passing p[i] and upper/lower(alpha array)
{
string alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // alphabet array
for (int i = 0; i < strlen(alpha); i++) // accessing each element in alpha array
{
if (islower(pos)) // p[i] is lower
{
if (pos == tolower(alpha[i]))
{
printf("%c", tolower(key[i]));
}
}
else // for UPPERCASE // p[i] is upper
{
if (pos == toupper(alpha[i]))
{
printf("%c", toupper(key[i]));
}
}
}
}
@abdullahkhancs50
Copy link

amazing

@Melopia131
Copy link

Why on line 29, you are using toupper functions ?

@Latishfaction
Copy link
Author

Why on line 29, you are using toupper functions ?

because, principle to Substitution is "The Key must not contain repeated alphabets". But user may accidentally enter repeated alphabets with different cases(like A,a) .so while checking(comparing )the repeated alphabets i make sure that both the alphabets should be of same cases, And if i didn't add "toupper()" the answer will always be false because of their ASCII values ex: A: 063, a: 097. And When "C-compiler" compares two character(alphabets), it uses their ASCII values to compare them internally . That's why i used toupper function to compare the two characters of same case to identify if user entered the same character, regardless of their cases and to maintain the rule of substitution cipher technique. hope you understand the problem.

@Aquaghost27
Copy link

Why in the for loop did you set j = i+ 1? where did the plus one come from?

@Aquaghost27
Copy link

also what does char, pos stand for

@Aquaghost27
Copy link

sorry for all the questions im new and really trying to understand this problem if you answer any ps answer this one. im extremely confused as to what is happening in the alphabet array value method

@Latishfaction
Copy link
Author

also what does char, pos stand for

"char" is the keyword in c language to define the type of value or a variable and "char" is the acronym of character, it means it represents in only character of an string (like string is "Hello" then char will be any single alphabet of given string ex:- char maybe "H") just as "int" represents any integer value like 1,2,74 and so on.

Here "pos" holds each character user has entered in the form of string as an input , and matching with the string it already has in it's memory (variable) as shown in line 90 (alphabet array), if match found then it replaces(substitute) the value with given character in the key (key is the non-repeating string given at the time of input.)

Hope this will satisfy your curiosity😉

@Latishfaction
Copy link
Author

Why in the for loop did you set j = i+ 1? where did the plus one come from?

suppose string = "Hello"(string(key) which will be given to the system as an input)

Take a look at line 17, i=1; which means i will be holding second character of our input string(e because string[1] is e),
now a rule of substitution is that it's key's" character must not be repeated.

So now we need to check the if there is any repeated character on the string, to compare the repeating characters we need the current character(e) and next character (l).
To write in equation if i=1 which is "e" then i+1(1+1 = 2), i=2 which is "l", hence we get the next character and on the line 29 we are comparing the two character by arranging them in same type (uppercase)
And i write it loop inside loop because in outer loop it holds one character and in the second it compares it all the way up to the last element.
if it find any repeated character it simply abort the program.

I recommend you to debug this program and go through the steps. It will help you for better understanding.

@A-Shankar-mahadevan
Copy link

wooow

@Ferenczy13
Copy link

Just finished this problem on my own. Man, your solution looks waaaaay better than mine. But Im pretty happy knowing I had some of the right instincts. The output function you wrote was especially slick. Nice work, I wanted to se what someone with a better handle on coding would do with it.

@Msspera
Copy link

Msspera commented May 24, 2021

Why does it return 1?

@fzmirsalim
Copy link

perfect bro

@kushy115
Copy link

on line 26, why does j have to equal to i+1 to test for repeated letters? I don't get the logic there

@A7med-Ma9dy
Copy link

you can make code smaller for the two functions Do_substitute && alpha_arr_val
void substitution (string key ,string plaintext)
{
printf("ciphertext: ");
for (int i = 0, len = strlen(plaintext); i < len; i++)
{
if (isalpha(plaintext[i]))
{
alpha_converter(key, plaintext[i]);
}
else
{
printf("%c",plaintext[i]);
}
}
printf("\n");
}


void alpha_converter (string key, char pi)
{
string alpha = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0, len = strlen(alpha); i < len; i++)
{
if (tolower(pi) == alpha[i])
{
if (islower(pi))
{
printf("%c", tolower(key[i]));
}
else
{
printf("%c", toupper(key[i]));
}
}
}
}

@hansthebeas
Copy link

Thanks a lot

@zehraina
Copy link

How can I solve the error "could not find ciphertext in plaintext"? Any help?

@the-boshi
Copy link

beautiful

@anannt14
Copy link

anannt14 commented Jan 7, 2023

what is the point of this :
if (islower(p[i]))
{
alpha_arr_val(tolower(x), key); // passing p[i] in lower-case
}
else
{
alpha_arr_val(toupper(x), key); // passing p[i] in UPPER-CASE
}

on line 68
because we are doing the same thing on the line 94

@Tomi-3-0
Copy link

Tomi-3-0 commented Jan 9, 2023

#line 6 you might consider removing the check_key () function on line 6, seems redundant.
#line 61 you couldmerge the printf("ciphetext: ") statement on line 61 and merged it with that on line 81.

@Latishfaction
Copy link
Author

#line 6 you might consider removing the check_key () function on line 6, seems redundant. #line 61 you couldmerge the printf("ciphetext: ") statement on line 61 and merged it with that on line 81.

Dear @Tomi-3-0 ,
Thankyou for your suggestion on #line 6 , the checkey() function was declared but never initialized, I've updated the changes.

#line 61, if we try to merge the printf's on line 61 and line 81, since it is written inside the loop we see "ciphertext : " repeatedly which may be not look pleasing as per viewing experience. But I encourage you to try to merge the lines as per your convenience. :)

@Latishfaction
Copy link
Author

Why does it return 1?

return 1 means interrupting the execution of a code and aborting the program. Please notice line no 21,30, 41,48 these printf statements are indicating error, and to terminate the program so that it will not move further we use return 1 (because the main function is initialized with int return type).
return 0 for successfully exiting from the program.

@Aquaghost27
Copy link

Aquaghost27 commented Nov 13, 2023 via email

@mohawkart
Copy link

mohawkart commented Jan 21, 2024

Why does it return 1?

Return 1 is another thing for saying that if the input doesn't meet the requirement, it will assume it is false and stop the function and go the next function rather than repeating it, causing errors, and stopping it from going to the next function. Similarly, return 0 is the opposite, it means it will return true, stop the function, and move to the next function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment