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' -> ...)
Related
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.
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;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
As I am new to coding c++ and am taking a object oriented class, I need some help. For this code I want to encrypt it by shifting all of the text that is enter by 1 ascii digit i.e. a -> b, b-> etc. I am suppose to use all ascii values 32 - 126 but I cant figure out why when i try to encrypt anything I only get a "^" as a output.
#include <iostream>
#include <string>
using namespace std;
void encrypt (string &encrypt)
{
string encryption;
for (int i = 0; i < encrypt.length(); i++)
{
encrypt[i]++;
if (i > 126){
encrypt = i - 94;
}
else if (i < 32){
encrypt = i + 94;
}
}
}
void decrypt (string decrypt)
{
string decryption;
for ( int i = 0; i < decryption.length(); i ++)
{
decryption[i]--;
if (i > 126){
decrypt = i + 94;
}
else if (i < 32){
decrypt = i - 94;
}
}
}
int main ()
{
string option;
string encryption1;
string decryption1;
cout << "Do you want to encrypt or decrypt? \n";
cin >> option;
if (option == "encrypt")
{
cout << "What do you want to encrypt \n";
cin.ignore();
cin.clear();
getline (cin, encryption1);
encrypt ( encryption1);
cout << encryption1 << " " << endl;
}
if (option == "decrypt")
{
cout << "What do you want to decrypt \n";
cin.ignore();
cin.clear();
getline (cin, decryption1);
encrypt ( decryption1);
cout << decryption1 << " " << endl;
}
return 0;**
I did something similar to this in my level one programming class last year. We created a Vigenere Cipher that is based off of the architecture of the Cesar cipher.
Something that is useful is to first create a 0 base, i.e. if you are working with values a through b, subtract a from each of the characters that you are encoding first, do the math, double check that the value falls within the range of values (32 through 126 == 0 through 94) and then return the char + a. This would mean rewriting your logic and function to take a char instead of the entire string at once.
As for why you are getting '^' as your only output, the ACSII code for '^' is 94 and your code:
for ( int i = 0; i < decryption.length(); i ++)
{
decryption[i]--;
if (i > 126){
decrypt = i + 94;
}
else if (i < 32){
decrypt = i - 94;
}
}
}
is setting the entire string to char 94. You set i = 0 then say that if i is less than 32 then the string decrypt is equal to the char 0 + 94 which is equal to 94 which is equal to '^'
I'm doing a problem where it asks to input an account number, which consists only of four digits. This has to be accomplished with basic beginner C++.
I need to figure out a way to restrict the input of the integer to four digits. A user should be able to put in 0043 or 9023 or 0001 and it should be an acceptable value....
I think I know how to accomplish it with a string.... getline(cin,input) and then check if input.length()==4?
But I've no idea how I would even do this with an integer input.
Note that if 0043 is intended to be distinct from 43, then the input is not in fact a number, but a digit string, just like a telephone "number".
Read the line as a string input.
Check that the length of input is 4.
Check that each character in the string is <= '9' and >= '0'.
Something like:
std::string read4DigitStringFromConsole()
{
bool ok = false;
std::string result;
while (!ok)
{
std::cin >> result;
if (result.length() == 4)
{
bool allDigits = true;
for(unsigned index = 0; index < 4; ++index)
{
allDigits = allDigits && (
(result[index] >= '0') &&
(result[index] <='9')
);
}
ok = allDigits;
}
}
return result;
}
Something like this should work. Once the user enters something with exactly four characters you can validate it. The rest of the logic is up to you.
#include <iostream>
#include <string>
int main() {
std::cout << "Enter a PIN Number: ";
std::string pinStr;
while(std::getline(std::cin,pinStr) && pinStr.size() != 4) {
std::cout << "Please enter a valid value\n";
}
}
Should you want to store it in an integer form, holding the integers in an std::vector might be beneficial. You can do this easily (loop unrolling was for clarity):
#include <iostream>
#include <string>
#include <vector>
int main() {
std::cout << "Enter a PIN Number: ";
std::string pinStr;
while(std::getline(std::cin,pinStr) && pinStr.size() != 4 ) {
std::cout << "Please enter a valid value\n";
}
std::vector<int> pin;
pin[0] = pinStr[0] - '0';
pin[1] = pinStr[1] - '0';
pin[2] = pinStr[2] - '0';
pin[3] = pinStr[3] - '0';
//pin now holds the integer value.
for(auto& i : pin)
std::cout << i << ' ';
}
You can see it running here
I like your idea to use a string as the input. This makes sense because an account "number" is simply an identifier. You don't use it in calculations. By if (sizeof(input)==4) I think you are trying to check the length of the string. The correct way to do this is if (input.length() == 4). This will check that the user inputs 4 characters. Now you need to make sure that each of the characters is also a digit. You can do this easily by taking advantage of the fact that the ASCII codes for digit characters are ordered as you expect. So if (input[i] >= '0' && input[i] <= '9') will do the trick with an appropriate for loop for the index i. Also, you probably need some kind of loop which continues to ask for input until the user enters something which is deemed to be correct.
Edit:
As an alternative to checking that each character is a digit, you can attempt to convert the string to an int with int value = atoi(input.c_str());. Then you can easily check if the int is a four-or-less-digit number.
// generic solution
int numDigits(int number)
{
int digits = 0;
if (number < 0) digits = 1; // remove this line if '-' counts as a digit
while (number) {
number /= 10;
digits++;
}
return digits;
}
similar to this post.
Then you can call this function to check if the input is 4 digits.
You probably want your code to be responsive to the user input, so I would suggest getting each character at a time instead of reading a string:
std::string fourDigits;
char currentDigit;
std::cout << "Enter 4 digits\n";
for(int i = 0; i < 4; ++i)
{
currentDigit = getch();
if(isdigit(currentDigit))
{
fourDigits += currentDigit;
std::cout << currentDigit; // getch won't display the input, if it was a PIN you could simply std::cout << "*";
}
else
{
// Here we reset the whole thing and let the user know he entered an invalid value
i = 0;
fourDigits = "";
std::cout << "Please enter only numeric values, enter 4 digits\n";
}
}
std::cout << "\nThe four digits: " << fourDigits.c_str();
This way you can handle gracefully invalid character instantly. When using strings, the input will only be validated once the user hits Enter.
So I was going over how I can use an integer type to get the input, and looked at char... since it's technically the smallest integer type, it can be used to get the code... I was able to come up with this, but it's definitely not refined yet (and I'm not sure if it can be):
int main() {
int count=0;
while(!(count==4)){
char digit;
cin.get(digit);
count++;
}
return 0;
}
So, the loop keeps going until 4 characters are collected. Well, in theory it should. But it doesn't work. It'll stop at 2 digits, 5 digits, etc.... I think it could be the nature of cin.get() grabbing white space, not sure.
I am trying to create a Caesar cipher using C++. I have the program read in a text file but I need it to encrypt the text and output to the screen.
This is my encryption code but I can't seem to get it to work. I have only just started using C++ and not really sure where to go from here.
cout << "enter a value between 1-26 to encrypt the text: ";
cin >> shift;
while ((shift <1) || (shift >26)) {
cout << "Enter a value between 1 and 26!: ";
cin >> shift;
}
int size = strlen(text);
int i=0;
for(i=0; i<size; i++) {
cipher[i] = (text[i]);
if (islower(text[i])) {
if (text[i] > 122) {
cipher[i] = ( (int)(text[i] - 26) + shift);
}
} else if (isupper(text[i])) {
if (text[i] > 90) {
cipher[i] = ( (int)(text[i] - 26) + shift);
}
}
}
cipher[size] = '\0';
cout << cipher << endl;
First of all, your algorithm is wrong.
If we assume ASCII input then you need to encrypt the values that are between 32 (i.e. space) and 126 (i.e. tilde ~), inclusive. You do this by adding the key (a single number) to the value. If the result is greater than 126 (your highest available character) you need to wrap around and start counting from 32. This means 126 + 1 = 32, 126 + 2 = 33, etc. Look up "modulo".
I recommend you look-up the word "debugging". Generally, when you have an algorithm you write code that matches the algorithm as best you can. If the results are not the expected ones then you step line by line using the debugger until you find the line were your expected results and your code's result no longer match.
reformatted, made compilable ad fixed algorithm (to what i think was tried to achieve)
#include <iostream>
using namespace std;
char text[] = {"This is my encryption code but I can't seem to get it to work. "
"I have only just started using C++ and not really sure where "
"to go from here."};
char cipher[sizeof(text)];
void main()
{
int shift;
do {
cout << "enter a value between 1-26 to encrypt the text: ";
cin >> shift;
} while ((shift <1) || (shift >26));
int size = strlen(text);
int i=0;
for(i=0; i<size; i++)
{
cipher[i] = text[i];
if (islower(cipher[i])) {
cipher[i] = (cipher[i]-'a'+shift)%26+'a';
}
else if (isupper(cipher[i])) {
cipher[i] = (cipher[i]-'A'+shift)%26+'A';
}
}
cipher[size] = '\0';
cout << cipher << endl;
}
A few things:
You are checking if the character islower and then checking if the
ascii value is > 122. This will never be true. In the default
locale (standard ascii), islower() will only be true if the ascii
value is in the range [97, 122] (a-z). The same goes for
isupper(). It only returns true for ascii values between 65 and
90, inclusive.
You are already working with ascii values anyway, so islower() and isupper() may be redundant. Those are equivalent to doing bounds checking on the ranges, i.e. text[i] >= 97 && text[i] <= 122. They are useful shortcuts, but don't base your code around them if you can simplify.
Your code never adds the caesar shift if the value is <= 90/122, so you will never shift anything.