Text to Caesar Cipher - c++

I am a beginner and i made a code in C++ to convert 3 characters to caesar cipher but my problem is that i can print only characters to a - w. How can i print x, y ,z using only if else statement. I have tried else if and many other things but it prints for x,y,z {|} which is +3 i know i need to do -23 but i cant get it to work pls help. This is my code for only to a - w. Edit : i still don’t get how to go from x,y,z to a,b,c if some1 has an code example i would appreciate it cus im trying but it for some reason keeps printing {|} which is ch = ch + 3; and not ch = ch - 23; which is the one i want to do with else if statement
char ch1;
char ch2;
char ch3;
cout << "Insert three characters: " << endl;
cin >> ch1;
cin >> ch2;
cin >> ch3;
if (ch1 >= '97' && ch1 <= '119' || ch2 <= '97' && ch2 <= '119' || ch3 >= '97' && ch3 <= '119') {
ch1 = ch1 + 3;
ch2 = ch2 + 3;
ch3 = ch3 + 3;
cout << "Caesar Cipher: " << ch1 << ch2 << ch3 << endl;
}

To wrap your characters around, you need the modulo operator, %. But first you must transform the letter to a zero-based value. After that, you have a number in the range [0, 25] and you can offset it. You then take the modulo to wrap the new value to the same range and finally transform it back to an alphabet character.
Example:
ch1 = 'a' + (ch1 - 'a' + 3) % 26;
Notice I'm using a character literal here. You should always avoid hard-coding character values, as that just makes your code more difficult to read and less portable. To test if a value is lowercase, there's a standard library function std::islower (and a corresponding std::isupper) found in the header <cctype>.
Fixing your code up a bit, it becomes:
if (std::islower(ch1)) ch1 = 'a' + (ch1 - 'a' + 3) % 26;
if (std::islower(ch2)) ch2 = 'a' + (ch2 - 'a' + 3) % 26;
if (std::islower(ch3)) ch3 = 'a' + (ch3 - 'a' + 3) % 26;
cout << "Caesar Cipher: " << ch1 << ch2 << ch3 << endl;
But look at all the code duplication! What if you want to change the key, or use more or less characters, or change the encoding algorithm completely? That's where a function comes in handy:
char EncodeChar(char c, int key)
{
if (std::islower(c))
c = 'a' + (c - 'a' + key) % 26;
return c;
}
Now you can use it like this:
const int key = 3;
ch1 = EncodeChar(ch1, key);
ch2 = EncodeChar(ch2, key);
ch3 = EncodeChar(ch3, key);
Even better, read your characters into a std::string and encode it in-place. You're no longer restricted to exactly three characters:
void CaesarEncode(std::string& s, int key)
{
for (char& c : s) c = EncodeChar(c, key);
}
Call that like this:
std::string text = "Hello, world!";
CaesarEncode(text, 3);
std::cout << text << "\n";
Now, this will work for positive offsets, but not negatives. If you need to apply a negative offset, you need to add an additional 26 before modulo which ensures you never go below zero. It's useful to support both, because you probably want to decode the ciphertext at some point. You can use the same function but make the key negative.
One way to approach this is to modify a negative key at the last minute with a recursive call in your CaesarEncode function:
void CaesarEncode(std::string& s, int key)
{
if (key < 0)
{
CaesarEncode(s, 26 - (-key % 26));
return;
}
for (char& c : s) c = CaesarEncode(c, key);
}
Let's continue. What about capital letters? You can handle those too:
char EncodeChar(char c, int key)
{
if (std::isalpha(c))
{
char base = std::islower(c) ? 'a' : 'A';
c = base + (c - base + key) % 26;
}
return c;
}
As you can see, using functions makes life much easier, because you don't need to create a mess when beefing up your encoding method. You just change the core logic in one place.
Rolling this all together, and with a few extra helpers from the standard library, you get a reasonably compact program that can encode and decode:
#include <algorithm>
#include <cctype>
#include <iostream>
#include <iterator>
#include <string>
std::string CaesarEncode(const std::string& s, int key)
{
if (key < 0)
{
return CaesarEncode(s, 26 - (-key % 26));
}
auto fnEncodeChar = [key](unsigned char c) -> unsigned char
{
if (std::isalpha(c))
{
char base = std::islower(c) ? 'a' : 'A';
c = base + (c - base + key) % 26;
}
return c;
};
std::string encoded;
std::transform(s.begin(), s.end(), std::back_inserter(encoded), fnEncodeChar);
return encoded;
}
std::string CaesarDecode(const std::string& s, int key)
{
return CaesarEncode(s, -key);
}
int main()
{
const int KEY = 3;
std::string line;
while (std::getline(std::cin, line))
{
std::string encoded = CaesarEncode(line, KEY);
std::string decoded = CaesarDecode(encoded, KEY);
std::cout << "Original : " << line << "\n";
std::cout << "Encoded : " << encoded << "\n";
std::cout << "Decoded : " << decoded << "\n";
}
}
Input:
This is a test.
Output:
Original : This is a test.
Encoded : Wklv lv d whvw.
Decoded : This is a test.

Related

wraparound c++ for ASCII

I'm Matt, first time posting. I'm in school and learning c++ at the moment and I'm stuck on this problem. I can't seem to find the solution so I'm looking for help.
#include <iostream>
using namespace std;
int main()
{
char ch;
cin >> ch;
if(ch <= 122){
cout << ++ch;
cout << ++ch;
}else if (ch > 122){
cout << static_cast<char>(97)++ch;
cout << static_cast<char>(97)++ch;
}
}
The program is very basic. All it needs to do is be fed a lowercase letter and the program just needs to spit out the next two characters. My problem is that after 'z' I don't know how to wrap back around to 'a'. I've tried to static_cast but it says I can'. I've tried reassigning the variable and it says I can't. I've tried several other basic things but none seem to work.
Thank you in advance for the help!
First, don't use magic numbers like 122 and 97. Use the actual character value.
Second, just declare a string abcdefghijklmnopqrstuvwxyz, and index into that string. This eliminates the need for 122, 97, or any other number. Not only that, you can probably see how to do the problem much easier when dealing with indices such as 0, 1, 25, etc. instead of 122, 97, etc.
Once you do that, a little bit of insight shows that the next two characters will be at position (if positions start at 0), (index + 1) % 26 and (index + 2) % 26. The % is the modulus operator, and it returns the remainder after a division is done.
For example, if the current character is y, the yis located at position 24 of the string. So
(24 + 1) % 26 = 25 % 26 = 25
and
(24 + 2) % 26 = 26 % 26 = 0
So the next two characters are situated at position 25 and position 0, which are z and a.
Take another example: z:
(25 + 1) % 26 = 26 % 26 = 0
and
(25 + 2) % 26 = 27 % 26 = 1
So the next characters after z are a and b.
Basically, when you get an assignment where the data "wraps around" to 0, then the word "remainder" or "modulo arithmetic" should immediately come to mind.
So the final program would look like this:
#include <iostream>
int main()
{
char ch;
const char * alphabet = "abcdefghijklmnopqrstuvwxyz";
std::cin >> ch;
int position1 = ch - 'a'; // get position of input character
int position2 = (position1 + 1) % 26; // get position of next character
int position3 = (position1 + 2) % 26; // get position of next next character
// output results
std::cout << ch << alphabet[position2] << alphabet[position3];
}
Live Example
(assuming that the input is: 'a' - 'z')
Keep It Simple
Solution 1:
#include <iostream>
int main()
{
char ch = 0;
std::cin >> ch; // "fed a lowercase letter"
// "spit out the next two characters"
if (ch < 'y')
std::cout << ++ch << ++ch;
else if (ch == 'y')
std::cout << "za";
else // (ch=='z')
std::cout << "ab";
}
Solution 2:
#include <iostream>
int main()
{
const char * lut = "abcdefghijklmnopqrstuvwxyzab";
char ch = 0;
std::cin >> ch; // "fed a lowercase letter"
ch -= 'a'; // lowercase letter to index
// "spit out the next two characters"
std::cout << lut[++ch] << lut[++ch];
}
Try to use the following code for your problem.
#include <iostream>
using namespace std;
int main()
{
char ch = '\0';
cin >> ch; // "fed a lowercase letter"
char c_next;
c_next = (ch-'a'+1)%26+'a';
cout <<c_next;
c_next = (ch-'a'+2)%26+'a';
cout << c_next;
return 0;
}
Here is one way at going about tackling your problem that is clean and elegant. It is very readable that uses a look up table, converts caps to lowercase using a bit of modulo arithmetic; it also leverages some of the newer features of modern C++ such as range loops.
#include <iostream>
#include <ccytpe> // needed for ::tolower
int main() {
// ascii a-z [97,122]
char alphabet[26] = {}; // 0 initizlize this will be a look up table
int i = 97;
for( auto & c : alphabet ) {
c = static_cast<char>( i );
i++;
}
// check to see if our table is correct
for( auto & c : alphabet ) {
std::cout << c << " ";
std::cout << '\n';
}
std::cout << '\n';
// Alphabet Seems to be fine.
char c = {};
std::cout << "Please enter a lower case character: ";
std::cin >> c;
if( c >= 'A' && c <= 'Z' ) {
::tolower( c ); // make sure that it's not in caps
} else if( c >= 'a' && c <= 'z' ) {
// nothing to do
} else {
std::cout << "Error: input value\n";
return -1;
}
// Now that we have the correct inputs we can show your next two characters.
// Since we know that the ascii table has a range of [97,122] for
// lower case letters and that our array index starts at 0; what we can do
// is a little bit of arithmetic to take the input character and set that
// to the index value of the array above. Then use the array indexing to
// output the next 2 characters. To do this we simply just need to subtract 97 or 'a'
c = c - 'a';
// Now we can print the two lines using the adjusted c value with
// a little bit of modulo arithmetic using the stride, size, or
// length of the alphabet.
int stride = 26;
std::cout << alphabet[++c % stride] << '\n';
std::cout << alphabet[++c % stride] << '\n';
// And we are done!
return 0;
}
This is what the code would look like without the comments and the code to print the whole alphabet:
#include <iostream>
#include <cctype>
int main() {
char alphabet[26] = {};
int i = 97;
for( auto & c : alphabet ) {
c = static_cast<char>( i );
i++;
}
char c = {};
std::cout << "Please enter a lower case character: ";
std::cin >> c;
if( c >= 'A' && c <= 'Z' ) {
::tolower( c );
} else if( c >= 'a' && c <= 'z' ) {
// nothing to do
} else {
std::cout << "Error: input value\n";
return -1;
}
c = c - 'a';
int stride = 26;
std::cout << alphabet[++c % stride] << '\n';
std::cout << alphabet[++c % stride] << '\n';
return 0;
}

ROT-13 using the entire printable ASCII Character Set C++

I am trying to create a code that will use the entire printable ASCII Character set. My problem is that when it comes to characters that will be a number higher than 126 they print as '?', except for 'r', which prints correctly. Why does my code allow 'r' to roll back up to a printable character but not any characters after that? (stuvwxyz{|}~)
" Please enter your password.
abcdefghijklmnopqrstuvwxyz{|}~
nopqrstuvwxyz{|}~!???????????? "
#include <iostream>
#include <string>
using namespace std;
void encrypt(string password)
{
int count = 0;
char i;
for (count = 0; count < password.length(); count++)
{
i = password.at(count) + 13;
if (i >= 127)
{
i = 32 + (i - 126);
cout << i;
}
else
cout << i;
}
return;
}
int main()
{
string password;
cout << "Please enter your password." << endl;
cin >> password;
encrypt(password);
cout << "\n";
return 0;
}
Your target platform has signed char, so valid values in char are of range -128 .. +127.
Thus your if (i >= 127) will cover only 'r' (value 114), for 's' the i is equal to -128, not +128. And your if will be false and you will output -128 char value.
One quick-fix is to declare i as unsigned char to operate rather on range +0 .. +255. If you are going to support only valid ASCII 7b input, then that is enough to have all that +13 arithmetic correct.
Also I'm not sure why you do 32 + (i - 126);, that's asking r to convert to ! (33), skipping space (32), which is printable ASCII character.
So after those fixes applied, and simplifying the code a bit (toward C++ style), I ended with:
void encrypt(const string & password)
{
for (unsigned char charToRot13 : password) {
charToRot13 += 13;
if (127 <= charToRot13) charToRot13 -= (127 - ' ');
cout << charToRot13;
}
}
Which does input+output ('r' now maps to ' '):
Please enter your password.
abcopqrstuvw
nop|}~ !"#$%
BUT. The main ROT13 feature is, that you can encrypt and decrypt the text by the same operation. I.e. "abc" -> "nop" -> "abc" -> "nop" -> ...
Your conversion to whole ASCII range breaks that feature. So what you probably want is to cover whole +32 .. +126 range of ASCII values, that's 95 of them. 95/2 = 47.5, not good. Let's remove space, because you already did that by that -126, so you probably don't want it. The value range to encrypt is then +33 .. +126 = 94 of them. 94/2 = 47, good. To get ROT13-like encryption for whole ASCII range (except space) you can use ROT47.
void encrypt(const string & password)
{
for (unsigned char charToRot47 : password) {
if (charToRot47 < 33 || 126 < charToRot47) {
cout << "\nERROR: detected invalid character.\n";
break;
}
charToRot47 += 47;
if (126 < charToRot47) charToRot47 -= 94;
cout << charToRot47;
}
}
This will output:
Please enter your password.
xyz{|}~!"#$%000000IJKLMNOPQRST
IJKLMNOPQRST______xyz{|}~!"#$%
(notice how for example 'y' -> 'J' -> 'y' -> 'J' -> ...)

c++ input character or check length of string is 1?

So I was originally using cin to have the user input a character. Then if this character isn't a, b, or c, it continues to loop and prints an error message. However, if the user enters multiple characters, it prints the error message multiple times. So now I'm using scanf to take in a string and check if the length is 1. This is straight up just not working at all.
string enterLetter() {
string n;
scanf("%s", &n);
return n;
}
void main() {
string ch = "";
cout << "Type a, b, or c: ";
while (ch != "a" && ch != "b" && ch != "c"){
while (ch.length() != 1) {
ch = enterLetter();
cout << ch.length();
}
ch = tolower((char)ch.c_str());
cout << "\n" << ch;
}
You can't use scanf("%s") with std::string like you are attempting. scanf("%s") expects a pre-allocated char[] instead. If you want to read a std::string, use std::cin.operator>>() or std::getline() instead:
char enterLetter() {
string n;
do {
std::getline(std::cin, n);
}
while (n.length() != 1);
return n[0];
}
int main() {
char ch;
do {
std::cout << "Type a, b, or c: ";
ch = enterLetter();
}
while ((ch != 'a') && (ch != 'b') && (ch != 'c'));
std::cout << ch;
return 0;
}
You don't need to, nor should you use a string for this. Using a char with scanf works better.
int main() {
char ch;
cout << "Type a, b, or c: ";
scanf("%c", &ch);
while ((ch > 'C' && ch < 'a') || ch > 'c' || ch < 'A' ) {
if (ch >= 'A' && ch <= 'Z')
ch += ('a' - 'A');
cout << endl << ch;
cout << endl << "Enter a, b, or c: ";
scanf("%c", &ch);
}
}
This uses scanf to get a char ch. It loops while the char is not a, b, c or A, B, C (as you seemed to want an uppercase use case). If the char is uppercase it gets converted to lower case and then outputs the char.
You could use cin.getline() to read a whole line of user input terminated by the Enter key.
char str[64];
cin.getline(str, sizeof(str));
if the strlen(str) is not equal to 1, an error can be thrown. Otherwise, str[0] can be compared with a, b or c.
If you scanfa string in a loop, it will return the first set of characters terminated by a whitespace (space-bar or new-line char). In the next iteration it will read the next string and so. If a user enters something like "abc def\n", scanf will first return abc followed by def. If you use cin.getline(), all the characters entered until the newline, i.e. "abc def" will be returned in the first call to cin.getline().

Read digits from an int and counting them

Alright so I've been looking though Google and on forums for hours and can't seem to understand how to solve this problem.
I need to write a program that first determines if the number entered by the user is a base 5 number (in other words, a number that only has 0s, 1s, 2s, 3s, and 4s in it). Then, I have to count how many 0s, 1s, 2s, etc are in the number and display it to the user.
I've seen people saying I should convert int to a string and then using cin.get().
I noticed that I can't use cin.get() on a string, it needs to be a char.
I can only use a while loop for this assignment, no while... do loops.
Any help is appreciated!!
Here's what I have so far, obviously with all my mistakes in it:
//----------------------------------------------
// Assignment 3
// Question 1
// File name: q1.cpp
// Written by: Shawn Rousseau (ID: 7518455)
// For COMP 218 Section EC / Winter 2015
// Concordia University, Montreal, QC
//-----------------------------------------------
// The purpose of this program is to check if the
// number entered by the user is a base of 5
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
// Declaring variables
int number;
int zeros;
int ones;
int twos;
int threes;
int fours;
bool base5;
// Get data and calculate
cin >> number;
string numberString = to_string(number);
// Determine if the number is a base 5 number
while (cin.get(numberString) == 0 || cin.get(numberString) == 1 ||
cin.get(numberString) == 2 || cin.get(numberString) == 3 ||
cin.get(numberString) == 4)
base5 = true;
// Determine the number of each digits
zeros = 0;
ones = 0;
twos = 0;
threes = 0;
fours = 0;
return 0;
}
Several things you need to beware of:
One way to get a specific character from a std::string is by []. e.g.
std::string myString{"abcdefg"};
char myChar = myString[4]; // myChar == 'e'
cin.get(aString) is not trying to get data from aString. It continues to get data from stdin and store in aString. Once you have get the data and put into the string, you can simply manipulate the string itself.
a short piece of code that will count number of vowel in a string. If you can understand it, there should be no problem doing your work. (Haven't compiled, probably some typos)
std::string inputString;
std::cin >> inputString;
// you said you need a while loop.
// although it is easier to with for loop and iterator...
int i = 0;
int noOfVowels = 0;
while (i < inputString.length()) {
if (inputString[i] == 'a'
|| inputString[i] == 'e'
|| inputString[i] == 'i'
|| inputString[i] == 'o'
|| inputString[i] == 'u' ) {
++noOfVowels;
}
++i;
}
std::cout << "number of vowels : " << noOfVowels << std::endl;
Well you can try this approach. This will solve your needs I guess.
#include <iostream>
#include <string>
#include <sstream>
#include <conio.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int number=0;
int zeros=0;
int ones=0;
int twos=0;
int threes=0;
int fours=0;
bool valid=true;;
int counter = 0;
cout<<"Enter the number: ";
cin >> number;
stringstream out;
out << number; //int to string
string numberString = out.str();
cout<<"\n\nNumber after string conversion : "<<numberString;
cout<<"\nPrinting this just to show that the conversion was successful\n\n\n";
while (counter < numberString.length())
{
if (numberString[counter] == '0')
zeros++;
else if(numberString[counter] == '1')
ones++;
else if(numberString[counter] == '2')
twos++;
else if(numberString[counter] == '3')
threes++;
else if(numberString[counter] == '4')
fours++;
else
valid=false;
counter++;
}
if(valid==true)
{
cout<<"\nZeros : "<<zeros;
cout<<"\nOnes : "<<ones;
cout<<"\nTwos : "<<twos;
cout<<"\nThrees : "<<threes;
cout<<"\nFours : "<<fours;
}
else
cout<<"\n\nInvalid data...base of 5 rule violated";
_getch();
return 0;
}
If you don't want to use std::string then use characters, first loop over the input from the user until ENTER is pressed.
char ch = 0;
while ((ch = cin.get()) != '\n')
{
...
}
For each character read, check if it is a digit (std::isdigit) and if it is in the range 0..4, if not quit and give some message of not being base 5
have an array of ints to keep track of the frequency of the digits
int freq[5] = {0,0,0,0,0};
after you have checked that the character is valid subtract the ascii value from the digit and use that as index in the array, increment that:
freq[ch - '0']++;
e.g.
char ch;
int freq[5] = {0};
while ((ch = cin.get()) != '\n')
{
cout << ch;
freq[ch-'0']++;
}
for (int i = 0; i < sizeof(freq)/sizeof(freq[0]); ++i)
{
cout << static_cast<char>(48+i) << ":" << freq[i] << endl;
}
Here's a useful function that counts digits:
// D returns the number of times 'd' appears as a digit of n.
// May not work for n = INT_MIN.
int D(int n, int d) {
// Special case if we're counting zeros of 0.
if (n == 0 && d == 0) return 1;
if (n < 0) n = -n;
int r = 0;
while (n) {
if (n % 10 == d) r++;
n /= 10;
}
return r;
}
In your code you can use this naively to solve the problem without any further loops.
if (D(n, 5) + D(n, 6) + D(n, 7) + D(n, 8) + D(n, 9) != 0) {
cout << "the number doesn't consist only of the digits 0..4."
}
cout << "0s: " << D(n, 0) << "\n";
cout << "1s: " << D(n, 1) << "\n";
cout << "2s: " << D(n, 2) << "\n";
cout << "3s: " << D(n, 3) << "\n";
cout << "4s: " << D(n, 4) << "\n";
You could also (or should also) use loops here to reduce the redundancy.

Encryption issue in c++

I'm currently attempting to implement a substitution cipher that for some reason keeps crashing, the code is fairly straight forward but I keep running into problems I believe originate in the for loop or when I attempt to read in the data from a file.
cout << "Ener a key :";
cin >> key;
cin.ignore();
cout << endl << "Enter input file name: ";
getline(cin,fileIn);
inputfile.open(fileIn.c_str(), ios::in);
cout << endl << "Enter output file name: ";
getline(cin,fileOut);
outfile.open(fileOut.c_str(), ios::app);
cout << endl << "[E]ncryption or [D]ecryption? :";
cin >> EorD;
//Encryption
if (EorD == "E" || "e")
{
while(!inputfile.eof()) // Reading in file data, while not end of file.
{
getline(inputfile,plainText);
}
for (int i = 0; i <= plainText.length(); i++)
{
char letter = plainText.at(i);
int val = (int)letter; // getting ascii value of each letter.
int EnVal = (val - 32) + key;
if(EnVal > 95)
{
EnVal = (EnVal - 95) + 32;
}
char EnLetter = static_cast<char>(EnVal);
outfile << EnLetter;
change
for (int i = 0; i <= plainText.length(); i++)
to
for (int i = 0; i <= plainText.length()-1; i++)
because out of range. Even better use iterator.
also change this:
if (EorD == "E" || "e")
to
if (EorD == "E" || EorD == "e")
because former is always true.
as James Kanze pointed out, don't use std::string::at, you don't need it here, change it to std::string operator[] and my advice: additionally cover your code in a nice try{}catch(...){} block
you might consider something like this:
#include <vector>
#include <iterator>
#include <algorithm>
int key=100;
char op(char c){
char letter = c;
int val = (int)letter; // getting ascii value of each letter.
int EnVal = (val - 32) + key;
if(EnVal > 95)
{
EnVal = (EnVal - 95) + 32;
}
char EnLetter = static_cast<char>(EnVal);
return EnLetter;
}
int main(){
try{
std::string s="piotrek";
std::vector<char> vc_in(s.begin(),s.end());
std::vector<char> vc_out;
std::transform (vc_in.begin(), vc_in.end(),
std::back_inserter(vc_out), op); //this do the thing
std::copy(vc_out.begin(), vc_out.end(),
std::ostream_iterator<char> (std::cout,"_")); // to print
}catch(std::exception& e){
cout<<"exception: "<<e.what();
}
return OK;
}
You are looping one index too far in the plainText string. Since it has length() entries and the first one is 0, the last index is length()-1. Try this:
for (int i = 0; i < plainText.length(); i++)
Otherwise plainText.at(i) will crash when i is too big.