I've searched the web quite long for a simple caesar chiper/encryption algorithm in C language.
I found one but is wasn't perfect so I already changed the code.
Still having problems, because a friend said that the programm should be able to handle big key's, too.
For example text "Hello World" with a Key: 50... And if I do that I get the following: (Console output)
This tiny application encodes plain text to the Caesar Encryption
Type in some text to decode: Hello World
Type in the key/shifting of the letters:
50
`}ääç oçèä|
Which is wrong.... And maybe the problem is the char/array - I don't know...So I would be happy if you could help me with that :)
Here is the source code(with some comments):
#include <stdio.h>
#include <conio.h>
#include <wchar.h>
int main()
{
unsigned char array[100], shifting; //creating 2 arrays for the encryption
//I changed it to unsigned char because otherwise Z with key 6/7 dosen't work
int z; //This is our key
printf("This tiny application encodes plain text to the Caesar Encryption\n");
printf("Type in some text to decode :");
fgets(array, 100, stdin); //because gets() is bad I'am using fgets()
printf("Type in the key/shifting of the letters:\n");
scanf("%d", &z);
for (int i = 0; array[i] != '\0'; i++)
{
shifting = array[i]; //overgive values from array to shifting
if (shifting >= 'a' && shifting <= 'z') { //check the containing lowercase letters
shifting = shifting + z;
if (shifting > 'z') {
shifting = shifting - 'z' + 'a' - 1; // if go outside the ascii alphabeth this will be done
}
array[i] = shifting;
}
else if (shifting >= 'A' && shifting <= 'Z') { //the same for uppercase letters
shifting = shifting + z;
if (shifting > 'Z') {
shifting = shifting - 'Z' + 'A' - 1;
}
array[i] = shifting;
}
}
printf("%s\n", array);
return 0;
}
The source of your problem is here:
if (shifting > 'z') {
shifting = shifting - 'z' + 'a' - 1; // if go outside the ascii alphabeth this will be done
}
What's the length of the English alphabet? It's 26.
If you give z greater than 26, a single decrement by the alphabet length does not suffice. You should either make sure z does not exceed the length of alphabet, of repeat decrementing until the result fits the alphabet range.
Solution 1:
int asciiAlphabetLength = 'z' - 'a' + 1;
printf("Type in the key/shifting of the letters:\n");
scanf("%d", &z);
z %= asciiAlphabetLength;
Solution 2:
shifting += z;
while (shifting > 'z') {
shifting -= asciiAlphabetLength; // while outside the ascii alphabeth reduce
}
Related
Your program should read a word from the input and then sort the letters of the word alphabetically (by their ASCII codes). Next, your program should iterate through the letters of the word and compare each letter with the one following it. If these equal each other, you increase a counter by 1, making sure to then skip ahead far enough so that letters that occur more than twice are not counted again. You may assume that the word you read from the input has no more than 50 letters, and that the word is all lowercase.
I wrote a program and get these results:
apple gives me 1
erroneousnesses gives 5,
but taylor should give me 0 however it gives 1.
How can I make yup, taylor and other words with non-repeating alphabets give me 0?
Here is my code:
#include <stdio.h>
int main(void) {
char string[51];
int c = 0, count[26] = { 0 }, x = 0;
scanf("%s", string);
while (string[c] != '\0') {
if (string[c] >= 'a' && string[c] <= 'z') {
x = string[c] - 'a';
count[x]++;
}
c++;
}
printf("%d", count[x]);
return 0;
}
There are multiple problems in your code:
scanf("%s", string); may cause a buffer overflow if the input is longer than 50 bytes.
Furthermore, you do not test the return value to check for invalid or missing input.
counting the number of occurrences of each letter is an alternative approach to the stated problem, and OK if you are only graded based on the program output. However be aware that the program does not implement what the assignment explicitly mandates and the value you output is incorrect anyway.
the output value should be the number of counts that are >= 2. Printing the value of count[x] is meaningless.
Here is a modified version:
#include <stdio.h>
int main() {
char str[51];
int dup = 0;
int count['z' - 'a' + 1] = { 0 };
if (scanf(" %50[a-z]", str) == 1) {
for (int i = 0; str[i] != '\0'; i++) {
if (++count[str[i] - 'a'] == 2)
dup++;
}
printf("%d\n", dup);
}
return 0;
}
to answer your specifc question
printf("%d", count[x]);
prints the count of number of appearances of the last letter.
taylor => 1 (r occurs 1 time)
apple => 1 (e once)
erroneousnesses => 5 (s count)
you need to loop over count array adding all counts > 1
#include <stdio.h>
int main()
{
int rotation, i=0;
char str[80]={0};
printf("Enter Text: ");
scanf("%[^\n]", str);
printf("\"");
printf("Enter Rotation: ");
scanf("%i", &rotation);
while(str[i])
{
if (str[i] >= 'a' && str[i] <= 'z')
printf("%c\n", 'a' + (str[i] - 'a' + rotation)%26);
else
printf("%c\n", str[i]);
i++;
}
return 0;
}
Have a hard time understanding this line of code (printf("%c\n", 'a' + (str[i] - 'a' + rotation)%26); )
Can anyone just write a brief explanation quickly it would help me
The program is taking the user's input text and on a per character basis rotating it through the alphabet based on the number entered. It works because of the ASCII table.
The line in question takes the character a user entered, offsets it by 'a' (which equals 91 in ASCII), adds in the rotation factor then performs modulo 26 on the result (how many characters are there in the alphabet again?) to make sure the result is still a lowercase character.
I bet you could find a good way to break this program :)
I can get it to print the plaintext and and shift by the key value, but
i'm a bit confused on how to get the letters to wrap around, and how to implement it into my code.
Any suggestions would be appreciated.
Thank you.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
//Gets number of user arguments and the key.
int main (int argc, string argv[]) {
if(argc != 2) {
printf("try again\n");
}
//Converts string to int.
int key = atoi(argv[1]);
//Will store the chars + key.
int result;
printf("Please enter what you would like to encrypt: ");
//Gets plaintext from user.
string plainText = get_string();
//Iterates over the user's input, checking for the case of each char.
for (int i = 0; i <= strlen(plainText); i++) {
if (toupper(plainText[i]) || tolower(plainText[i])) {
result = plainText[i];
}
//Checks if i'th char is a letter and shifts it.
if (isalpha(plainText[i])) {
result = plainText[i + key];
}
}
printf("%c", result);
}
One of the neatest tricks to do this is to use the modulo % operator.
Now talking about your code,
for (int i = 0; i <= strlen(plainText); i++) {
if (toupper(plainText[i]) || tolower(plainText[i])) {
result = plainText[i];
}
//Checks if i'th char is a letter and shifts it.
if (isalpha(plainText[i])) {
result = plainText[i + key];
}
}
printf("%c", result);
This code makes no sense to me.
Your first if condition is I guess to distinguish of the not alphabetical characters, so the if condition could be something like if (! isalpha(plainText[i]) ,
Then your second condition is to add the key to the character if it is an alphabet. It should be something like
if (isalpha (plainText[i])) {
if (islower(plainText[i])
result = ((plainText[i] - 'a') + key) % 26 + 'a';
else
result = ((plainText[i] - 'A') + key) % 26 + 'A';
}
Explanation of above logic:: First you check weather the letter is lowercase or uppercase, so that you can make it in range of 0 to 26,
Then you add the key with the modulo of key, so that it can circle back to 0, then you again convert that it to ascii by adding the value of 'a' their.
e.g. if plainText[i] = 'x' (ascii value 120) and key = 5, then
plainText[i] = 120
plaintext[i] - 'a' = 23
(plaintext[i] - 'a') + key = 28 // Out of 0-25 alphabet range
((plaintext[i] - 'a') + key) % 26 = 2 // Looped back
(((plaintext[i] - 'a') + key) % 26) + 'a' = 99 (ascii value for 'c')
So as you can see we got c after adding 5 to x
And finally the position of your print should be inside loop, otherwise it's gonna only print the last input, which is not correct.
I hope I did everything to help you, keeping in mind the CS50's Honor Code. And also I would suggest you to ask these questions in their forums, because they are a more knoledgeble community to use <cs50.h>
Also, enjoy CS50, it is one of the best CS courses to get you started ;)
#include <stdio.h>
void caesar (char cipher[], int shift);
int main ()
{
char cipher[200];
int shift;
printf("Enter text to be encrypted (in small letter): ");
gets(cipher);
printf("Number of shift to right? : ");
scanf("%d", &shift);
caesar (cipher, shift);
return 0;
}
void caesar (char cipher[], int shift)
{
int i = 0;
while (cipher[i] != '\0')
{
if ((cipher[i] + shift) >= 97 && (cipher[i] + shift) <= 122)
{
cipher[i] += (shift);
}
else
{
cipher[i] += (shift - 25);
}
i++;
}
printf("%s", cipher);
}
How can I ignore the operation of spaces? I mean, I want to add spaces in my converted/decrypted string. While I running this program it vanishes the spaces from the encrypted string. How can I do this? Suppose that, "this is a pen" is would become: "uijt jt b qfo" if right shift by 1.
You should check whether a character is a letter before shifting. Your code shifts everything and checks only whether a character is a valid letter afterwards to detect wrapping. (It also doesn't make the puctuation and spaces vanish, it converts them to non-printable characters with ASCII values below 32.)
You could also enforce correct wrapping by using the modulo operator:
void caesar(char cipher[], int shift)
{
char *p = cipher;
while (*p)
{
if ('a' <= *p && *p <= 'z') {
*p = 'a' + (*p - 'a' + shift) % 26;
}
p++;
}
}
If you want to auto-detect the shift, just use brute force for all 26 possible shifts and check for common expected substrings:
int autocaesar(char cipher[])
{
int shift = 0;
while (shift < 26) {
if (strstr(cipher, "the")) return shift;
if (strstr(cipher, "this")) return shift;
if (strstr(cipher, "that")) return shift;
caesar(cipher, 1);
shift++;
}
return -1;
}
The function strstr is in <string.h> and finds a substring in an string. This is done very crudely here: It is not enforced that "the" is a word of its own. Also, the check is case sensitive.
Note that the cipher is shifted by one character at a time, because the original string will be shifted continuously. If nothing os found, it will have wrapped over to contain the original string.
I'm trying to create a simple Caesar shift program in C but I can't seem to figure it out. The program keeps crashing. Any help would be greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int arc, const char* argv[])
{
int shift = atoi(argv[1]);
char message[256];
strcpy(message, argv[2]);
int i;
for(i = 0; i < strlen(message); i++) {
printf("%c", message[i] + shift);
}
putchar('\n');
return 0;
}
You're not correctly implementing the Caesar Cipher. Your code includes the following line, which is wrong:
printf("%c", message[i] + shift);
To do this correctly, you'll want to convert that to a function:
printf("%c", encrypt(message[i], shift));
And let's implement the function:
char encrypt(char input, int shift) {
if (input >= 'a' && input <= 'z')
return ((input - 'a' + shift) % 26) + 'a';
if (input >= 'A' && input <= 'Z')
return ((input - 'A' + shift) % 26) + 'A';
return input;
}
And just to explain what the math is doing in that function:
input - 'a' tells us what position in the alphabet the input is (assuming input is a lowercase letter). So if the input is 'c', then we will get a 2 back. If the input is 'z', we get 25.
input - 'a' + shift gets us the new position of the character that we are using to do the cipher. Note that this could be a larger number than the alphabet (26 characters).
So to solve that problem, we use modular arithmetic to bound that number between [0 - 25].
Then adding 'a' to that character gets us the actual character we want to print.
Note that this only works because the character codes for a to z and A to Z are consecutive.
There are three problems with your program.
The program reads from argv[1] and argv[2], but it assumes that the program receives at least 2 arguments. If it doesn't receive this many, then it can crash or do arbitrary things. You should explicitly check that the program receives at least (or exactly) 2 command-line arguments:
if (argc != 3) {
fprintf(stdout, "Not enough arguments\n");
exit(1);
}
Note: Rename arc to argc, and there is an extra implicit argument for the program name, which is why we check for 3.)
The program copies argv[2] into a fixed-size buffer. If the message is longer than 255 characters (plus null terminator), then it can overwrite memory and cause arbitrary things to happen. In the current situation, you can process the characters of argv[2] directly without copying it to a temporary variable:
for (i = 0; argv[2][i] != '\0' ; i++) {
printf("%c", encrypt(argv[2][i], shift));
}
The Caesar shift needs to wrap around after z or Z. See sharth's answer.