caesar cipher algorithm c++ - c++

i'm trying to implement Ceaser cipher in c++ language
#include <iostream>
#include <string>
#include <locale>
using namespace std;
int main()
{
string word;
getline(cin,word);
for(int i=0; i<word.length();i++)
{
if(isalnum(word[i]))
{
//shift by 3
word[i]+= 3;
}
}
cout << word ;
return 0;
}
what i want is to limit the output also for only letter and number .
for example if i want to shift z by 3 the output would be 'c' and not '}' as in my code .

Compilers are much better at handling the tedious details than humans, so in this case, I would write the code to show clearly what you intend, and then let the compiler figure out the numbers.
For example, if you want to shift a letter, don't you really just want to add 3 to the index of the letter in the range A to Z, and then mod by 26 -- the number of letters from A to Z? This is really what you want -- rotate around the circle of LETTERS from A to Z, of which there are 26, and not worry about ASCII values.
In that case, you can let the compiler figure it out for you:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int shift = 3;
char* input = "Is it 90 with a ZERO?";
printf("%s\n", input);
int length = strlen(input);
char* output = malloc(length + 1);
output[length] = '\0';
for (int i = 0; i < length; i++)
{
char c = input[i];
if (c >= 'A' && c <= 'Z')
{
c = (((c - 'A') + shift) % 26) + 'A';
}
else if (c >= 'a' && c <= 'z')
{
c = (((c - 'a') + shift) % 26) + 'a';
}
else if (c >= '0' && c <= '9')
{
c = (((c - '0') + shift) % 10) + '0';
}
output[i] = c;
}
printf("%s\n", output);
}
Why would you want to take on that responsibility, if you are not worried about speed or memory footprint?

You have to make sure it does not go out of the valid range for ASCII letters. A way of doing this is to convert the input to lowercase, then make sure that when the shift is added, it does not exceed 122 (z's value in ASCII).
if (word[i] + SHIFT > 'z') {
SHIFT -= 123 - word[i];
word[i] = 'a'; // go back to the beginning
word[i] += SHIFT; // add on the remaining amount
}

This should work.This assumes that there will be only lower case letters.
word[i]+= 3;
//at this point word[i] might have cross the ascii limit for lower case letters
ie may be word[i]>122.Ascii range for lower case letters is 97-122
So we use mod to wrap it around.
But now may be word[i]<97 which is again out of range so we add 97 to it.
word[i]%=123;
if(word[i]<97)word[i]+=97;
Example z
word[i]+=3 makes word[i] as 125 //out of range
word[i]%=123 //word[i]=3
word[i]+=97 //word[i]=99=c

Related

hexa-decimal to decimal conversion (using implicit type casting)

I think there's some problem in my vs code I am new to this coding stuff even after writing the correct code it gives me wrong results in almost every second code I write i get uncertain results Plz guys help me with this , plz check running this code in your machine....
#include <iostream>
using namespace std;
int main()
{
char a[30];
cout << "enter the hexadecimal";
cin >> a;
int i = 0, c, digit, decimal = 0, p = 1;
while (a[i] != '\0') {
i++;
}
for (int j = i; j >= 0; j--) {
c = a[j];
if (c >= 48 && c <= 57) {
digit = c - 48;
}
else if (c >= 97 && c <= 112) {
digit = c - 87;
}
decimal += digit * p;
p *= 8;
}
cout << "\ndecimal is " << decimal;
return 0;
}
while entering hexa decimal plz only enter small alphabets i have not taken capital letters into consideration
for cheking hexadecimal to decimal use this site https://www.rapidtables.com/convert/number/hex-to-decimal.html?x=146
There are several problems with the code, but I think that the main one is that you are multiplying p by 8 when it should be 16 (as hex is base-16, not base-8).
You also should take care with invalid inputs. What happens if someone enters an invalid letter 'j' for instance?
Besides, when you calculate the initial length of the string, you are setting ito the position of the array with a '\0' value so when you start processing the input, a[i] is 0 and that leads to using an uninitialized variable (digit has not been assigned a value, this is related to the previous "invalid input" issue).
By the way, I would also use chars in the comparisions instead of ASCII codes, it's easier to see what you are looking for:
if (c >= '0' && c <= '9') {
digit = c - '0';
}
and so on...

Return the complete uppercase/lowercase converted string

I am writing a program to convert all lowercase letters in a string to uppercase letters, vice versa.
However, I found that my program cannot return the whole converted string.
Here are outcomes and my program code.
Input: "a Survey", Output: "A".
Input: "Hello", Output: "hELLO".
#include <iostream>
#include <cstring>
using namespace std;
int main() {
char inWord[50], outWord[50];
int j = 0;
cin.getline(inWord, 50);
for (j = 0; j < strlen(inWord); j++)
{
//upper to lower
if (inWord[j]>='A'&&inWord[j]<='Z')
outWord[j] = inWord[j] + 'a' - 'A';
//lower to upper
else
outWord[j] = inWord[j] + 'A' - 'a';
}
cout << outWord;
return 0;
}
You need to take into account characters that are not letters. Now you are converting the space to 0, which is the way cout knows he needs to stop reading from the string. This is a simple solution:
#include <iostream>
#include <cstring>
using namespace std;
int main() {
char inWord[50], outWord[50];
cin.getline(inWord, 50);
for (int j = 0; j < strlen(inWord); j++)
{
char c = inWord[j];
//upper to lower
if (c>='A' && c<='Z')
outWord[j] = c + 'a' - 'A';
//lower to upper
else if (c>='a' && c<='z')
outWord[j] = c + 'A' - 'a';
else
outWord[j] = c;
}
cout << outWord;
return 0;
}
And if you are programming in C++, you should probably replace those char[50] with std::string, and avoid that using namespace std:
#include <iostream>
#include <string>
int main() {
std::string inWord, outWord;
std::getline(std::cin, inWord);
outWord.reserve(inWord.size());
for (int i = 0; i < inWord.size(); i++)
{
char c = inWord[i];
//upper to lower
if (c>='A' && c<='Z') {
outWord.push_back(c + 'a' - 'A');
}
//lower to upper
else if (c>='a' && c<='z') {
outWord.push_back(c + 'A' - 'a');
}
else {
outWord.push_back(c);
}
}
std::cout << outWord;
return 0;
}
In ascii,
' ' is not in 'A'-'Z' range, so second branch is taken.
By hazard, its value is 'a' - 'A'. resulting in '\0' (nul terminator of C-string).
To fix that issue, you have to handle a third case:
const std::size_t size = strlen(inWord)
for (std::size_t j = 0; j < size; j++)
{
//upper to lower
if (inWord[j]>='A'&&inWord[j]<='Z')
outWord[j] = inWord[j] + 'a' - 'A';
//lower to upper
else if (inWord[j]>='a'&&inWord[j]<='z')
outWord[j] = inWord[j] + 'A' - 'a';
else
outWord[j] = inWord[j];
}
'a'-'z', 'A'-'Z' are not guaranteed to be contiguous ranges (it is for Ascii, not for EBCDIC), so you might use standard methods instead (even if their interfaces is error prone :( ):
const std::size_t size = strlen(inWord)
for (std::size_t j = 0; j < size; j++)
{
unsigned char c = static_cast<unsigned char>(inWord[j]);
if (std::isupper(c))
outWord[j] = static_cast<char>(std::tolower(c));
//lower to upper
else if (std::islower(c))
outWord[j] = static_cast<char>(std::toupper(c));
else
outWord[j] = inWord[j];
}
If you want to convert all letters to for instance to the opposite case you would need to check which case the string is after input. (for instance by counting the upper case characters).
Right now you are inverting the case of each letter, as you do an if else comparison of each letter in the loop. If you execute only one of the 2 branching conditions it will do an conversion to the same case.
A few words on how you might want to improve your style:
You can define j inside the for loop if you are not using the int outside of the loop
for (int j = 0; j < strlen(inWord); j++){}
'a' - 'A' and 'A' - 'a' do have the same absolute value and do not change during the loop, so you could define a variable before the loop and then add or subtract inside of the loop respectively.
It is also useful to know that C++ treats characters as 8bit numbers in the case of ascii, this is the reason why the offset calculation works:
Link to an ASCII table

C++ Not sure how to have my program output the location of a space

Alright, so I have two questions and if anyone can help me out I would greatly appreciate it! This is my first programming class, so it would also be my first C++ class and I'm a bit stuck.
So I created a Caesar cipher that shifts the string that the user inputs to the right by a pseudo random number between 8-15. What the complete program needs to do is give the number it is shifted by at the beginning, followed by the encrypted string. If there are spaces in the string that are inputed, they need to take the letter/number that is before the space and shift it by 4. I need to terminate the encryption with an '&' character and that is followed by a '#' character and then the number location of the first space followed by another '#' character and another location of a second space if there is one and so on.
So for example, if I were encrypting a string that was being shifted by 9 and said:
Hello World 123
It should look like this when encrypted:
9qnuuxsfxaumh012&#6#12
My first and more important question. I can't figure out how to make the program output the '#' character followed by the number that tells the location of the space. I've thought of maybe doing some kind of loop that reads the string but I'm coming up blank. If I could get some advice that would be great as this is the only part holding me up from turning this in.
My second question comes from a little confusion within my own code that I would love an English interpretation on how it works since I don't understand it myself. I was first using just for loops to make it so that the character 'z' would wrap back around to 'a' but no matter what I did, I kept getting it to only wrap around after a '{' character which is the next character after 'z' on the ascii table. So I decided to change my method and I read on wikipedia under "Caesar cipher" that you could use a modulus. So I used the equation they gave me which was E(x) = (a + b) mod 26. Well it didn't work. So I started to do a google search and saw 2 different posts where people subtracted the character 'a' and then added the chracter 'a' back on at the end as well as added the variable to itself with +=. So I put it in and it worked.
It looks like this:
output += ((input[count] - 'a' + n) % 26) + 'a';
and I thought it would look like this after reading the wiki and it not working when i put this in
output = ((input[count] + n) % 26)
Same goes for wrapping the numbers as well:
output += ((input[count] - '0' + n) % 10) + '0';
So if someone could explain to me why I am adding output to itself as well as subtracting 'a' in the beginning and then re-adding 'a' at the end so I could understand what's going on. I really don't like having code in a program that I'm going to turn in that I don't even understand myself.
Anyways, I'm sorry for the long read, I just thought I would explain what's going on and what I need clearly so that anyone willing to help would completely understand what I'm saying without me having to follow up with a second post explaining.
And finally here's the full program that I have written:
#include <ctime>
#include <iostream>
#include <string>
#include <cstdlib>
#include <fstream>
using namespace std;
//random number generator between 8 and 15
int random()
{
int value;
value = rand() % (18 - 10) + 8;
return value;
}
int main()
{
//Give random() a seed
srand(time(NULL));
//Declare variables
string input;
int length;
int n = random();
string output;
//Program
cout << "Enter your secret message: " << endl;
getline (cin, input);
cout << n;
length = input.length();
for (int count = 0; count < length; count++)
{
input[count] = tolower(input[count]);
if (input[count] >= 'a' && input[count] <= 'z')
{
output += ((input[count] - 'a' + n) % 26) + 'a';
}
if (input[count] >= '0' && input[count] <= '9')
{
output += ((input[count] - '0' + n) % 10) + '0';
}
else if(input[count] == ' ')
{
if (input[count - 1] >= 'a' && input[count - 1] <= 'z')
{
output += ((input[count - 1] - 'a' + 4) % 26) + 'a';
}
else if (input[count - 1] >= '0' && input[count - 1] <= '9')
{
output += ((input[count - 1] - '0' + 4) % 10) + '0';
}
cout << output;
}
}
cout << output << endl;
return 0;
}
Thanks so much for anyone willing to help!
Two answer the second question:
input[count] - 'a'
This gives you 0 for the letter a, 1 for the letter b, ... 25 for the letter z.
input[count] - 'a' + n
Then you add the number n. Having "a" as an input and being n==2 you will get a 3. But for a "z" as input you will get a 27.
To solve the problem you use the modulus:
(input[count] - 'a' + n) % 26
The result is a 1 for the "z".
((input[count] - 'a' + n) % 26) + 'a'
Now you transfer the number from 0 to 25 back to the corresponding ASCII code.
The point of the seemingly odd expansion is to do the following:
Create a number from 0..25: input[count] - 'a'
Adjust that number by adding your shift amount: + n
Modulo the result with 26 to wrap overflow of 26+ back into 0..25: % 26
And finally, add that result back to the base character: +a``
Your idea of a shortcut:
output = ((input[count] + n) % 26)
simply takes the ascii value of the input char, adds the shift, then modulo 26. The result is a value in 0..25, nowhere near the range of 'a'..'z'.
And before you think just adding 'a' would work, it isn't that simple. For example, suppose you had a shift of 9 and in input char of 'z'
The presented formula that works: (ch - 'a' + n) % 26 + 'a'
(('z' - 'a' + 9) % 26 + 'a'
((122 - 97 + 9) % 26 + 97
34 % 26 + 97
8 + 97
105, the ascii value of 'i'
Your formula, with 'a' adjustment: (ch + n) % 26 + 'a'
('z' + 9) % 26 + 'a'
(122 + 9) % 26 + 97
131 % 26 + 97
1 + 97
98, the ascii value for 'b'.
The problem is the distance from the beginning of the char sequence that is being modulo-adjusted is never accounted for in the modulo reduction. Thus the reason for the formula you find odd.
Regarding how to accumulate a list of space locations. a ostringstream will make that trivial, as would a std::vector<int>. An example of the former looks like this:
#include <ctime>
#include <iostream>
#include <string>
#include <cstdlib>
#include <fstream>
#include <sstream> // for std::ostringstream
using namespace std;
int main()
{
//Give random() a seed
srand(static_cast<unsigned>(time(NULL)));
//Declare variables
string input;
int length;
int n = rand() % (18 - 10) + 8;
string output;
//Program
cout << "Enter your secret message: " << endl;
getline (cin, input);
cout << n;
// string stream to hold the list of space locations.
std::ostringstream oss;
length = input.length();
for (int count = 0; count < length; count++)
{
input[count] = tolower(input[count]);
if (input[count] >= 'a' && input[count] <= 'z')
{
output += ((input[count] - 'a' + n) % 26) + 'a';
}
if (input[count] >= '0' && input[count] <= '9')
{
output += ((input[count] - '0' + n) % 10) + '0';
}
else if(input[count] == ' ')
{
if (input[count - 1] >= 'a' && input[count - 1] <= 'z')
{
output += ((input[count - 1] - 'a' + 4) % 26) + 'a';
}
else if (input[count - 1] >= '0' && input[count - 1] <= '9')
{
output += ((input[count - 1] - '0' + 4) % 10) + '0';
}
// add space location with preamble to string stream
oss << '#' << count;
}
}
// append space accumulated list string to the end after '&'
cout << output << '&' << oss.str() << endl;
return 0;
}

C++ caesar cipher — understanding ascii keys

I am currently doing a caesar cipher program. It should encrypt for both lower and upper case.
e.g
If I typed in a, it will then shift the keys by 3 and the final output will become d.
Take a look at my codes
char c;
c = (((97-52)+3) % 26) + 52;
cout << c;
The letter 'a' has an ASCII code of 97.
So by right
1) ((97-52)+3) will give you 48
2) 48 % 26 will give you 8 since 48/26 will give you a remainder of 8.
3) 8 + 52 = 60(which will by right give you a value of '>' according to the ascii table)
but my output that I have got is J and I don't understand which am I getting the output of 'J' instead of '>'
My concepts might be wrong so I need help.
Let me link ASCII chart I use first: http://pl.wikipedia.org/wiki/ASCII
The website is polish, but table itself is in english.
I think it's plainly obvious that problem is the equatation you use:
(((letter-52)+3) % 26) + 52;
Actually first letter in ASCII is 65(hexadecimal 0x41 - follow with the chart provided).
Your idea with the modulo would be fine, if there were no chars between letter blocks in ASCII. But there are (again check up chart).
That is why you should manually check if the sign:
is a capital letter: if (letter >= 0x41 && letter <= 0x5a)
is a non-capital: if (letter >= 0x61 && letter <= 0x7a)
Usually when making Ceasar cipher, you should follow these:
Replace a capital letter with capital letter moved in the alphabet by a given number.
If the letter would be out of alphabet scope, continue iteration from the start of alphabet (X moved 5 to the right would give C).
Other chars stay the same
Now let's implement this (in code I'll use letter values of chars - to avoid mistakes):
#include <iostream>
#include <cstdlib>
using namespace std;
string Ceasar(string input, int offset)
{
string result = "";
for (int i = 0; i < input.length(); ++i)
{
// For capital letters
if (input[i] >= 'A' && input[i] <= 'Z')
{
result += (char) (input[i] - 'A' + offset) % ('Z' - 'A') + 'A';
continue;
}
// For non-capital
if (input[i] >= 'a' && input[i] <= 'z')
{
result += (char) (input[i] - 'a' + offset) % ('z' - 'a') + 'a';
continue;
}
// For others
result += input[i];
}
return result;
}
int main()
{
cout << Ceasar(string("This is EXamPLE teXt!?"), 8).c_str();
system("PAUSE");
}

C++ manipulating numbers in ASCII to stay only in range of letters

#include <iostream>
using namespace std;
Int main() {
cout<<"Give me a letter" <<endl;
char letter;
cin>>letter;
cout<<letter;
(Int)letter;
letter+=2;
cout<<(char)letter;
(Int)letter;
letter-=25;
cout<<(char)letter;
return 0;
}
How would I manipulate the numbers in a way so that the numbers will always output a letter.
ie: if the letter z was chosen and adding 2 is a symbol how would I manipulate it in a way so that it will always stay between the numbers for capital numbers and uncapitalized numbers. Thanks. Please try to keep answers at a beginner level please I am new to this.
if(letter > 'z') {
//do stuff
}
if(letter < 'a' && letter > 'Z') {
//do stuff
}
if(letter < 'A') {
//do stuff
}
It just depends on how you want to handle the character when it goes into one of the three ranges on the ASCII chart in which the characters are not letters.
As a side note, you don't have to cast a char to an int to do math with it.
char myChar = 'a' + 2;
cout << myChar;
This will print: c
c has an ASCII value of 2 more than a.
The surest method is to use a table for each category, and do
your arithmetic on its index, modulo the size of the table.
Thus, for just lower case letters, you might do something like:
char
transcode( char original )
{
char results = original;
static std::string const lower( "abcdefghijklmnopqrstuvwxyz" );
auto pos = std::find( lower.begin(), lower.end(), results );
if ( pos != lower.end() ) {
int index = pos - lower.begin();
index = (index + 2) % lower.size();
results = lower[ index ];
}
return results;
}
This solution is general, and will work regardless of the sets
of letters you want to deal with. For digits (and for upper and
lower case, if you aren't too worried about portability), you
can take advantage of the fact that the code points are
contiguous, and do something like:
char
transcode( char original )
{
char results = original;
if ( results >= '0' && results <= '9' ) {
char tmp = results - '0'
tmp = (tmp + 2) % 10;
results = tmp + '0';
}
return results;
}
An alternative implementation would be to use something like:
results = results + 2;
if ( results > '9' ) {
results -= 10;
}
in the if above. These two solutions are mathematically
equivalent.
This is only guaranteed to work for digits, but will generally
work for upper or lower case if you limit yourself to the
original ASCII character set. (Be aware that most systems today
support extended character sets.)
You can test directly against ASCII chars by using 'x' notation. Further, you can test things together using && ("and" respectively"):
if ('a' <= letter && letter <= 'z') {
// Letter is between 'a' and 'z'
} else if ('A' <= letter && letter <= 'Z')) {
// Letter is between 'A' and 'Z'
} else {
// Error! Letter is not between 'a' and 'z' or 'A' and 'Z'
}
Or you can use the standard library function std::isalpha which handles this for you:
if (std::isalpha(letter)) {
// Letter is between 'a' and 'z' or 'A' and 'Z'
} else {
// Error! Letter is not between 'a' and 'z' or 'A' and 'Z'
}