How to Preserve Case of Inputted Chars in C? - c

The user inputs chars that can be uppercase or lowercase. I need to spit an answer back that preserves the case of the inputted char after that char is processed by my code. How do I preserve case when the char was converted to its ASCII value and then to its alphabetical index equivalent.
Here is my code:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
int counter = 0;
if (argc == 2) {
for (int k = 0; k < strlen(argv[1]); k++) {
if (isdigit(argv[1][k])) {
counter++;
}
}
if (strlen(argv[1]) == counter)
{
string s = get_string("plaintext: ");
printf("ciphertext: ");
for (int i = 0; i < strlen(s); i++) {
int c = (int) s[i];
if (c >= 97 && c <= 122)
{
printf("%i\n", (((c % 32) - 1 + atoi(argv[1]))) % 26);
}
printf("\n");
if (c >= 65 && c <= 90)
{
printf("%i", (((c % 32)) - 1 + atoi(argv[1])) % 26);
}
printf("\n");
}
} else {
printf("Usage: ./caesar key\n");
}
}
}
Expected behavior would print Zoo as "App" if Key entered in command line were 1.

Related

How to handle handles lack of argv[1] and handles too many arguments in caesar?

I finished Caesar pset2 for CS50, but when I run it for a check-up, I get 2 errors. One for how handles lack of argv[1] and the other being too many arguments. I've been stuck on this for several hours and haven't made any progress. Any tips on how to move forward?
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
int strtoint;
int onlydigits = 0;
if (argc == 2) //Checks the program with one command-line argument
{
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if (isdigit(argv[1][i]))
{
onlydigits += 1;
}
}
if (onlydigits == strlen(argv[1])) //Checks if characters are digits
{
strtoint = atoi(argv[1]); //Converts string to int
string plain = get_string("plaintext: "); //Prompt user for input
printf("ciphertext: ");
for (int j = 0, m = strlen(plain); j < m; j++) //Iterate over each character for plaintext
{
if (isalpha(plain[j]) && isupper(plain[j])) //Checks if characters are uppercase
{
printf("%c", (((plain[j] - 65) + strtoint) % 26) + 65);
}
else if (isalpha(plain[j]) && islower(plain[j])) //Checks if characters are lowercase
{
printf("%c", (((plain[j] - 97) + strtoint) % 26) + 97);
}
else
{
printf("%c", plain[j]); //Prints as is if neither of the above
}
}
printf("\n"); //Prints a new line
return 0;
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
}
output for code

Cannot stop array from overflowing in Caesar algorithm

I have almost finished my code, but ran into the following problem. The code, luckily, works, but when I write as input ZQ, with a key of 1, it gives me the next character of the ASCII chart. Is there a way to stop it from overflowing? If it reaches Z, I'd like to go back to the first index character, which would be the A. Additionally, it seems to work better when I get rid of the % 26 in line 39, even though I need to use the formula ci = (pi + k) % 26. It gives me no characters as an output otherwise. Thanks!
If a character is uppercase, it should remain uppercase, vice versa with lowercase.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
int k = 0;
string key = argv[1];
if (argc == 2)
{
for (k = 0; k < strlen(key); k++)
{
if (!isdigit(key[k]))
{
printf("\nUsage: %s key\n", argv[0]);
return 1;
}
}
}
else
{
printf("\nUsage: %s key\n", argv[0]);
return 1;
}
string plaintext = get_string("\nplaintext: ");
printf("ciphertext: ");
for (int i = 0; i < strlen(plaintext); i++)
{
char c = plaintext[i];
int keycode = atoi(key);
if (isalpha(c))
{
printf("%c", (c + keycode) % 26);
}
else if (isspace(c) || isdigit(c) || ispunct(c))
{
printf("%c", c);
}
}
}
The number values for letters are offset from the values for the Cæsar cipher, depending on what case it is. You must transform them into numbers in the range of (0, 25), do the operation, and inverse transform the result back into the case selected. These transformations are fairly simple, eg for lower-case letters, F(c) = c - 'a'.
The formula is correct to handle wrapping from Z to A, but you must first convert letters to their index value in the alphabet. For the ASCII character set, this conversion is a simple subtraction but must be performed separately for uppercase (c = 'A') and lowercase letters (c - 'a').
Here is a modified version:
#include <ctype.h>
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(int argc, string argv[])
{
int k = 0;
string key = argv[1];
if (argc == 2)
{
for (k = 0; key[k] != '\0'; k++)
{
if (!isdigit((unsigned char)key[k]))
{
printf("\nUsage: %s key\n", argv[0]);
return 1;
}
}
}
else
{
printf("\nUsage: %s key\n", argv[0]);
return 1;
}
string plaintext = get_string("\nplaintext: ");
int keycode = atoi(key);
printf("ciphertext: ");
for (int i = 0; plaintext[i] != '\0'; i++)
{
char c = plaintext[i];
if (isupper((unsigned char)c))
{
printf("%c", 'A' + (c - 'A' + keycode) % 26);
}
else if (islower((unsigned char)c))
{
printf("%c", 'a' + (c - 'a' + keycode) % 26);
}
else // leave other characters unchanged
{
printf("%c", c);
}
}
return 0;
}

Why is my code skipping over spaces and punctuation when shifting letters through the caesar cipher?

So my code for my caesar programming is shifting the letters with the key just fine, but it is not keeping the spaces or puncuation. For example, if the user runs the program using ./caesar 2 in the command line, and they want "A b." to be shifted, the result comes out as "Cd", but it should be "C d.". I have tried to fix the problem but I just don't know how. Any help would be appreciated. My code is below.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
string plain = NULL;
char num1;
char halftotal;
char total;
//creating the key
if(argc == 2)
{
int shift = atoi(argv[1]);
if(shift < 0)
{
printf("Usage: ./caesar key\n");
return 1;
}
else if(shift > 0)
{
//prompting for plaintext
plain = get_string("Plaintext: ");
//enciphering plaintext
int test = strlen(plain);
printf ("Ciphertext: ");
for( int i = 0;i < test;i++)
{
if(isalpha(plain[i]))
{
if(isupper(plain[i]))
{
num1 = plain[i] - 65;
halftotal = (num1 + shift)%26;
total = (halftotal + 65);\
printf("%c", total);
}
else if(islower(plain[i]))
{
num1 = plain[i] - 97;
halftotal = (num1 + shift)%26;
total = (halftotal + 97);
printf("%c", total);
}
}
}
printf("\n");
return 0;
}
}
else if(argc != 2)
{
printf("Usage: ./caesar key\n");
}
}
Your loop basically looks like this:
for( int i = 0;i < test;i++)
{
if(isalpha(plain[i]))
{
// convert the character
...
}
}
So when the character is a letter you do a conversion. But if it's not, you do nothing. That's why you don't see anything other than letters in the output.
You need to add an else clause here to simply print whatever was given if it's not a letter.
for( int i = 0;i < test;i++)
{
if(isalpha(plain[i]))
{
// convert the character
...
}
else
{
printf("%c", plain[i]);
}
}
The test if(isalpha(plain[i])) doesn't do anything else if the character is not alphabetical, so it is ignored.
You can remove that and add else printf("%c", plain[i]); below so that part of the code looks like this
printf ("Ciphertext: ");
for( int i = 0;i < test;i++)
{
if(isupper(plain[i]))
{
num1 = plain[i] - 'A'; // replaced magic numbers too
halftotal = (num1 + shift) % 26;
total = (halftotal + 'A');
printf("%c", total);
}
else if(islower(plain[i]))
{
num1 = plain[i] - 'a';
halftotal = (num1 + shift) % 26;
total = (halftotal + 'a');
printf("%c", total);
}
else
{
printf("%c", plain[i]);
}
}
printf("\n");
isalpha exludes whitespace and punctuation characters.
http://cplusplus.com/reference/cctype/isalpha/

Wrapping Text Using Modulo

I am trying to cipher some plain text using a string key. Anyway if the plain text is greater than the key the key is suppose to continue using the key..I have used modulo to make the key start over again but for some reason it is not working...what is wrong with the code? By the way the key status upper or lower status is not a factor so this is why I change it to lower. Any help rendered would be appreciated. //Code cleaned up as suggested.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include<stdlib.h>
#include<ctype.h>
int main (int argc, string argv[])
{
if (argc != 2)
{
printf("Ouch missing key\n");
return 1;
}
//get encryption keyword from argv array
string k= (argv[1]);
//test for non aplha character in plain text message
int x;
for (x = 0; x <strlen(argv[1]); x++)
{
if(isalpha(k[x]) == false)
{
printf("Ouch ensure value is alphabetical only\n");
return 1;
}
}
string m;
m = GetString(); //get plain text from prompt
for (int i= 0, j = 0; i< strlen(m) && j<= strlen(k); i++, j++)
{
if (
isalpha(m[i]) && isupper(m[i]))
{
m[i]= (m[i]-'a' + (tolower(k[j % strlen(k)])-'a')) % 26 + 'A';
}
else if (
isalpha(m[i]) && islower(m[i])
)
{
m[i] = (m[i] - 'a' + (tolower(k[j %strlen(k)])- 'a')) % 26 + 'a';
}
else
m[i] = m[i];
}
printf("%s\n", m);
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <cs50.h>
int main (int argc, string argv[]){
if (argc != 2){
printf("Ouch missing key\n");
return 1;
}
string k = argv[1];
int len_k = strlen(k);
for (int i = 0; i < len_k; ++i){
if(isalpha(k[i]))
k[i] = tolower(k[i]);
else {
printf("Ouch ensure value is alphabetical only\n");
return 1;
}
}
string m;
m = GetString();
for (int i= 0; i< m[i] ; ++i){
if(isupper(m[i]))
m[i]= (m[i]-'A' + k[i % len_k] - 'a') % 26 + 'A';
else if(islower(m[i]))
m[i]= (m[i]-'a' + k[i % len_k] - 'a') % 26 + 'a';
else
m[i] = m[i];//no effect, no need
}
printf("%s\n", m);
free(m);
return 0;
}
If your coding language is C fix main() by,
int main (int argc, string argv[])
to
int main (int argc, char * argv[])

Strange unwanted three digit code printouts from caesar cipher

The cipher code actually works; it's just that I get some odd three digit codes separated with slashes too.
Any help would be greatly appreciated. Here's my code.
The codes look like this but have random numbers /354/233/645/810/236
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cs50.h"
int i, len;
string sentance, encrypted;
int k, argvLen;
int caesar (int k){
printf("Hi I'm Ceaser! What would you like me to cipher?\n");
sentance = GetString();
len = strlen(sentance);
char encrypted[len];
for (i=0; i<len; i++) {
if (sentance[i] >='a' && sentance[i] <='z') {
encrypted[i] = ((sentance[i] - 'a' + k) % 26) + 'a';
}
else if (sentance[i] >='A' && sentance[i] <='Z') {
encrypted[i] = ((sentance[i] - 'A' + k) % 26) + 'A';
}
else if (sentance[i] >=' ' && sentance[i] <= '#'){
encrypted[i] = sentance[i];
}
}
printf("%s", encrypted);
return 0;
};
int main (int argc, const char * argv[]) {
if (argc==2) {
k = atoi(argv[1]);
argvLen = strlen(argv[1]);
for (i=0; i<argvLen; i++){
if (isdigit(argv[1][i])){
caesar(k);
}
else {
printf("please enter a number for the key!");
return 1;
}
}
return 0;
}
};
You are not terminating the encrypted string properly.
You need:
To make sure you have room for the terminating character, by using char encrypted[len + 1];.
encrypted[len] = '\0'; after the loop.

Resources