Pig Latin - strings - c++

So I am supposed to convert English words to Pig Latin using stringConvertToPigLatin(string word) function. All the answers I could find on the internet were using char[], and I am not allowed to do so.
The program is supposed to begin with adding -way if the first letter is a vowel, and adding -ay if it's a consonant. The problem is that it is always adding "-way", even if my "word" has no vowel at all. What am I doing wrong? This is my function:
string ConvertToPigLatin(string word)
{
char first = word.at(0);
cout << first << endl;
if (first == 'a' || 'A' || 'e' || 'E' || 'i' || 'I' || 'o' || 'O' || 'u' || 'U')
{
word.append("-way");
}
else
{
word.append("-ay");
}
return word;
}

As noted in the comments your if statement is wrong. Each comparison needs to be done individually. From the comment.
if (first == 'a' || first == 'A' || first == 'e' || ...)
However, rather than using a long if statement you should consider stuffing all of the vowels into a string and using find. Something like the code below will be easier to read and follow.
#include <iostream>
#include <string>
std::string ConvertToPigLatin(std::string word)
{
static const std::string vowels("aAeEiIoOuU");
char first = word.at(0);
std::cout << first << std::endl;
if (vowels.find(first) != std::string::npos)
{
word.append("-way");
}
else
{
word.append("-ay");
}
return word;
}
int main()
{
std::cout << ConvertToPigLatin("pig") << '\n';
std::cout << ConvertToPigLatin("alone") << '\n';
}
This outputs
p
pig-ay
a
alone-way

I'll explain why your code isn't working:
if (first == 'a' || 'A' || 'e' || 'E' || 'i' || 'I' || 'o' || 'O' || 'u' || 'U')
Let's walk through that iff statement using the word "Pig"
First the program checks first == 'a'... first == 'P' so that is false.
Then the program checks to see if false || 'A' is true. Since 'A' is true, false || 'A' is also true.
Short circuit evaluation kicks in, and the code doesn't bother checking the rest of the statement, the if condition is true so -way is appended.
To do what you want, you need to compare first to each letter. I.E.,
if (first == 'a' || first == 'A' || ...
Don't worry too much, this is a pretty standard mistake.

Related

Trying to create a basic "encrypter"

It's a simple concept and not very secure, but just a practice session as i am a very early beginner (2 to 3 weeks)
I basically wanted to interject a random amount of random characters, like numbers and expressions, in to the inputted message after each letter. So for example, "HELLO" would become "H45[E[./43L/54L43[]O".
However i just seem to be getting back the exact input, without the jargon being added in between. Any ideas?
Here is my code:
#include <iostream>
#include <ctime>
#include <string>
std::string encryptFunc(std::string address){
int i = 0;
int store = address.length();
std::string Output;
while(i < store){
if(address[i] == ' ' || address[i] == 'a' || address[i] == 'b' || address[i] == 'c' || address[i] == 'd' || address[i] == 'e' || address[i] == 'f' || address[i] == 'g' || address[i] == 'h' || address[i] == 'i' || address[i] == 'j' || address[i] == 'k' || address[i] == 'l' || address[i] == 'm' || address[i] == 'n' || address[i] == 'o' || address[i] == 'p' || address[i] == 'q' || address[i] == 'r' || address[i] == 's' || address[i] == 't' || address[i] == 'u' || address[i] == 'v' || address[i] == 'w' || address[i] == 'x' || address[i] == 'y' || address[i] == 'z' || address[i] == 'A' || address[i] == 'B' || address[i] == 'C' || address[i] == 'D' || address[i] == 'E' || address[i] == 'F' || address[i] == 'G' || address[i] == 'H' || address[i] == 'I' || address[i] == 'J' || address[i] == 'K' || address[i] == 'L' || address[i] == 'M' || address[i] == 'N' || address[i] == 'O' || address[i] == 'P' || address[i] == 'Q' || address[i] == 'R' || address[i] == 'S' || address[i] == 'T' || address[i] == 'U' || address[i] == 'V' || address[i] == 'W' || address[i] == 'X' || address[i] == 'Y' || address[i] == 'Z'){
srand(time(NULL));
int randJargonSelect = rand()%26; //which character of individual jargon is currently selected to be placed
char jargonSelection[] = {'1','2','3','?', '<', '~', '#', '/', '#', '+', '*', '&', '^', '%', '$', '!', '-', '0', '9', '8', '7', '6', '5', '4', '`', '|' };
char randPlacementJargon = jargonSelection[randJargonSelect]; //the variable holder for the character of jargon to place
int randJargonAmount = rand()%500; //the amount of jargon chars to place
Output = address[i], randPlacementJargon * randJargonAmount;
}
std::cout << Output;
i++;
};
std::string nada = " ";
return nada;
}
int main(){
std::string userin;
std::cout << "Please enter the message you wish to encrypt" << std::endl;
std::cout << "Enter here: "; std::getline(std::cin, userin);
std::cout << " " << std::endl;
std::cout << "Here is your Encoded Message: " << encryptFunc(userin) << std::endl;
std::cout << " " << std::endl;
system("pause");
return 0;
}
Thanks again. I know there are probably 100 better ways of doing this, but i just wish to understand it for the sake of learning.
First, let's talk a bit about style. The way your code looks is extremely important to readability, not just for yourself but for others. There are tools that can style code for you, like clang-format. Here's your code with the only change being that I ran your code through clang-format set to Google's style. I chose this style because it seems good for presentation on this site.
Whether you use a tool or not, being aware of and using good and consistent style is important.
#include <ctime>
#include <iostream>
#include <string>
std::string encryptFunc(std::string address) {
int i = 0;
int store = address.length();
std::string Output;
while (i < store) {
if (address[i] == ' ' || address[i] == 'a' || address[i] == 'b' ||
address[i] == 'c' || address[i] == 'd' || address[i] == 'e' ||
address[i] == 'f' || address[i] == 'g' || address[i] == 'h' ||
address[i] == 'i' || address[i] == 'j' || address[i] == 'k' ||
address[i] == 'l' || address[i] == 'm' || address[i] == 'n' ||
address[i] == 'o' || address[i] == 'p' || address[i] == 'q' ||
address[i] == 'r' || address[i] == 's' || address[i] == 't' ||
address[i] == 'u' || address[i] == 'v' || address[i] == 'w' ||
address[i] == 'x' || address[i] == 'y' || address[i] == 'z' ||
address[i] == 'A' || address[i] == 'B' || address[i] == 'C' ||
address[i] == 'D' || address[i] == 'E' || address[i] == 'F' ||
address[i] == 'G' || address[i] == 'H' || address[i] == 'I' ||
address[i] == 'J' || address[i] == 'K' || address[i] == 'L' ||
address[i] == 'M' || address[i] == 'N' || address[i] == 'O' ||
address[i] == 'P' || address[i] == 'Q' || address[i] == 'R' ||
address[i] == 'S' || address[i] == 'T' || address[i] == 'U' ||
address[i] == 'V' || address[i] == 'W' || address[i] == 'X' ||
address[i] == 'Y' || address[i] == 'Z') {
srand(time(NULL));
int randJargonSelect =
rand() % 26; // which character of individual jargon is currently
// selected to be placed
char jargonSelection[] = {'1', '2', '3', '?', '<', '~', '#', '/', '#',
'+', '*', '&', '^', '%', '$', '!', '-', '0',
'9', '8', '7', '6', '5', '4', '`', '|'};
char randPlacementJargon =
jargonSelection[randJargonSelect]; // the variable holder for the
// character of jargon to place
int randJargonAmount =
rand() % 500; // the amount of jargon chars to place
Output = address[i], randPlacementJargon * randJargonAmount;
}
std::cout << Output;
i++;
};
std::string nada = " ";
return nada;
}
int main() {
std::string userin;
std::cout << "Please enter the message you wish to encrypt" << std::endl;
std::cout << "Enter here: ";
std::getline(std::cin, userin);
std::cout << " " << std::endl;
std::cout << "Here is your Encoded Message: " << encryptFunc(userin)
<< std::endl;
std::cout << " " << std::endl;
return 0;
Now, let's look at your code. I'll start with the main function since it's smaller. There are two small things here, and one can be considered somewhat subjective. The line std::cout << " " << std::endl; is wholly unnecessary. If you just want a blank line, print '\n' (newline character). And you wouldn't need an entire statement for that, either, just stick it at the beginning of your next actual cout. std::cout << "\nHere is your Encoded Message: " << .... The second thing is to prefer '\n' over std::endl. std::endl does two things, print the '\n' and flush the stream. You don't have to constantly flush the stream.
This is note in your main, but it transitions us. You attempt to print the result of encryptFunc() but it returns a single space, the one you declare and return at the end of the function. Your function also prints, and this is bad.
Functions should be singular in purpose. You named it encryptFunc(), not encryptAndPrintFunc(). You also don't need to name your function with any form of "func." We all know it's a function. And you're not really encrypting, I'd say it's more like padding, so I'm going to change the name.
Let's also look at the parameter name, address. That makes no sense. You're not passing an address, your passing a message to be encoded. We'll change that name, I'm choosing message.
std::string pad(std::string message) { ... }
So we've got this, and it already is more understandable what your code intends to do.
I'm going to rename Output to output. Names starting with an upper case letter is generally reserved for classes/structs. You want to pad after a space or a letter. You have a massive Boolean expression for your if. We're going to change this loop to a for loop, and simplify things with the library <cctype>. This is a great library for ASCII work. If you don't know what ASCII is, look up an ASCII table. For beginner programming stuff, ASCII is great. The loop change means we don't need i (not the way you use it anyway) or store.
std::string pad(std::string message) {
std::string output;
for (auto c : message) {
if (std::isalpha(c) || std::isspace(c)) {
// Still working
The for loop I'm using is a range-based for loop. The value of i will be each char of message. Next we're going to change out the older C-style random number stuff for C++ versions. This involves <random>.
std::string pad(std::string message) {
std::string output;
const std::string jargon("123456790?<>~#/#+*&^%$!-`|");
static std::mt19937 prng(std::random_device{}());
static std::uniform_int_distribution<std::size_t> jargonSelector(
0, jargon.length() - 1);
static std::uniform_int_distribution<int> numJargon(1, 5);
for (auto c : message) {
if (std::isalpha(c) || std::isspace(c)) {
// Still working
The keyword static is there for situations when you might call this function many times. If that's the case, you don't want to constantly re-initialize your Pseudo-Random-Number-Generator or distributions. static is how we accomplish that. const ensures that jargon is never modified.
Now, we're getting to the actual issue of your code. This line: output = message[i], randPlacementJargon * randJargonAmount; doesn't do what you expect. The comma operator performs the first expression, discards the result, and returns the result of the second expression. So, you made output hold a single character, then did a random multiplication that wasn't saved anywhere. That's why the original string printed again, your function printed it one character at a time.
You could have known that statement was not working as intended if you were compiling with warnings enabled. -Wall -Wextra should be considered mandatory. Let the compiler help you.
Here's the full program:
#include <iostream>
#include <random>
#include <string>
std::string pad(std::string message) {
std::string output;
const std::string jargon("123456790?<>~#/#+*&^%$!-`|");
static std::mt19937 prng(std::random_device{}());
static std::uniform_int_distribution<std::size_t> jargonSelector(
0, jargon.length() - 1);
static std::uniform_int_distribution<int> numJargon(1, 5);
for (auto c : message) {
if (std::isalpha(c) || std::isspace(c)) {
int padSize = numJargon(prng);
output.push_back(c);
for (int i = 0; i < padSize; ++i) {
output.push_back(jargon[jargonSelector(prng)]);
}
}
};
return output;
}
int main() {
std::string userin;
std::cout << "Please enter the message you wish to encrypt" << '\n';
std::cout << "Enter here: ";
std::getline(std::cin, userin);
std::cout << "\nHere is your Encoded Message: " << pad(userin) << '\n';
std::cout << " " << '\n';
return 0;
}
Once a character is determined to be a letter or space (worth noting that std::isspace returns true for any whitespace character): the size of the pad is determined, the original letter is pushed back into output, then a small loop to push back the pad size's worth of 'jargon' characters.
At the end of the function, the object output is returned instead of the single space nothing string you were returning. I also removed the print statement from the function because that's not the function's job.
Here's a sample output:
Please enter the message you wish to encrypt
Enter here: Hello World!
Here is your Encoded Message: H#32e~/l94l%-4o5`> ?#W/o*5!r>!l&+#d15~3
I fixed it by simply moving my variables inside the loop so that they repeat each time, as they were previously outside the loop, and only being carried out once.
If You Are Beginner I Suggest You To Use Caesar Cipher Its The Most Easiest Way To Encrypt Text Here Is An Example:-
#include <iostream>
#include <string>
using namespace std;
string CaesarCipher(string text, int key)
{
string result;
for (int i = 0; i < text.length(); i++)
{
if (isupper(text[i]))
result += char(int(text[i] + key - 65) % 26 + 65);
else if (text[i] > 47 && text[i] < 58)
result += char(int(text[i] + key - 48) % 10 + 49);
else
result += char(int(text[i] + key - 97) % 26 + 97);
}
return result;
}
int main()
{
int key;
string text, result;
cout << "Warning: Do Not Use Special Chars Like : $ % # # !" << "\n";
cout << "Enter The Text You Want To Encrypt: ";
cin >> text;
cout << "Enter The Key Number For Chars Shifting: ";
cin >> key;
result = CaesarCipher(text, key);
cout << "Encrypted Text: " << result << "\n";
system("pause");
return 0;
}
Key Number Is The Number Of Times You Want To Shift The Char To Another Char In Ascii.
Example Using Key 4 For Test String: test -> xiwx
I Suggest You To Read Ascii Table To Understand The Code More Easier.
I Made A CrackMe On Github That Have Alot Of Basic Information About Encrypting And Anti Debugging: https://github.com/coderx64-cyber/Anti-CrackMe-V2

Comparing chars in if statement with or

recently I encountered a problem with comparing chars.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string test1 = "test";
string test2 = "adssadad";
if (test1[0] == 'b' || 'd')
{
cout << "it equals" << "\n";
}
return 0;
}
Everytime I compare chars in if statement and or appears - if statement always returns true and code inside is executed. How do I solve this kind of problem?
The line
if (test1[0] == 'b' || 'd')
is equivalent to
if ((test1[0] == 'b') || 'd')
due to == having higher precedence than ||. This always evaluates to true since 'd' implicitly evaluates to true.
Probably what you thought this meant was
if (test1[0] == ('b' || 'd'))
but this wouldn't work either since this will evaluate to
if (test1[0] == true) // <=> if (test1[0])
Which will be true whenever test[0] != '\0'. What you need is to test each case separately
if ((test1[0] == 'b') || (test1[0] == 'd'))
If there are lots of values to check then it may be easier to store them in a container and use an algorithm.
const std::vector<char> vals {'b', 'd'};
if (std::find(vals.cbegin(), vals.cend(), test1[0]) != vals.cend())
'd' evaluates to non-zero, which is interpreted as true in C++. If even one operand of OR is true, the entire expression is true, so the cout line is executed.
You want to write test[0] == 'b' || test[0] == 'd'
Your if statement is interpreted as follows: if [(test1[0] == 'b') || ('d')] Since 'd' is not null or zero, it always evaluates to true.
Change the statement to if (test1[0] == 'b' || test1[0] = 'd')
Use switch here:
switch(test[10])
{
case b:
case d:
cout << "it equals" << "\n";
break;
}

Unable to compare characters (c++)

I'm trying to make a simple mad libs program in c++, and i want to check and see if a word that a user entered starts with a vowel, and if it does, change the "a" before the word, to an "an". I've been able to get the first character stored, but it will not compare to the other characters in the If statement. Am i doing this completely wrong?
#include <string>
#include <iostream>
using namespace std;
int main() {
string adj_3;
string anN;
char firstChar;
// GETTING USER'S WORD
cout << "ADJECTIVE: " << endl;
getline(cin, adj_3);
// GETTING FIRST CHARACTER
firstChar = adj_3[0];
// SEEING IF IT'S A VOWEL (not working)
if(firstChar == ('a' || 'e' || 'i' || 'o' || 'u' || 'A' || 'E' || 'I' || 'O' || 'U')) {
anN = "n";
}
else {
cout << "not working" << endl;
}
cout << "I am having a" << anN << " " << adj_3 << " time at camp." << endl;
}
The || operator needs to be applied to two arguments, like so:
if (firstChar == 'a' || firstChar == 'e' || firstChar == 'i' || ...)
firstChar == 'a' evaluates to a boolean. firstChar == 'a' || firstChar == 'e' takes the two booleans that results from those two operations, and returns another boolean, which is then fed into the next || operation as the first argument. In this way you can "chain" the || operations until one of them is true, or until they're all false.
See here for examples and explanation.
hnefatl's answer is one way.
You can also use switch case without break statements to check vowel. Something like:
switch(firstChar)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
case 'A':
case 'E':
case 'I':
case 'O':
case 'U': cout<<"Vowel";
}
On top of that switch-case have many advantages over if-else ladder as stated here https://stackoverflow.com/a/1028463/6594779.
Logical operator || combines two boolean expressions, e.g. a==0 || b==1, and returns true if either of the two operands is true. If you pass a single character like 'a' as operand, this will be interpreted as true, since the value of 'a' is 97 and 97 != 0 => true. Hence, your expression ('a' || 'e' || 'i' || 'o' || 'u' || 'A' || 'E' || 'I' || 'O' || 'U') will always be true, and firstchar == (....) is the same as firstchar == true, which will probably give false.
You could write...
if (firstChar == 'a' || firstChar == 'e' || firstChar == 'i' || ...)
or...
if (strchr(firstChar, "aeiouAEIOU") != NULL)) ...
You can use an array too wherein you store all the vowels and then compare it. Something like shown below:
char vowels[10]={'a','e','i','o','u','A','E','I','O','U'};
int flag=0;
for(int i=0;i<10;i++)
{
if(vowels[i]==firstChar)
{
flag=1;
anN="n";
}
}
if(flag==1)
cout << "I am having a" << anN << " " << adj_3 << " time at camp." << endl;
else
cout << "not working" << endl;

Comparing char for validation in C++

/*
PROGRAM: Ch6_14.cpp
Written by Corey Starbird
This program calculates the balance
owed to a hospital for a patient.
Last modified: 10/28/13
*/
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
// Prototypes for In-patient and Out-patient functions.
double stayTotal (int, double, double, double); // For In-patients
double stayTotal (double, double); // For Out-patients
int main()
{
char patientType; // In-patient (I or i) or Out-patient (O or o)
double rate, // Daily rate for the In-patient stay
servCharge, // Service charge for the stay
medCharge, // Medication charge for the stay
inTotal, // Total for the In-patient stay
outTotal; // Total for the Out-patient stay
int days; // Number of days for the In-patient stay
// Find out if they were an In-patient or an Out-patient
cout << "Welcome, please enter (I) for an In-patient or (O) for an Out-patient:" << endl;
cin >> patientType;
while (patientType != 'I' || 'i' || 'O' || 'o')
{
cout << "Invalid entry. Please enter either (I) for an In-patient or (O) for an Out-patient:" << endl;
cin >> patientType;
}
cout << "FIN";
return 0;
}
Hey, brand new to C++ here. I am working on a project and I'm having trouble figuring out why my validation for patientTypeisn't working properly. I first had double quotes, but realized that would denote strings. I changed them to single quotes, my program will compile and run now, but the while loop runs no matter what I enter, I, i, O, o, or anything else.
I don't know why the while loop isn't checking the condition, seeing that I did enter one of the characters in the condition, and move on to cout. Probably a simple mistake, but I thank you in advance.
Your while condition is wrong.
You most likely want this:
while (patientType != 'I' && patientType != 'i' && patientType != 'O' && patientType != 'o')
You got to use &&. patientType isn't I or it isn't i would be always true. Also you got to use patientType != for every item being checked or the characters i, o, O would be implicitly converted to bool (true for all of them).
while (patientType != 'I' && patientType != 'i' &&
patientType != 'O' && patientType != 'o')
As written, the condition is always true, because three of the four expressions OR-ed together are non-zero.
The problem is this line
(patientType != 'I' || 'i' || 'O' || 'o')
This doesn't do what you think, you want
(patientType != 'I' && patientType != 'i' && patientType != 'O' && patientType != 'o')
The comparison operators are strictly between two values, the left and right side.
C and C++ treat any value that is not zero as being "true". So,
(patientType != 'I' || 'i' || 'O' || 'o')
Was being translated as
(patientType != 'I') or ('i' is not 0) or ('O' is not 0) or ('o' is not 0)

conditional statement in while loop

I must have missed something. I'm doing an exercise to learn c++ and it asks that if a user inputs either c,p,t or g character then carry on, otherwise re-request prompt, so I wrote this:
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int main(void){
cout << "Please enter one of the following choices:" << endl;
cout << "c) carnivore\t\t\tp) pianist\n";
cout << "t) tree\t\t\t\tg) game\n";
char ch;
do{
cout << "Please enter a c, p, t, or g: ";
cin >> ch;
cout << "\"" << ch << "\"" << endl;
}while(ch != 'c' || ch != 'p' || ch != 't' || ch != 'g');
cout << "End" << endl;
cin.clear();
cin.ignore();
cin.get();
return 0;
}
This does not work and all I get is the prompt re-requesting it even when pressing either of the correct characters.
However if I change this line:
while(ch != 'c' || ch != 'p' || ch != 't' || ch != 'g');
to
while(ch != 'c' && ch != 'p' && ch != 't' && ch != 'g');
why is that? My understanding is that the "OR" statement should work as one of the tests is correct.
why is that? My understanding is that the "OR" statement should work as one of the tests is correct.
Exactly. There is always one of the tests that passes. A character will either be not 'c', or not 'p'. It can't be both 'c' and 'p'. So the condition is always true, leading to an infinite loop.
The alternative condition with the conjunctions works because it is false as soon as ch is equal to one of the alternatives: one of the inequalities is false, and thus the whole condition is false.
My understanding is that the "OR" statement should work as one of the tests is correct.
Well, you could use ||, but the expression would have to be:
while(!(ch == 'c' || ch == 'p' || ch == 't' || ch == 'g'));
By applying the De Morgan's law, the above simplifies to:
while(ch != 'c' && ch != 'p' && ch != 't' && ch != 'g');