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
The current code at the bottom works but I can't combine the if statements without shifting the ascii values to a position that I don't want them to be. The encryption is supposed to be only alphabet values. Capital and lowercase z's are supposed to loop around to an A. I have a teacher but she doesn't know so I would be grateful for any help. Thanks <3
This doesn't work...
if (sentence[i] == 'z' || 'Z')
{
sentence[i] = sentence[i] - 26;
}
And this doesn't work
if (sentence[i] == 'z' || sentence[i] == 'Z')
{
sentence[i] = sentence[i] - 26;
}
This works.
if (sentence[i] == 'z')
{
sentence[i] = sentence[i] - 26;
}
if (sentence[i] == 'Z')
{
sentence[i] = sentence[i] - 26;
}
Full code.
#include <iostream>
#include <string>
using namespace std;
class EncryptionClass
{
string sentence;
public:
//constructors
EncryptionClass(string sentence)
{setString(sentence);}
EncryptionClass()
{sentence = "";}
//get and set
string getString()
{return sentence;}
void setString(string sentence)
{this-> sentence = sentence;}
//encrypt
void encryptString()
{
for(int i = 0; i < sentence.length(); i++)
{
if (isalpha(sentence[i]))
{
if (sentence[i] == 'z')
{
sentence[i] = sentence[i] - 26;
}
if (sentence[i] == 'Z')
{
sentence[i] = sentence[i] - 26;
}
sentence[i] = sentence[i] + 1;
}
}
}
};
int main()
{
string sentence;
cout << "Enter a sentence to be encrypted. ";
getline(cin, sentence);
cout << endl;
EncryptionClass sentence1(sentence);
cout << "Unencrypted sentence." << endl;
cout << sentence1.getString() << endl << endl;
sentence1.encryptString();
cout << "Encrypted sentence." << endl;
cout << sentence1.getString() << endl;
cin.get();
return 0;
}
In your case both If statements should both be equally.
if (sentence[i] == 'z' || sentence[i] == 'Z')
{
sentence[i] = sentence[i] - 26;
}
And:
if (sentence[i] == 'z')
{
sentence[i] = sentence[i] - 26;
}
if (sentence[i] == 'Z')
{
sentence[i] = sentence[i] - 26;
}
This is not always the case.
Snippet 2: if you change the value if i or sentence[i], the 2nd if will behave different.
If you would decrement by value 32, then both snippets will behave different
char myChar = 'z'
if (myChar == 'z' || myChar == 'Z')
{
myChar = myChar - 32;
}
// myChar is now 'Z'
And:
char myChar = 'z'
if (myChar == 'z')
{
myChar = myChar - 32;
}
// myChar is now 'Z'
if (myChar == 'Z')
{
myChar = myChar - 32;
}
// myChar is now ':'
The problem is you should be deducting 25 from your value, not 26! That's because there are 26 letters in the alphabet, relatively numbered from 0 to 25 (inclusive). To arrive at the first letter (number 0) from the last letter (number 25) you need to deduct 25.
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
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
But every version except the first version should give the same results.
#include <iostream>
int main()
{
char sentance[] = "Zz";
for(int i = 0; i < 2; ++i)
{
if(sentance[i] == 'Z' || sentance[i] == 'z')
{
sentance[i] = sentance[i] - 25;
std::cout << "letter " << i << " = " << sentance[i] << '\n';
}
}
}
Run it here
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 months ago.
Improve this question
I found a code on the internet to encrypt user input with Caesar encryption. But in the code the loop head bother me, because we didn't have things like "message[i]" or "\0" in class. Is it possible to write this in a different way? But we had not used arrays as far as in this loop header. This is not homework or anything like that. I'm practicing for my computer science test next week and there will probably be something similar. The loop header always looked like this for example for(i = 0; i < 4; i++). How can I write this code without arrays?
How can I write the loop differently? Or do I have to change other code parts?
#include <iostream>
using namespace std;
int main()
{
char message[100], ch;
int i, key;
cout << "Enter a message to encrypt: ";
cin.getline(message, 100);
cout << "Enter key: ";
cin >> key;
for (i = 0; message[i] != '\0'; ++i)
{ //<-
ch = message[i]; //<-
if (ch >= 'a' && ch <= 'z')
{
ch = ch + key;
if (ch > 'z')
{
ch = ch - 'z' + 'a' - 1;
}
message[i] = ch; //<-
}
else if (ch >= 'A' && ch <= 'Z')
{
ch = ch + key;
if (ch > 'Z')
{
ch = ch - 'Z' + 'A' - 1;
}
message[i] = ch; //<-
}
}
cout << "Encrypted message: " << message;
return 0;
}
To have a for loop closer to what you are used to, we need to know how many letters were input. The smallest change that does that is to use strlen to count them.
for (i = 0; i < strlen(message); ++i)
However it's better to use std::string to hold text, because that knows it's size.
int main()
{
std::string message;
int key;
std::cout << "Enter a message to encrypt: ";
std::getline(std::cin, message);
std::cout << "Enter key: ";
std::cin >> key;
for (i = 0; i < message.size(); ++i)
{
char ch = message[i];
if (ch >= 'a' && ch <= 'z')
{
ch = ch + key;
if (ch > 'z')
{
ch = ch - 'z' + 'a' - 1;
}
message[i] = ch; //<-
}
else if (ch >= 'A' && ch <= 'Z')
{
ch = ch + key;
if (ch > 'Z')
{
ch = ch - 'Z' + 'A' - 1;
}
message[i] = ch; //<-
}
}
std::cout << "Encrypted message: " << message;
return 0;
}
And even better than that, you can loop over the chars in a string directly
int main()
{
std::string message;
int key;
std::cout << "Enter a message to encrypt: ";
std::getline(std::cin, message);
std::cout << "Enter key: ";
std::cin >> key;
for (char & ch : message) // <- N.b. char &, we are modifying the `char` objects owned by message
{
if (ch >= 'a' && ch <= 'z')
{
ch = ch + key;
if (ch > 'z')
{
ch = ch - 'z' + 'a' - 1;
}
}
else if (ch >= 'A' && ch <= 'Z')
{
ch = ch + key;
if (ch > 'Z')
{
ch = ch - 'Z' + 'A' - 1;
}
}
}
std::cout << "Encrypted message: " << message;
return 0;
}
Look at this snippet. Sorry if I have made a mistake with syntax, but this is enough to give you a general idea.
#include <iostream>
#include <cctype>
using namespace std;
int main() {
char message[100];
int key;
cout << "Enter a message to encrypt: ";
cin.getline(message, 100);
cout << "Enter key: ";
cin >> key;
encrypt(message, key);
cout << "Encrypted message: " << message;
return 0;
}
void encrypt(char& message, const int key) {
for (char& ch : message) {
if (islower (ch))
ch = encrypt (ch + key, 'a', 'z');
else if (isupper (message[i]))
ch = encrypt (ch + key, 'A', 'Z');
}
}
char encrypt(const char ch, const char lo, const char hi) {
return ch % hi ? lo + (chi % hi) : ch;
}
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 months ago.
Improve this question
I am making a program to calculate the value of words for a friend who is interested in numerology.
In my program, I ask the user how many words they want to calculate, so I can dynamically allocate the size of the array to store the words.
It works perfectly the first time they run the program, but when I ask if they want to test more words, and if they hit yes, it reruns the while loop and it asks them for how many words to evaluate, but this time, no matter what number they type, it always sets the size of the array to 1, due to the number variable being set to 1 and not changing after user input. My friend has to rerun the program to make it work again.
I really want to fix this problem to make it easier for my friend.
(Yes, I do plan on fixing my code, and if you have seen this code in another question, that was me, and yes, I am going to improve my code based on the suggestions I got, but I want it to at least work before I improve on it.)
Here is my code:
#include <iostream>
#include <string>
#include <sstream>
void clear()
{
system("clear");
}
int main(int argc, char* argv[])
{
int number{1};
int total{0};
int value{0};
std::string number_str;
std::string response;
std::stringstream ss;
bool isDigit;
while (true)
{
clear();
number = 1;
total = 0;
value = 0;
number_str = "";
response = "";
isDigit = true;
clear();
std::cout << "How many words to evalute? (Default: 1):\n> ";
//std::cin >> number;
std::getline(std::cin, number_str);
//std::cin.ignore();
clear();
for (int i = 0; i < number_str.size(); ++i)
{
if (!(std::isdigit(number_str[i])))
isDigit = false;
break;
}
if (isDigit)
{
if (number_str.empty()) {
number = 1;
} else {
ss << number_str;
ss >> number;
}
}
if (std::isdigit(number)) {
if (number <= 0) {
number = 1;
}
}
std::string* pPhrase = new std::string[number];
int* pValue = new int[number]{}; // Initialized each element to 0
for (int i = 0; i < number; ++i) // could replace "number" with "sizeof(pPhrase)/sizeof(pPhrase[0])"
{
(i == 0) ? std::cout << "Enter Word #" << i+1 << " (or type your full phrase):\n> " :
std::cout << "Enter Word #" << i+1 << ":\n> ";
std::cin >> pPhrase[i];
for (char j : pPhrase[i])
{
value = 0;
if (std::isalnum(j) && j != '0')
{
if (std::isalpha(j))
j = std::tolower(j);
} else {
continue;
}
if (j == 'a' || j == 'i' || j == 'j'
|| j == 'q' || j == 'y' || j == '1')
value += 1;
if (j == 'b' || j == 'k' || j == 'r' || j == '2')
value += 2;
if (j == 'c' || j == 'g' || j == 'l'
|| j == 's' || j == '3')
value += 3;
if (j == 'd' || j == 'm' || j == 't' || j == '4')
value += 4;
if (j == 'e' || j == 'h' || j == 'n'
|| j == 'x' || j == '5')
value += 5;
if (j == 'u' || j == 'v' || j == 'w' || j == '6')
value += 6;
if (j == 'o' || j == 'z' || j == '7')
value += 7;
if (j == 'f' || j == 'p' || j == '8')
value += 8;
pValue[i] += value;
value = 0;
std::cout << '\n';
clear();
}
}
std::cin.ignore();
std::cin.clear();
std::cout << "\n\n";
for (int i = 0; i < number; ++i)
{
std::cout << "Value of \"" << pPhrase[i] << "\": " << pValue[i] << '\n';
total += pValue[i];
}
std::cout << "Total value: " << total << "\n\nPress \'Enter\' or \'Return\' to Continue... ";
//std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
//std::cin.clear();
std::cout << "\n\n\nWould you like to evaluate another phrase? (Y/n):\n> ";
std::getline(std::cin, response);
delete[] pPhrase;
delete[] pValue;
if (response[0] == 'y' || response[0] == 'Y'
|| response.empty() || response[0] == ' ')
continue;
break;
}
std::cout << "Exiting...";
try {
//system("killall Terminal");
} catch (std::exception& ex) {}
std::cout << "\n\n\n";
return 0;
}
for (int i = 0; i < number; ++i) // could replace "number" with "sizeof(pPhrase)/sizeof(pPhrase[0])"
Actually, you can't use the sizeof(array)/sizeof(array[0]) trick on a pointer to an array. It only works when you use it directly on the actual array itself. There are numerous questions on StackOverflow that explain this, including (just to name a few):
How to get the size of an array using a pointer to the first element and properties of "\0"?
Pointer to an array get size C++
getting size of array from pointer c++
In any case, one problem I do see in your code is that on each iteration of the outer while loop, you are not resetting the std::stringstream that you use to convert the user's input to the number variable. Each iteration is just pushing more and more data into the stream without removing the old data first.
Also, using std::isdigit(number) is useless. You already validated the user entered only digits, and then converted those digits to the number variable. What you didn't do is validate that the conversion to int was actually successful before using number. You must validate that the extraction of the number from the stringstream is successful, ie in case the user enters a large value that can't fit into an int.
Try this instead:
while (true)
{
clear();
number = 1;
total = 0;
value = 0;
number_str = "";
response = "";
isDigit = true;
// ADD THIS!
ss.str("");
ss.clear();
//
...
if (isDigit)
{
ss << number_str;
if (!(ss >> number) { // <-- ADD THIS!
number = 1;
}
}
...
}
That being said, you could just get rid of the stringstream altogether, you don't actually need it. You can extract the number value directly from std::cin itself (which you are already aware of, because you commented out that code), eg:
std::cout << "How many words to evalute? (Default: 1):\n> ";
if (!(std::cin >> number)) {
number = 1;
std::cin.clear();
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// no need for the `isdigit() check at all...
I'm learning strings and am trying to write a cipher program where a user inputs a string, inputs the key(how many spaces to shift a number either left or right) and outputs the encrypted string. I believe I have it almost figured out, But I need help fixing the issue where spaces and special characters get changed as well as the letters. I believe it has something to do with the toupper function, but I can't be sure. Any help would be appreciated!
#include<iostream>
#include<string>
using namespace std;
int main() {
string message;
int key;
cout << "Your message? ";
getline(cin, message);
cout << "Encoding key? ";
cin >> key;
for (int i = 0; i < message.length(); i++) {
if (islower(message[i])) {
message[i]=toupper(message[i]);
}
if (message[i] >= 'A' && message[i] <= 'Z') {
message[i] += key;
}
if (message[i] > 'Z') {
int overLimit = message[i] - 'Z';
message[i] = 'A' + overLimit - 1;
}
else if (message[i]<'A') {
int underLimit = 'A' - message[i];
message[i] = 'Z' - underLimit + 1;
}
}
cout << message << endl;
return 0;
}
Your message[i] > 'Z' and message[i] < 'A' should be inside the first if, where you already have detected a letter. If it's outside, it's also changing any non-letter characters too! (for example, space ' ' passes message[i] < 'A' and gets changed)
Here's the fixed code, I just placed the ifs in the correct place
#include<iostream>
#include<string>
using namespace std; // This is bad, you should get used to writing std::cout
int main() {
string message;
int key;
cout << "Your message? ";
getline(cin, message);
cout << "Encoding key? ";
cin >> key;
for (int i = 0; i < message.length(); i++) {
if (islower(message[i])) {
message[i]=toupper(message[i]);
}
if (message[i] >= 'A' && message[i] <= 'Z') {
message[i] += key;
if (message[i] > 'Z') {
int overLimit = message[i] - 'Z';
message[i] = 'A' + overLimit - 1;
}
else if (message[i]<'A') {
int underLimit = 'A' - message[i];
message[i] = 'Z' - underLimit + 1;
}
}
}
cout << message << endl;
return 0;
}
I'm having trouble with a basic c++ program assignment, and would greatly appreciate any help. The assignment is as follows:
Write a program that accepts input from the keyboard (with the input
terminated by pressing the Enter key) and counts the number of letters (A-Z and a-z), numerical digits (0-9), and other characters. Input the string using cin and use the following looping structure to examine each character in the string with an "if" statement and multiple "else if" statements.
My program thus far is:
#include <iostream>
using namespace std;
int main()
{
char s[50];
int i;
int numLet, numChars, otherChars = 0;
cout << "Enter a continuous string of characters" << endl;
cout << "(example: aBc1234!##$%)" << endl;
cout << "Enter your string: ";
cin >> s;
i = 0;
while (s[i] != 0) // while the character does not have ASCII code zero
{
if ((s[i] >= 'a' && s[i] <= 'z') || s[i] >= 'A' && (s[i] <= 'Z'))
{numLet++;
}
else if (s[i] >= 48 && s[i] <= 57)
{numChars++;
}
else if ((s[i] >= 33 && s[i] <= 4) || (s[i] >= 58 && s[i] <=64) || (s[i] >= 9 && s[i] <= 96) || (s[i] >= 123 && s[i] <= 255))
{otherChars++;
}
i++;
}
cout << numLet << " letters" << endl;
cout << numChars << " numerical characters" << endl;
cout << otherChars << " other characters" << endl;
return 0;
}
The letter count gives a value a little too low, and the number count gives a large negative number. Other chars seems to function fine.
As mentioned in the other answer, you need to initialize your variables, but you have also an error in this code:
if ((s[i] >= 'a' && s[i] <= 'z') || s[i] >= 'A' && (s[i] <= 'Z'))
the brackets are wrong. And as a result, you are not counting lowercase letters (i think) anyways it shoul be this (indented for visibility):
if (
(s[i] >= 'a' && s[i] <= 'z') ||
(s[i] >= 'A' && s[i] <= 'Z')
)
you can also use this. Since you're using c++ and not c, right ;) (people here get mad about the difference apparently)
You need to set each integer to 0. As it is, your code only sets otherChars = 0. Make that line numLet = 0, numChars = 0, otherChars = 0;.
I have made small encryption program that uses to keys rot7 and rot13. Everything works fine except two 6 letters uvwxyz.
If I type ABCDEFGHIJKLMNOPQRSTUVWXYZ it encrypts and decrypts no problem. However, if I enter the same in lower case letters then uvwxyz do not work.
Having said this, I have allowed all the writable characters within the ascii table as the valid range as follows:
// allow all writable characters from 32 to 255
if ((str[i] >= 32 ) && (str[i] <=255))
{
str[i] -= key;
}
Here is the process of encryption:
cout << endl;
cout << "Encrypting process started " << endl << endl;
cout << "--------------------------- " << endl;
//get the string length
int i = 0;
int length = str.length();
int key = rot13 ;
int k = 5;
int multiple = 0;
int count = 0;
cout << "the text to encrypt is: " << str << endl;
cout << "text length is: " << length << endl;
cout << "using rot13"<<endl;
cout <<"---------------------------" << endl;
cout << "using rot13" << endl;
//traverse the string
for(i = 0; i < length; i++)
{
count ++;
cout << left;
//if it is a multiple of 5 not the first character change the key
if((multiple = (( i % 5 ) == 0)) && (count != 1) && (key == rot13)){
key = rot7;
}
//if it is a multiple of 5 not the first character change the key
else if((multiple = (( i % 5 ) == 0)) && (count != 1) && (key == rot7) ) {
key = rot13;
}
// Capital letters are 65 to 90 (a - z)
if ((str[i] >= 32) && (str[i] <= 255))
{
str[i] += key;
}
}
return str;
How is it possible that the capital letters work and not the lower case if I have allowed this range? Can it be because of something else? I have added these captures with what happens step by step... hopefully this helps
In your code :
if ((str[i] >= 32) && (str[i] <= 255))
{
if (str[i] + key > 255)
str[i] = ((str[i] + key) % 255 )+ 32;
else
str[i] += key;
}
if key has a value of 13 and str[i] is 'u' or greater, str[i] has a value higher than 255.
You should use modulo % operator in this case, this is rotation, not only a shift