C++ caesar cipher — understanding ascii keys - c++

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");
}

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...

caesar cipher algorithm 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

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++ 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'
}

How does this array conversion work ( lowercase to uppercase using a string)?

I got the program to work as expected, but can anyone explain how it works?
#include <iostream>
using namespace std;
int main(void) {
int exit;
string name;
cin >> name;
for (int i = 0; i < name.length(); i++) {
// the line below is the one I don't understand
if ('a' <= name[i] && name[i] <= 'z') name[i] = char(((int)name[i]) - 32);
}
cout << name;
cin >> exit;
return 0;
}
EDIT: Let me rephrase:
The thing I don't understand is how does the string-to-array deal work, as in:
'a'<= name[i]. What exactly does this compare and how?
EDIT2
Thanks for the quick responses guys, love you all. I figured it out.
This is the line:
if('a'<=name[i] && name[i]<='z')name[i]=char(((int)name[i])-32);
broken down:
if( 'a'<=name[i] ) {
if( name[i]<='z' ) {
// name_int is a temporary, which the above code implicitly creates,
// but doesn't give a name to:
int name_int = name[i];
name_int = name_int - 32;
name[i] = char(name_int);
}
}
and note that 32 happens to equal 'a'-'A' in the character encoding you are using.
(Technically name_int should be an int&& or somesuch, but no need to be that confusing.)
I assume from the edit in your comment that you are wondering how the [] can apply to a string object. The operator [] is overloaded for string to return a reference to the character at the specified position offset of the represented string. There need not be any direct conversion of the string into an array. The code that implements the overload could well be walking a linked list. It depends on how string was implemented.
It assumes ASCII character format where to convert from lowercase to uppercase you subtract 32 from the original ASCII value. This is because the ASCII values for uppercase are smaller than those for lower case and it's a constant difference between A and a, B and b and so on.
For reference: http://www.asciitable.com/
'a' <= name[i] && name[i] <= 'z'
This line is comparing the corresponding ASCII values of these two characters. 'a' in ASCII is 97 and 'z' is 122. If name[i] is one of the characters from 'a' to 'z' the expression returns true. This is commonly used to check if a variable is alphabetic.
if ('a' <= name[i] && name[i] <= 'z')
char objects are numeric values similar to ints. So 'a' <= name[i] is simply testing if the numeric value of 'a' is less than or equal to the character you're examining. Combined with name[i] <= 'z' and you're testing if the numeric value of name[i] is between the values of 'a' and 'z'. Now, it just so happens that the most common scheme for assigning numeric values to chars, named "The American Standard Code for Information Interchange" (ASCII), has the alphabet arranged in order; 'a' + 1 = 'b', 'b' + 1 = 'c', and so on. So figuring out if the character is between 'a' and 'z' tells you if it's a lower case letter.
name[i] = char(((int)name[i]) - 32);
Once you know that chars are just numeric values you might infer from the basic properties of arithmetic which we all learned in grade school that 'a' + ('A' - 'a') results in the value 'A'. Further, ASCII has the upper case alphabet arranged similarly to the lower case alphabet so that 'A' + 1 = 'B', etc. So taking anycharin the lower case alphabet and adding'A' - 'a'will result in the upper case version of that letter. In ASCII'A' - 'a'` happens to have the value -32. So take the numeric value for a lower case letter, subtract 32, and you have the value for the upper case letter.
For comparison here's a version of the code that doesn't depend on ASCII:
auto l = std::locale();
if (std::islower(name[i], l))
name[i] = std::tolower(name[i], l);