-
-
Save teeschorle/cc998f1ef47e270282d3d4fa3d217d31 to your computer and use it in GitHub Desktop.
//CS50 Problem Set 2 (Fall 2019): Substitution | |
//Author: teeschorle | |
#include <stdio.h> | |
#include <cs50.h> | |
#include <string.h> | |
#include <ctype.h> | |
bool validate(string key); | |
int main(int argc, string argv[]) | |
{ | |
if (argc == 2) | |
{ | |
string key = argv[1]; | |
if (validate(key) == true) | |
{ | |
string plaintext = get_string("plaintext: "); | |
int charcount = strlen(plaintext); | |
char ciphertext[charcount]; | |
string abc = "abcdefghijklmnopqrstuvwxyz"; | |
for (int i = 0; i < charcount; i++) | |
{ | |
if (isupper(plaintext[i]) != 0) | |
{ | |
for (int j = 0; j < 26; j++) | |
{ | |
if(abc[j] == tolower(plaintext[i])) | |
{ | |
ciphertext[i] = toupper(key[j]); | |
break; | |
} | |
} | |
} | |
else if (islower(plaintext[i]) != 0) | |
{ | |
for (int j = 0; j < 26; j++) | |
{ | |
if(abc[j] == plaintext[i]) | |
{ | |
ciphertext[i] = tolower(key[j]); | |
break; | |
} | |
} | |
} | |
else | |
{ | |
ciphertext[i] = plaintext[i]; | |
} | |
} | |
printf("ciphertext: %s\n", ciphertext); | |
return 0; | |
} | |
else | |
{ | |
printf("Please make sure your key is a permutation of all 26 characters - not more, not less.\n"); | |
return 1; | |
} | |
} | |
else | |
{ | |
printf("Input error. Please provide a single key.\n"); | |
return 1; | |
} | |
} | |
bool validate(string key) | |
{ | |
int matches = 0; | |
if (strlen(key) == 26) | |
{ | |
for (char c = 'a'; c <= 'z'; c++) | |
{ | |
for (int i = 0; i < 26; i++) | |
{ | |
if(tolower(key[i]) == c) | |
{ | |
matches++; | |
break; | |
} | |
} | |
} | |
if(matches == 26) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
else | |
{ | |
return false; | |
} | |
} |
check if you returned false for loop.
you have to return it out of the for loop.
Easy fix just minus 1 at the char ciphertext[length -1];
Your solution is more elegant that mine although mine compiles just fine. I would've assumed that printf wouldn't correctly print your char array because it's not null-terminated but I tried compiling and testing yours and it works fine. Odd.
After using check50, they are showing me the these-
:( encrypts "A" as "Z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key
output not valid ASCII text
:( encrypts "a" as "z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key
output not valid ASCII text
:( encrypts "ABC" as "NJQ" using NJQSUYBRXMOPFTHZVAWCGILKED as key
output not valid ASCII text
:( encrypts "XyZ" as "KeD" using NJQSUYBRXMOPFTHZVAWCGILKED as key
output not valid ASCII text
but on running the code, I am getting the desired output for each of them.
then why is it showing "output not valid ASCII code" ?
After using check50, they are showing me the these-
:( encrypts "A" as "Z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key
output not valid ASCII text
:( encrypts "a" as "z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key
output not valid ASCII text
:( encrypts "ABC" as "NJQ" using NJQSUYBRXMOPFTHZVAWCGILKED as key
output not valid ASCII text
:( encrypts "XyZ" as "KeD" using NJQSUYBRXMOPFTHZVAWCGILKED as key
output not valid ASCII text
but on running the code, I am getting the desired output for each of them.
then why is it showing "output not valid ASCII code" ?
Could you link me to your code? I can't tell what the problem is just by the error messages
Hi, here it is.
https://github.com/ayanika02/substitution.git
Hey, thanks for the post
I am having a set of mistakes when I run the check50 on my code which I spend the last 3 hours trying to figure out but nothing..
I was checking your solution here and it's fundamentally same as mine, and that was even more troubling! so I copied and run your own code and got the exact same problems :/ please someone explain:Results for cs50/problems/2020/x/substitution generated by check50 v3.0.10
:) substitution.c exists
:) substitution.c compiles
:( encrypts "A" as "Z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key output not valid ASCII text :( encrypts "a" as "z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key output not valid ASCII text :( encrypts "ABC" as "NJQ" using NJQSUYBRXMOPFTHZVAWCGILKED as key output not valid ASCII text :( encrypts "XyZ" as "KeD" using NJQSUYBRXMOPFTHZVAWCGILKED as key output not valid ASCII text
:) encrypts "This is CS50" as "Cbah ah KH50" using YUKFRNLBAVMWZTEOGXHCIPJSQD as key
:) encrypts "This is CS50" as "Cbah ah KH50" using yukfrnlbavmwzteogxhcipjsqd as key
:) encrypts "This is CS50" as "Cbah ah KH50" using YUKFRNLBAVMWZteogxhcipjsqd as key
:) encrypts all alphabetic characters using DWUSXNPQKEGCZFJBTLYROHIAVM as key
:) handles lack of key
:) handles invalid key length
:) handles invalid characters in key
:) handles duplicate characters in key
:) handles multiple duplicate characters in key
If anyone is struggling with this like I did, its highly likely that we created this "ciphertext" been working differently as we expected.
if you recall from the lecture, all string has an char of '\0' at the end of it. If we loop through our plaintext and 'append'/put the ciphered character into this new array, you would need to add '\0' at ciphertext[strlen(plaintext)] to finish up the string. Or i guess something to do with the memory structure, it will add random chars at the end of the operations.
In short: add the extra char '\0' at the end of your ciphered text.
include <stdio.h>
include <cs50.h>
include <string.h>
include <ctype.h>
bool check(string key);
int main(int argc, string argv[])
{
if (argc == 2)
{
string key = argv[1];
if (check(key) == true)
{
string text = get_string("Enter plaintext : ");
int textlenth = strlen(text);
char cipher[textlenth];
string alpha = "abcdefghijklmnopqrstuvwxyz";
for (int j = 0; j < textlenth; j++)
{
if (isupper(text[j]) != 0)
{
for (int k = 0; k < 26; k++)
{
if (alpha[k] == tolower(text[j]))
{
cipher[j] = toupper(key[k]);
break;
}
}
}
else if (islower(text[j]) != 0)
{
for (int k = 0; k < 26; k++)
{
if (alpha[k] == text[j])
{
cipher[j] = tolower(key[k]);
break;
}
}
}
else
{
cipher[j] = text[j];
}
}
cipher[textlenth] = '\0';
printf("ciphertext: %s\n", cipher);
return 0;
}
else
{
printf("Usage: ./substitution key\n");
return 1;
}
}
else
{
printf("Usage: ./substitution key\n");
return 1;
}
}
bool check(string key)
{
int same = 0;
if (strlen(key) == 26)
{
for (char c = 'a'; c <= 'z'; c++)
{
for (int n = 0 ; n < 26; n++)
{
if (tolower(key[n]) == c)
{
same++;
break;
}
}
}
if (same == 26)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
Hi all,
I am writing this to help all of those who ran into a similar issue with the code not passing all test cases and returning random characters at the end. This is because we are dealing with adding chars to a new array and returning that new array as a string. Recall from the lectures that a string ends with '\0' so the code does not pass all cases because it's returning as a string of chars but no '\0'
Please find code attached for your reference
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
bool validate(string key);
int main(int argc, string argv[])
{
if (argc == 2)
{
string key = argv[1];
if(validate(key) == true)
{
string plaintext = get_string("plaintext: ");
int charcount = strlen(plaintext);
char ciphertext[charcount];
string abc = "abcdefghijklmnopqrstuvwxyz";
for(int i = 0; i < charcount; i++)
{
if(isupper(plaintext[i]) != 0)
{
for(int j = 0; j < 26; j++)
{
if(abc[j] == tolower(plaintext[i]))
{
ciphertext[i] = toupper(key[j]);
break;
}
}
}
else if(islower(plaintext[i])!=0)
{
for(int j = 0; j < 26; j++)
{
if (abc[j] == plaintext[i])
{
ciphertext[i] = tolower(key[j]);
break;
}
}
}
else
{
ciphertext[i] = plaintext[i];
}
}
ciphertext[charcount] = '\0';
printf("ciphertext: %s\n", ciphertext);
return 0;
}
else
{
printf("Please make sure your key is a permutation of all 26 characters - not more, not less.\n");
return 1;
}
}
else
{
printf("Input error. Please provide a key.");
return 1;
}
}
bool validate(string key)
{
int matches = 0;
if (strlen(key) == 26)
{
for (char c = 'a'; c <= 'z'; c++)
{
for (int i = 0; i < 26; i++)
{
if(tolower(key[i]) == c)
{
matches++;
break;
}
}
}
if(matches == 26)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
include <stdio.h>
include <cs50.h>
include <string.h>
include <ctype.h>
bool check(string key);
int main(int argc, string argv[])
{
if (argc == 2)
{string key = argv[1]; if (check(key) == true) { string text = get_string("Enter plaintext : "); int textlenth = strlen(text); char cipher[textlenth]; string alpha = "abcdefghijklmnopqrstuvwxyz"; for (int j = 0; j < textlenth; j++) { if (isupper(text[j]) != 0) { for (int k = 0; k < 26; k++) { if (alpha[k] == tolower(text[j])) { cipher[j] = toupper(key[k]); break; } } } else if (islower(text[j]) != 0) { for (int k = 0; k < 26; k++) { if (alpha[k] == text[j]) { cipher[j] = tolower(key[k]); break; } } } else { cipher[j] = text[j]; } } cipher[textlenth] = '\0'; printf("ciphertext: %s\n", cipher); return 0; } else { printf("Usage: ./substitution key\n"); return 1; } } else { printf("Usage: ./substitution key\n"); return 1; }
}
bool check(string key)
{
int same = 0;if (strlen(key) == 26) { for (char c = 'a'; c <= 'z'; c++) { for (int n = 0 ; n < 26; n++) { if (tolower(key[n]) == c) { same++; break; } } } if (same == 26) { return true; } else { return false; } } else { return false; }
}
Thanks! This really help me out this problem
those answers are so long and complicated. Here is my solution:
`#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
bool check (string s);
bool check (string s)
{
int j, j2;
if (strlen(s) != 26)
{
return false;
}
for (j = 0; j < strlen(s); ++j)
{
for (j2 = j + 1; j2 < strlen(s); ++j2)
{
if (s[j]==s[j2])
{
return false;
}
}
}
for (j = 0; j < strlen(s); ++j)
{
if (isalpha(s[j])==0)
{
return false;
}
}
return true;
}
int main(int c5, string v[])
{
if (c5 != 2)
{
printf ("Wrong Input type. Exp: ./subtitution VcHpRzGjNtLsKfBdQwAxEuYmOi\n");
return 1;
}
int sl = strlen(v[1]);
string cr = v[1];
if (check(v[1])==true)
{
char carr [2][26], c2 [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int j = 0; j<26;++j)
{
carr[0][j] = cr[j];
carr[1][j] = c2[j];
}
string p2 = get_string("Plain Text: ");
string p3=p2;
int b = 0;
for (;b<strlen(p2); ++b)
{
for (int g = 0; g<26; ++g)
{
if (p2[b] == tolower(carr[1][g]))
{
p3[b] = tolower(carr[0][g]);
break;
}
else if (p2[b] == carr[1][g])
{
p3[b] = toupper((carr[0][g]));
break;
}
else
p3[b] = p2[b];
}
}
printf ("ciphertext: %s\n", p3);
}
else
{
printf ("Key must contain 26 characters.\n");
return 1;
}
}`
Since every one is posting their codes here I thought why not do the same. If some one reads this, please critique on my code so I get better at coding. thankyou :)
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
string ciphertext(string plain, string key);
int main(int argc, string argv[])
{
//To check if arguments are 2 and numeric
if (argc == 2)
{
string key = (argv[1]);
if (strlen(key) == 26) //To check key length
{
printf("%s\n", key);
for (int i = 0; (key[i]) != '\0'; i++)
{
if (isdigit(key[i])) //To check if key conatains digit
{
printf("Key must only cntain alphabetic characters.\n");
return 1;
}
if (isalpha(key[i])) //To check if key is alphabetical //To check if alphabet is double in key
{
for (int j = i + 1; key[j] != '\0'; j++)
{
if (key[i] == key[j])
{
printf("Key must not contain repeated characters.\n");
return 1;
}
}
}
}
//main code
string plain = get_string("plaintext:");
string cipher = ciphertext(plain, key); //calling function to cipher
printf("ciphertext: %s\n", cipher);
return 0;
}
else //To check length of key
{
printf("Key must contain 26 characters.\n");
return 1;
}
}
if (argc != 2) //To check if arguments are 2
{
printf("Usage: ./substitution key\n");
return 1;
}
}
string ciphertext(string plain, string key)
{
string c = plain;
string k = key;
string abc = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; plain[i] != '\0'; i++)
{
if (islower(plain[i]) != 0)
{
for (int j = 0; k[j] != '\0'; j++)
{
if (abc[j] == (plain[i]))
{
c[i] = tolower(k[j]);
break;
}
}
}
else if (isupper(plain[i]) != 0)
{
for (int j = 0; k[j] != '\0'; j++)
{
if (toupper(abc[j]) == plain[i])
{
c[i] = toupper(k[j]);
break;
}
}
}
else
{
c[i] = plain[i];
}
}
return c;
}
This function returns a non-zero int if c is an uppercase letter and 0 if c is not an uppercase letter.
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, string argv[])
{
if (argc != 2 || !isalpha(*argv[1]))
{
printf("Usage: ./sub key\n");
return (1);
}
string key = argv[1];
if (strlen(key) != 26)
{
printf("Usage: ./sub key\n");
return (1);
}
string s = get_string("Plaintext: ");
printf("Ciphertext: ");
for (int i = 0, n = strlen(s); i < n; i++)
{
if (isupper(s[i]))
{
char u = s[i];
char m = 'A';
if (islower(s[i]))
m = 'a';
printf("%c",key[u - m] );
}
else
{
printf("%c",s[i]);
}
}
printf("\n");
return(0);
}
#include <stdio.h>
#include <cs50.h>
#include <ctype.h>
#include <string.h>
bool validate_key(string key);
int main(int argc, string argv[])
{
//checks if key is the right length
if (argc != 2 || strlen(argv[1]) != 26 || validate_key((string) argv[1]) != 1)
{
printf("Key must exist and contain 26 non identical alphabetical characters.\n");
return 1;
}
//gets input text
string text = get_string("plaintext: ");
int len = strlen(text);
char mychar = toupper(text[0]) - 65;
for (int i = 0; i < len; i++)
{
if (mychar >= 0 && mychar <= 26)
{
if (isupper(text[i]))
{
text[i] = toupper((char) argv[1][(int) mychar]);
}
else
{
text[i] = tolower((char) argv[1][(int) mychar]);
}
}
mychar = toupper(text[i + 1]) - 65;
}
printf("ciphertext: %s\n", text);
return 0;
}
bool validate_key (string key)
{
int len = strlen(key);
char mychar;
for(int i = 0; i < len; i++)
{
mychar = toupper(key[i]);
if(mychar >= 65 && mychar <= 90)
{
for(int j = i + 1; j < len; j++)
{
if(mychar == toupper(key[j]))
{
return 0;
}
}
}
else
{
return 0;
}
}
return 1;
}
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
//get the input from the user in comomand-line
int main (int argc, string argv[])
{
if (argc == 2) // Checks if it is two arugument including file name
{
int len = strlen(argv[1]);
for (int i = 0; i < len; i++) // Checks if it is a digit, if yes, then print the following
{
if (isdigit(argv[1][i]))
{
printf("Usage: ./substitution key \n");
exit(0); // To terminate the program immediately
}
}
if (len != 26) // Checks if the length of the given input in command-line is 26 characters, if not, then print
{
printf("key must contain 26 characters.");
}
string plain = get_string("Plain text: "); //Get plain text from the user to encode it
string cipher;
printf("Cipher text: ");
for (int i = 0, n = strlen(plain); i < n; i++)
{
if (islower(plain[i])) // Checks the case sensitive
{
printf("%c", tolower(argv[1][plain[i] - 'a'])); // prints lower case cipher calue
}
else if (isupper(plain[i]))
{
printf("%c", toupper(argv[1][plain[i] - 'A'])); //prints upper case cipher value
}
else
{
printf("%c", plain[i]); // prints apart from alphabetical characters
}
}
}
else
{
printf("Usage: ./substitution key");
}
}
check if you returned false for loop.
you have to return it out of the for loop.