I am aware that this question has been asked a few times, and I may have missed the question that answers my specific problem however I cannot seem to find one that gives me an answer that works for me.
When I am decrypting a Caesar Cipher it doesn't seem to wrap around correctly, my code seems to follow the specific mathmatics for the caesar cipher but it seems to return junk output when it's supposed to wrap around. My code is as follows, including a system I used to test the problem.
#include "main.h"
#include <QCoreApplication>
#include <QDebug>
String caesarCipher(QString in, int shift, bool decrypt)
/*
* Caesar shift is mathmatically represented as e = (q + s) mod 26
* Decryption is represented as d = (q - s) mod 26
* ROT13 is a caesar shift with 13 shift
*/
{
QString out;
if (!decrypt)
{
for (int i = 0; i < in.length(); ++i)
{
if (in[i] >= 'a' && in[i] <= 'z')
{
int q = (in[i].unicode() - 'a');
int e = (q + shift) % 26;
out += e + 'a';
}
else if (in[i] >= 'A' && in[i] <= 'Z')
{
int q = (in[i].unicode() - 'A');
int e = (q + shift) % 26;
out += e + 'A';
}
else
out += in[i];
}
return out;
}
else
{
for (int i = 0; i < in.length(); ++i)
{
if (in[i] >= 'a' && in[i] <= 'z')
{
int q = (in[i].unicode() - 'a');
int d = (q - shift) % 26;
int r = d + 'a';
out += r;
}
else if (in[i] >= 'A' && in[i] <= 'Z')
{
int q = (in[i].unicode() - 'A');
int d = (q - shift) % 26;
int r = d + 'A';
out += r;
}
else
out += in[i];
}
return out;
}
}
int main() // Testing
{
QString testString = "abcdefghijklmnopqrstuvwxyz";
QString upperTest = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const int shifting = 3;
qDebug() << "Test String: " << testString;
qDebug() << "Test String (Upper): " << upperTest;
{
QString e = caesarCipher(testString, shifting, false);
QString E = caesarCipher(upperTest, shifting, false);
QString d = caesarCipher(e, shifting, true);
QString D = caesarCipher(E, shifting, true);
qDebug() << "Shift amount: " << shifting;
qDebug() << "Encrypt (Lower): " << e;
qDebug() << "Encrypt (Upper): " << E;
qDebug() << "Decrypt (Lower): " << d;
qDebug() << "Decrypt (Upper): " << D;
}
return 0;
}
The expected result is
Test String: "abcdefghijklmnopqrstuvwxyz"
Test String (Upper): "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Shift amount: 3
Encrypt (Lower): "defghijklmnopqrstuvwxyzabc"
Encrypt (Upper): "DEFGHIJKLMNOPQRSTUVWXYZABC"
Decrypt (Lower): "abcdefghijklmnopqrstuvwxyz"
Decrypt (Upper): "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Press <RETURN> to close this window...
The result I get:
Test String: "abcdefghijklmnopqrstuvwxyz"
Test String (Upper): "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Shift amount: 3
Encrypt (Lower): "defghijklmnopqrstuvwxyzabc"
Encrypt (Upper): "DEFGHIJKLMNOPQRSTUVWXYZABC"
Decrypt (Lower): "abcdefghijklmnopqrstuvw^_`"
Decrypt (Upper): "ABCDEFGHIJKLMNOPQRSTUVW>?#"
Press <RETURN> to close this window...
I have tried to move code around, change where the shift is removed, where the modulo is done and where the 'a' character is added
For reference the code was initially before I altered it for readability:
for (int i = 0; i < in.length(); ++i)
{
if (in[i] >= 'a' && in[i] <= 'z')
out.resultString += (((in[i].unicode() - 'a') - shift) % m) + 'a';
else if (in[i] >= 'A' && in[i] <= 'Z')
out.resultString += (((in[i].unicode() - 'A') - shift) % m) + 'A';
else
out.resultString += in[i];
}
The % operator can return negative results when used with negative numbers. In your case, when decrypting an 'a', q will be 0, d will be (-3 % 26), which can be -3.
The solution is to ensure the number is positive before calculating the remainder:
int d = (q - shift + 26) % 26;
Or, if the shift amount is unknown, or can be more than 25, check if d is negative and add 26 to it after your initial calculation.
I came here for help(with a more specific part) accouple days ago, but the solution I got didn't quite work. Basically I'm writing a program that serves 3 purposes: decodes a Rot 13 cypher, decodes a Rot 6 cypher, and put user input through an equation "x=2n-1" where n is the user input.
Rot 13 works fine, but Rot 6 outputs gibberish, and the equation outputs a letter (putting "8" gives you o instead of 15)
I know that this could be done in less functions, and I probably don't need an list, but this is for an assignment, and I need them
I know that I am not great at this, but any help would be great
#include <iostream>
#include <string>
#include <list>
#include <array>
using namespace std;
string coffeeCode(string input) { //Coffee code= 2n-1 where n=a number in a string
double index{};
input[index] = 2*input[index]-1;
return input;
};
string rot6(string input) {
int lower[] = { 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',' ' };
int upper[] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' };
int inputSize = input.size(); // rot 6 rotates letters so that a{0}->g[6]
int index{}; // m[12]->s[18]
// n->t
while (index != inputSize) { // z->f
if (input[index] >= lower[0] && input[index] <= lower[19])
input[index] = input[index] + 6;
else if (input[index] >= lower[20] && input[index] <= lower[25])
input[index] = input[index] - 20;
else if (input[index] >= upper[0] && input[index] <= upper[19])
input[index] = input[index] + 6;
else if (input[index] <= upper[20] && input[index] <= upper[25])
input[index] = input[index] - 20;
index++;
}
return input;
}
string rot13(string input) { //Decodes into rot 13
int lower[] = { 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',' ' };
int upper[] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' };
int inputSize = input.size();
int index{};
while (index != inputSize) {
if (input[index] >= lower[0] && input[index] <= lower[12])
input[index] = input[index] + 13;
else if (input[index] >= lower[13] && input[index] <= lower[25])
input[index] = input[index] - 13;
else if (input[index] >= upper[0] && input[index] <= upper[12])
input[index] = input[index] + 13;
else if (input[index] <= upper[13] && input[index] <= upper[25])
input[index] = input[index] - 13;
index++;
}
return input;
}
int main() {
string plaintext;
string ans13;
string ans6;
string ansCoffee;
cout << "Whats the message Spy Guy: ";
getline(cin, plaintext);
ans13 = rot13(plaintext);
ans6 = rot6(plaintext);
ansCoffee = coffeeCode(plaintext);
cout << "One of these is your decoded message" << endl << "In Rot 13: " << ans13 << endl << "In Rot 6: " << ans6 << endl
<< "In Coffee Code: " << ansCoffee << endl;
return 0;
}
Your best chance at understanding what you are doing is reading about how c++ handles characters, and what ASCII is.
[http://www.asciitable.com/]
Just a quick summary:
The ASCII table assigns every character in the english alphabet a number(or a code), and that number is what C++ actually stores in memory.
So, when you do char c = 'a' that is equivalent to doing char c = 97.
The ASCII table is pretty organised too, so all capital letters are in alphabetical order starting from 65(which is A) to 90(which is Z). The same is true for non capital letters, which go from 97 to 122, and for digits, which go from 48 to 57.
This can be used to determine what kind of character a variable is:
if ('a' <= input[index] && input[index] <= 'z') {
// It's lower case
}
if('A' <= input[index] && input[index] <= 'Z') {
// It's upper case
}
Note that when you put a singe character in single quotes the compiler will replace it with it's ASCII code, so you don't actually need to memorize the table. Think about how you could construct an if to determine whether a character is a digit.
Here is how I would implement the rot6. It may not bet the best, but I think it's alright.
string rot6(string input) {
for (int index = 0; index < input.size(); ++ index) {
if ('a' <= input[index] && input[index] <= 'z') { // It's lower case
input[index] = 'a' + ((input[index] - 'a') + 6) % 26;
}
else if ('A' <= input[index] && input[index] <= 'Z') { // It's upper case
input[index] = 'A' + ((input[index] - 'A') + 6) % 26;
}
else if ('0' <= input[index] && input[index] <= '9') { // It's a digit
input[index] = '0' + ((input[index] - '0') + 6) % 10;
}
else { // It's an error
return "Error, bad input!";
}
}
return input;
}
When I input
0x123456789
I get incorrect outputs, I can't figure out why. At first I thought it was a max possible int value problem, but I changed my variables to unsigned long and the problem was still there.
#include <iostream>
using namespace std;
long htoi(char s[]);
int main()
{
cout << "Enter Hex \n";
char hexstring[20];
cin >> hexstring;
cout << htoi(hexstring) << "\n";
}
//Converts string to hex
long htoi(char s[])
{
int charsize = 0;
while (s[charsize] != '\0')
{
charsize++;
}
int base = 1;
unsigned long total = 0;
unsigned long multiplier = 1;
for (int i = charsize; i >= 0; i--)
{
if (s[i] == '0' || s[i] == 'x' || s[i] == 'X' || s[i] == '\0')
{
continue;
}
if ( (s[i] >= '0') && (s[i] <= '9') )
{
total = total + ((s[i] - '0') * multiplier);
multiplier = multiplier * 16UL;
continue;
}
if ((s[i] >= 'A') && (s[i] <= 'F'))
{
total = total + ((s[i] - '7') * multiplier); //'7' equals 55 in decimal, while 'A' equals 65
multiplier = multiplier * 16UL;
continue;
}
if ((s[i] >= 'a') && (s[i] <= 'f'))
{
total = total + ((s[i] - 'W') * multiplier); //W equals 87 in decimal, while 'a' equals 97
multiplier = multiplier * 16UL;
continue;
}
}
return total;
}
long probably is 32 bits on your computer as well. Try long long.
You need more than 32 bits to store that number. Your long type could well be as small as 32 bits.
Use a std::uint64_t instead. This is always a 64 bit unsigned type. If your compiler doesn't support that, use a long long. That must be at least 64 bits.
The idea follows the polynomial nature of a number. 123 is the same as
1*102 + 2*101 + 3*100
In other words, I had to multiply the first digit by ten two times. I had to multiply 2 by ten one time. And I multiplied the last digit by one. Again, reading from left to right:
Multiply zero by ten and add the 1 → 0*10+1 = 1.
Multiply that by ten and add the 2 → 1*10+2 = 12.
Multiply that by ten and add the 3 → 12*10+3 = 123.
We will do the same thing:
#include <cctype>
#include <ciso646>
#include <iostream>
using namespace std;
unsigned long long hextodec( const std::string& s )
{
unsigned long long result = 0;
for (char c : s)
{
result *= 16;
if (isdigit( c )) result |= c - '0';
else result |= toupper( c ) - 'A' + 10;
}
return result;
}
int main( int argc, char** argv )
{
cout << hextodec( argv[1] ) << "\n";
}
You may notice that the function is more than three lines. I did that for clarity. C++ idioms can make that loop a single line:
for (char c : s)
result = (result << 4) | (isdigit( c ) ? (c - '0') : (toupper( c ) - 'A' + 10));
You can also do validation if you like. What I have presented is not the only way to do the digit-to-value conversion. There exist other methods that are just as good (and some that are better).
I do hope this helps.
I found out what was happening, when I inputted "1234567890" it would skip over the '0' so I had to modify the code. The other problem was that long was indeed 32-bits, so I changed it to uint64_t as suggested by #Bathsheba. Here's the final working code.
#include <iostream>
using namespace std;
uint64_t htoi(char s[]);
int main()
{
char hexstring[20];
cin >> hexstring;
cout << htoi(hexstring) << "\n";
}
//Converts string to hex
uint64_t htoi(char s[])
{
int charsize = 0;
while (s[charsize] != '\0')
{
charsize++;
}
int base = 1;
uint64_t total = 0;
uint64_t multiplier = 1;
for (int i = charsize; i >= 0; i--)
{
if (s[i] == 'x' || s[i] == 'X' || s[i] == '\0')
{
continue;
}
if ( (s[i] >= '0') && (s[i] <= '9') )
{
total = total + ((uint64_t)(s[i] - '0') * multiplier);
multiplier = multiplier * 16;
continue;
}
if ((s[i] >= 'A') && (s[i] <= 'F'))
{
total = total + ((uint64_t)(s[i] - '7') * multiplier); //'7' equals 55 in decimal, while 'A' equals 65
multiplier = multiplier * 16;
continue;
}
if ((s[i] >= 'a') && (s[i] <= 'f'))
{
total = total + ((uint64_t)(s[i] - 'W') * multiplier); //W equals 87 in decimal, while 'a' equals 97
multiplier = multiplier * 16;
continue;
}
}
return total;
}
Can anyone please explain me how this wrapping of chars between a-to-z and A-to-Z happening in Caesar shift code?
k %= 26;
for(int i = 0; i < n; i++){
int c = s[i];
if(c >= 'a' && c <= 'z'){
c += k;
if( c > 'z'){
c = 96 + (c % 122); // wrapping from z to a?
}
}
else if(c >= 'A' && c <= 'Z'){
c += k;
if(c > 'Z'){
c = 64 + (c % 90);
}
}
cout << (char)c;
}
K is amount of shift and c is a char of string s.
Is there any better way to do the same?
Lets make a couple changes to the code and it is easier to see what is going on
for(int i = 0; i < n; i++){
int c = s[i];
if(c >= 'a' && c <= 'z'){
c += k;
if( c > 'z'){
c = 'a' + (c % 'z') - 1; // wrapping from z to a?
}
}
else if(c >= 'A' && c <= 'Z'){
c += k;
if(c > 'Z'){
c = 'A' + (c % 'Z') - 1;
}
}
cout << (char)c;
}
So in c = 'a' + (c % 'z') - 1; if c is larger than z then we mod c by z(122) to get how many characters from a we need to go. The same thing is going on with the upper case letters. I am subtracting one here as we are starting at a instead of the character before a like you original code does.
Question: I'm new to C++ and after writing the following code seems like there should be a way to shorten it. Maybe by somehow matching the string? How would this be done?
The function takes a string message received via Serial port and sets the value of a particular element of the pinValues[] array depending on the message. The value that will be set is determined by the last character H or L just before the \n.
String pattern: (a number)(H or L)\n
Eg: message == "4H\n" will set the 5th element pinValues[4] to HIGH. The number at the start of the string can be 1 to 2 digits.
void setPinValues(String message) {
if( message == "1H\n" ) {
pinValues[1] = HIGH;
}
if( message == "1L\n" ) {
pinValues[1] = LOW;
}
if( message == "2H\n" ) {
pinValues[2] = HIGH;
}
if( message == "2L\n" ) {
pinValues[2] = LOW;
}
if( message == "3H\n" ) {
pinValues[3] = HIGH;
}
if( message == "3L\n" ) {
pinValues[3] = LOW;
}
if( message == "4H\n" ) {
pinValues[4] = HIGH;
}
if( message == "4L\n" ) {
pinValues[4] = LOW;
}
if( message == "5H\n" ) {
pinValues[5] = HIGH;
}
if( message == "5L\n" ) {
pinValues[5] = LOW;
}
if( message == "6H\n" ) {
pinValues[6] = HIGH;
}
if( message == "6L\n" ) {
pinValues[6] = LOW;
}
}
This is probably not the official "C++"-approved way of doing it, but you could do:
unsigned int pinNo = 0;
unsigned char level = 0;
int result = sscanf(message.c_str(), "%u%c", &pinNo, &level);
if (result < 2)
// it failed
if (pinNo > 6)
// bad data
levelVal = (level == 'H') ? HIGH : LOW;
I'd do some sanity checking on the string while extracting the key and value from the first two chars. If you don't need to sanity check the message, it could be as short as
void setPinValues(String message) {
pinValues[ message[0] - '0' ] = (message[1] == 'H') ? HIGH:LOW;
}
Although you may want to make that a little longer, i.e. check the string length, and that the 2 chars your checking are in the right range. i.e
void setPinValues(string message) {
if (
message.size() >= 2
and
message[0] >= '1' and message[0] <= '6'
and (message[1]=='H' or message[1]=='L')
) {
pinValues[ message[0] - '0' ] = (message[1] == 'H') ? HIGH:LOW;
}
}
EDIT: you could also extend that to checking two leading digits, i.e.
int n, off=0;
if ( s[off] <= '9' and s[off] >= '0')
{
n = s[off++] - '0';
}
if ( s[off] <= '9' and s[off] >= '0')
{
n = 10*n + s[off++] - '0';
}
if (off > 0 and (s[1]=='H' or s[1]=='L')) {
pinValues[ message[0] - '0' ] = (message[1] == 'H') ? HIGH:LOW;
}
Assuming String is actually a std::string or has an identical interface, and also assuming an ASCII-compatible character set...
void setPinValues(String message) {
const size_t sz = message.size();
// input validation, ignore the message if it doesn't fit the pattern
// you can remove this "if" block if the message has already been validated
if ( (sz < 3) || (sz > 4)
// note how message[0] will be checked twice if sz == 3
// once as message[0] and once as message[sz -3]
// but if sz == 4 we check message[0] and message[1]
|| (message[0] < '0') || (message[0] > '9')
|| (message[sz - 3] < '0') || (message[sz - 3] > '9')
|| ((message[sz - 2] != 'H') && (message[sz - 2] != 'L'))
|| (message[sz - 1] != '\n'))
return;
// convert the first or two characters to a number
int pinNumber = message[0] - '0';
if (sz == 4)
pinNumber = (pinNumber * 10) + (message[1] - '0');
// additional check to verify the pin number is in the correct range
if ((pinNumber < 1) || (pinNumber > 6))
return;
// apply
pinValues[pinNumber] = (message[sz - 2] == 'H' ? HIGH : LOW);
}