-
-
Save CraigRodrigues/100ab759b6b6722ba3ad8acf12e26371 to your computer and use it in GitHub Desktop.
#include <stdio.h> | |
#include <cs50.h> | |
#include <string.h> | |
#include <ctype.h> | |
/** | |
* Caesar.c | |
* A program that encrypts messages using Caesar’s cipher. Your program must | |
* accept a single command-line argument: a non-negative integer. Let’s call it | |
* k for the sake of discussion. If your program is executed without any | |
* command-line arguments or with more than one command-line argument, your | |
* program should yell at the user and return a value of 1. | |
* | |
* */ | |
int main(int argc, string argv[]) | |
{ | |
// check for 2 arguments only | |
if (argc != 2) | |
{ | |
printf("Nope\n"); | |
return 1; | |
} | |
// once I check for correct argv put key into an int k | |
int k = atoi(argv[1]); | |
// check if the integer is non-negative | |
if (k < 0) | |
{ | |
printf("Nope\n"); | |
return 1; | |
} | |
else | |
{ | |
// prompt user for a code to encrypt | |
string code = GetString(); | |
for (int i = 0, n = strlen(code); i < n; i++) | |
{ | |
//check if the letter is uppercase or lowercase then convert | |
if islower(code[i]) | |
printf("%c", (((code[i] + k) - 97) % 26) + 97); | |
else if isupper(code[i]) | |
printf("%c", (((code[i] + k) - 65) % 26) + 65); | |
//if neither then just print whatever it is | |
else | |
printf("%c", code[i]); | |
} | |
printf("\n"); | |
return 0; | |
} | |
} |
This is pretty good! Thank you for sharing this. I tested this code, but it appears that it doesn't handle non-numeric key.
Results for cs50/problems/2020/x/caesar generated by check50 v3.1.2
:) caesar.c exists.
:) caesar.c compiles.
:) encrypts "a" as "b" using 1 as key
:) encrypts "barfoo" as "yxocll" using 23 as key
:) encrypts "BARFOO" as "EDUIRR" using 3 as key
:) encrypts "BaRFoo" as "FeVJss" using 4 as key
:) encrypts "barfoo" as "onesbb" using 65 as key
:) encrypts "world, say hello!" as "iadxp, emk tqxxa!" using 12 as key
:) handles lack of key
:( handles non-numeric key
timed out while waiting for program to exit
:) handles too many arguments
`#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
// Validate correct argv enter key into int
if (argc == 2 && isdigit(*argv[1]))
{
int k = atoi(argv[1]);
// validate integer is not negative
if (k < 0)
//if a letter or unrecognized character is entered, then print instructions
{
printf("Please enter the following: ./caesar key(number, i.e., 25 or 51) \n");
return 1;
}
else
{
// Ask user for a word to encrypt
string code = get_string("Enter word(s) to encrypt: "); //someone told me to use GetString, but that doesn't seem right, so I asked around for suggestions
printf("ciphertext: ");
for (int i = 0, n = strlen(code); i < n; i++)
{
//check if the letter is uppercase or lowercase then convert
if islower(code[i])
{
printf("%c", (((code[i] + k) - 97) % 26) + 97); //testing suggestions on running negative -97 lowercase and 65 for uppercase
}
else if isupper(code[i])
{
printf("%c", (((code[i] + k) - 65) % 26) + 65);
}
else
{
printf("%c", code[i]);
}
}
printf("\n");
return 0;
}
}
//if a letter is entered instead of a number, then print instructions
else
{
printf("Text not recognized. Please enter a number. Example: ./caesar 23 \n");
return 1;
}
} `
I tried this. This solves the alpha numeric issue but starts giving more weird problems. I am getting these two problems, which were not there before i checked for alphanumeric thing
caesar.c exists.
:) caesar.c compiles.
:( encrypts "a" as "b" using 1 as key
output not valid ASCII text
:) encrypts "barfoo" as "yxocll" using 23 as key
:) encrypts "BARFOO" as "EDUIRR" using 3 as key
:) encrypts "BaRFoo" as "FeVJss" using 4 as key
:) encrypts "barfoo" as "onesbb" using 65 as key
:( encrypts "world, say hello!" as "iadxp, emk tqxxa!" using 12 as key
output not valid ASCII text
:) handles lack of key
:) handles non-numeric key
:) handles too many arguments
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int key;
int main(int argc, string argv[])
{
if (argc == 2)
{
for(int r = 0; r < strlen(argv[1]); r++) // after adding this to prevent taking "20x" type of input i am starting to get 2 new errors
{
if (isdigit(argv[1][r]) == false)
{
printf("Usage: ./caesar key\n");
return 1;
}
}
key = atoi(argv[1]); // converting from string to integer
if (key > 0) // bit of cheating, 0 will not be accepted as key :(
{
string message = get_string("plaintext: ");
int n = strlen(message);
char cmessage[n];
for (int i = 0; i < n; i++)
{
if (message[i] >= 'a' && message[i] <= 'z')
{
cmessage[i] = ((message[i] - 97) + key)%26 + 97;
}
else if (message[i] >= 'A' && message[i] <= 'Z')
{
cmessage[i] = ((message[i] - 65) + key)%26 + 65;
}
else
{
cmessage[i] = message[i];
}
}
printf("ciphertext: %s\n", cmessage);
return 0;
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
thank you!
Can someone please give me a simple way to check if my key is a number or not because I am very confused?
Hi all!
I have added some more code that covers the case that the user returns one alphanumeric key (e.g 5x). It doesn't look very...elegant though. Any suggestions are more than welcome. :)
`#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>int main(int argc, string argv[])
{
// Accept only one command-line argumentif (argc == 2) { // Check that they all chars are digits int j = 0; string z = argv[1]; for (int i = 0, n = strlen(z); i < n; i++) { if (isdigit(z[i])) { j++; } } // Convert according to the key if (j == strlen(z)) { int k = atoi(argv[1]); string text = get_string("plaintext: "); printf("ciphertext: "); for (int l = 0, m = strlen(text); l < m; l++) { // Convert if islower(text[l]) { printf("%c", (((text[l] - 'a') + k) % 26) + 'a'); } else if isupper(text[l]) { printf("%c", (((text[l] - 'A') + k) % 26) + 'A'); } else { printf("%c", text[l]); } } printf("\n"); return 0; } else { printf("Usage: ./caesar key\n"); return 1; } } else { printf("Please provide the key.\n"); return 1; }
}`
Oh my god! Thank you so much! This worked and was easy to understand as well. I have been so confused and stressed, you made my day. Thank youuuuu!
let someone help me at this:
Connecting.......
Authenticating......
Preparing...............
Uploading.............
Checking.......
:) caesar.c exists.
:( caesar.c compiles.
expected exit code 0, not 1
:| encrypts "a" as "b" using 1 as key
can't check until a frown turns upside down
:| encrypts "barfoo" as "yxocll" using 23 as key
can't check until a frown turns upside down
:| encrypts "BARFOO" as "EDUIRR" using 3 as key
can't check until a frown turns upside down
:| encrypts "BaRFoo" as "FeVJss" using 4 as key
can't check until a frown turns upside down
:| encrypts "barfoo" as "onesbb" using 65 as key
can't check until a frown turns upside down
:| encrypts "world, say hello!" as "iadxp, emk tqxxa!" using 12 as key
can't check until a frown turns upside down
:| handles lack of argv[1]
can't check until a frown turns upside down
same is happening
with me any soon
I like looking at these after I've finished mine to compare, and OP's code is definitely cleaner than mine. I thought of using ASCII but I don't know why my brain didn't just wrap itself around adding and subtracting... it's like I immediately ruled out the ASCII solution to go with something "easier" (arrays), even though they provided a nod to ASCII conversions being a more efficient way to do this on the pset page. Here's mine with a summary of how it all works at the bottom:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h> //CAESAR.C, scroll to bottom to see full summary
const char upperalphabet[26] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
const char loweralphabet[26] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
int main(int argc, string argv[])
{
if (argc < 2)
{
return 1;
}
else if (argv[1] < 0)
{
return 1;
}
int key = atoi(argv[1]);
string plaintext = get_string("plaintext: ");
printf("\n ciphertext: ");
for (int n = 0; n < strlen(plaintext); n++)
{
if (isalpha(plaintext[n]))
{
if (isupper(plaintext[n]))
{
int z;
for (z = 0; plaintext[n] != upperalphabet[z]; z++)
;
int ciphernumber = ((z + key) % 26);
printf("%c", upperalphabet[ciphernumber]);
}
else if (islower(plaintext[n]))
{
int z;
for (z = 0; plaintext[n] != loweralphabet[z]; z++)
;
int ciphernumber = ((z + key) % 26);
printf("%c", loweralphabet[ciphernumber]);
}
}
else
{
printf("%c", plaintext[n]); //non-alphabetical plaintext array elements get printed here
}
}
printf("\n");
return 0;
}
/*Code summary: This code takes a character string that the user inputs - let's call that p. And p's individual characters can be called p^i.
Through a loop, the code finds a character in the above alphabet array that matches p^i. The index identifier for this index in the alphabet array
(that matches p^i), we'll call n. It can be seen as a numerical equivalent to p^i.
Using the modulus of (n + the key inputted through the command line) out of 26 (all the letters of the alphabet), we'll find the index identifier of
the index containing the char that is the cipher-shift of p^i. And once that's found, we can print it to see its char element.
The output should be a ciphertext directly corresponding to the plaintext, with whitespaces, punctuation and lettercase unchanged, the only thing
modified being the alphabetical letters themselves to a cipher-shifted char equivalent. */
`
as you can see it's way too long lol
Steps:
- Get a single command-line argument "key" from the user that is a non-negative integer.
- If not a single argument then yell at user.
- Take the "key" and turn it into an int with atoi since it starts as a string.
- Prompt user for a code they want to encrypt.
- Need to loop through the entire code letter by letter.
- Check if each letter is either lowercase, uppercase or neither.
- Standardize the ASCII value of the char to 26 then add the key. Then convert back into ASCII so that the code can wrap around properly.
- If neither a lowercase or uppercase letter then just print whatever the char is. This allows for spaces or special characters like ! or &.
- Once all of the above is complete print a new line.
- Return 0.
Notes:
- Checking if the argv[1] was a non-negative integer (don't think I even needed to do this).
- Figuring out how to standardize ASCII to the regular alphabet then converting back took a lot of time.
- This ASCII chart was incredibly useful - http://www.kerryr.net/pioneers/ascii3.htm
- Trying to put argv[1] into a variable before I check if there is even an argv[1] caused a segmentation fault.
- Didn't notice that toupper/tolower already checks if the character is a letter. First I had two more checks to see if the character was a letter or not when that wasn't necessary.
- ctype.h library is very useful - https://cs50.harvard.edu/resources/cppreference.com/stdstring/all.html
What if the user enters an alphabet instead of a number in place of key?
Guys I'm getting this:
:) caesar.c exists.
:) caesar.c compiles.
:( encrypts "a" as "b" using 1 as key
expected "ciphertext: b...", not "ciphertext: b..."
:( encrypts "barfoo" as "yxocll" using 23 as key
expected "ciphertext: yx...", not "ciphertext: yx..."
:( encrypts "BARFOO" as "EDUIRR" using 3 as key
expected "ciphertext: ED...", not "ciphertext: ED..."
:( encrypts "BaRFoo" as "FeVJss" using 4 as key
expected "ciphertext: Fe...", not "ciphertext: Fe..."
:( encrypts "barfoo" as "onesbb" using 65 as key
expected "ciphertext: on...", not "ciphertext: on..."
:( encrypts "world, say hello!" as "iadxp, emk tqxxa!" using 12 as key
expected "ciphertext: ia...", not "ciphertext: ia..."
:) handles lack of argv[1]
:) handles non-numeric key
:) handles too many arguments
but the output match.... Any idea?
idk
i'm also getting thi with similiar code
were u able to do it?
few changes: