I have an assignment to cipher letters according to a formula. We are suppose to keep uppercases as uppercases and lowercases as lowercases.
The formula for ciphering is this: ci = (pi + k) % 26.
Int x in my code is k.
Pi is the character in the string.
Right now im facing two problems. The cipher is currently not working (and and the code is not done).
But the chars are not printing. Highly appriciate if you could look at it and give me some clues about why its not printing.
This is my code:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
char cipher (string plaintext, int x);
int main (int argc, string argv [])
{
//here is part for validation
//GET STRING
//CRYPT
string plaintext = get_string ("plaintext: ");
for(int i= 0; i < strlen(plaintext); i++)
{
int ci = 0;
int ch = 65;
if (isupper(plaintext[i]))
{
if (x <= 26 - (plaintext[i] - ch))
{
ci = plaintext[i] + x;
printf("%c", plaintext[ci]);
}
//if the key is overflowing the letters left in alpha
else if (x > 26 - (plaintext[i] - ch))
{
ci = ((plaintext[i] + x) % 26) + 64;
printf("%c", plaintext[ci]);
}
}
}
}
The lines
printf("%c", plaintext[ci]);
are wrong. ci here is already the character code to print, so they should be
printf("%c", ci);
or more simply
putchar(ci);
Related
Hey all I asked a question related to this code earlier and got a lot of helpful answers (I'm very green at coding). While I overcame my initial problem and corrected a few more mistakes I've run into another error that I can't seem to fix. I keep getting the Segmentation fault but I want it to prompt the user to give a second argument. Along with that when I do give the number, the code doesn't seem to actually encrypt the text Any suggestions or blaring issues I missed?
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
int num;
int k = atoi(argv[1]);
string output;
if(argc != 2)
{
printf("K not included in command");
return 1;
}
string s = get_string("Insert Lowercase Message:");
for (int i = 0, n = strlen(s); i < n; i++)
{
char c = s[i];
if (c >= 'A' && c <= 'Z')
{
num = 'A';
if (c >= 'a' && c <= 'z')
num = 'a';
printf("%c", (c - num + k) % 26 + num);
}
else
printf("%c", c);
}
}
You have your braces misaligned where you are testing the case of the letters. The way it is written, if a lowercase case letter is encountered, the uppercase test will fail and you will drop through to the else case. What you want is something like this:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, string argv[])
{
int num;
int k;
string output;
char c;
if(argc != 2)
{
printf("K not included in command");
return 1;
}
k = atoi(argv[1]);
string s = get_string("Insert Lowercase Message:");
for (int i = 0; c = s[i]; i++)
{
if (isalpha(c))
{
if (isupper(c))
num = 'A';
else // islower
num = 'a';
printf("%c", (c - num + k) % 26 + num);
}
else
printf("%c", c);
}
}
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;
}
I'm a newbie, so apologies if I don't explain myself well. If it helps, I'm doing this for the Caesar problem set as part of the Harvard CS50x OpenCourseWare.
I'm trying to convert user generated plain text to cipher text using a simple key. To accomplish this I'm attempting to use a wraparound counting formula in my last function. However, sometimes I get blanks that print out instead of the new characters... Help!
EDIT: I'm using a key of 5 and the plaintext "Helloz!" to test. Expect to see Mjqqte!
instead am seeing blank spaces.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>
int convert(string n);
string k, text;
char text;
int r, c, t,x;
bool validate(string n);
//int encrypted(string n);
int main(int argc, string argv[])
{
//accept single command-line argument, non negative integer, k with appropriate error
k = argv[1];
if (argc > 1 && argc <= 2)
{
//printf("Success\n%s\n", argv[1]);
// print individual characters of argv[i]
validate(k);
}
else //if wrong input then print error message and main should return 1
{
printf("Usage: ./caesar key\n");
return 1;
}
text = get_string("plaintext:");
t = atoi(k);
printf("%i\n", t);
convert (text);
printf("\n");
}
//output "ciphertext:" without a newline, with the characters roated by k positions
//after output, print a newline and exit by returning 0 from main
bool validate(string n)
{
for (int i = 0; k[i] != '\0'; i++)
{
if (48 <= k[i] && k[i] <= 57)
{
//printf("%c\n", k[i]);
}
else
{
printf("./caesar key\n");
return 1;
// save for later: printf("%s \n", k);
}
}
return r;
}
int convert(string n)
{
//if fits within a range, Reads individual characters
for (int i = 0; i < text[i]; i++)
{
if (isalpha(text[i]))
{
x = text[i];
//printf("%i\n", x);
c = (x+t) % 26;
// printf("%i\n",c);
printf("%c", c);
}
else
{
printf("%i", text[i]);
}
}
return 0;
}
Here's an implementation that could work for you:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
void convert(char *text, unsigned char k) {
for (unsigned int i = 0; i < strlen(text); i++) {
if (isalpha(text[i])) {
// Contains the 3 leftmost bits, containing the uppercase/lowercase part.
char c = (text[i] / 32) * 32;
// Perform the shifting with modulo on the alphabetic index of the letter.
text[i] = c + ((text[i] % 32) + k) % 26;
}
}
}
int main(int argc, char *argv[]) {
unsigned char k = strtol(argv[1], NULL, 10);
char text[64];
printf("Using key %d.\n", (int) k);
printf("Plaintext: ");
fgets(text, 64, stdin);
// Remove newline.
text[strlen(text) - 1] = 0;
convert(text, k);
printf("Ciphertext: %s.\n", text);
return 0;
}
Test run:
>>> cipher 4
Using key 4.
Plaintext: Test mE Right Away!!1
Ciphertext: Xiwx qI Vmklx Eaec!!1.
This code is supposed to encipher text based off the command argument input key and print out the enciphered text. However it doesn't print spaces and punctuation. Can someone explain what is wrong?
Example use:
$ ./caesar 12
world, say hello!
iadxp, emk tqxxa!
$
Code:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
if (argc>2 || argc<2)
{
printf("Please enter a valid argument.\n");
return 1;
}
string input = GetString();
int key = atoi(argv[1]);
for(int i = 0, l = strlen(input); i < l; i++)
{
//if(isalpha(input[i]))
//{
char c = input[i];
int letternum = c;
if(isupper(c))
{
int upper = 'A';
int alphanum = letternum - upper;
int newint = (alphanum + key) % 26;
newint = newint + upper;
char newchar = newint;
printf("%c", newchar);
}
if(islower(c))
{
int lower = 'a';
int alphanum = letternum - lower;
int newint = (alphanum + key) % 26;
newint = newint + lower;
char newchar = newint;
printf("%c", newchar);
}
//}
}
printf("\n");
}
Add else after if() blocks.
Change from
if(isupper(c)) {
...
}
if(islower(c)) {
...
}
to
if(isupper(c)) {
...
} else if(islower(c)) {
...
} else {
putc(c);
}
Note: pedantic code would use the following as is...() functions are defined for all int values in the range of unsigned char and EOF.
isupper((unsigned char) c)
islower((unsigned char) c)
Note2: Code will have problems if alphanum + key < 0. May want to add a test to insure key is not too negative or use the following to insure key >= 0.
int key = atoi(argv[1]) % 26 + 26;
Note3: OP's code assumes A-Z and a-z are consecutive like in ASCII encoding (which is certainly the case 99.99+% of the time.) but not in EBCDIC
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.