How to fix: else statement not being called c++ [duplicate] - c++

I am not sure what I'm doing wrong here, every time I run it, it goes through the if part even when it's not true? So the 'else' never runs.
#include <iostream>
using namespace std;
string choice;
float numb;
float convert(float numb,string choice)
{
float newNo;
if (choice == "F" or "f"){
newNo = numb * 0.2 * 9 + 32;
}else{
newNo = (numb - 32) / 1.8;
}
return newNo;
}
int main()
{
cout << "welcome to Temperature converter v0.1" << endl;
cout << endl;
cout << "Which conversion would you like to use?" << endl;
cout << "type C to convert to Celsius and F to convert to Fahrenheit - ";
cin >> choice;
cout << "what number would you like to convert? - ";
cin >> numb;
cout << convert(numb,choice);
return 0;
}

The problem is your if Statement:
if (choice == "F" or "f"){
basically, what you say here is:
If choise is "F" or if "f". You need to understand: True is everything besides zero (0). "f" is NOT zero, so it is true. You could also wirte (or = ||):
if (coice == "F" || true)
which is the same like:
if (true)
So in order for your code to work, you need:
if (choice == "f" || choice == "F")
That would do what you expect.

There is a problem in the syntax of 'if' statement. Following is the corrected code, where '||' stands for 'or':
if ((choice == "F") || (choice=="f")){
newNo = numb * 0.2 * 9 + 32;
}else{
newNo = (numb - 32) / 1.8;
}

Change this if statement
if (choice == "F" or "f"){
to the following
if (choice == "F" or choice == "f"){
Otherwise the right operand of the operator or
"f"
is always equal to true because it is converted to the address of the first character of the string literal that evidently is not equal to 0.
That is your original condition in the if statement looks like
if (choice == "F" or "f" != nullptr){
and indeed "f" != nullptr

Related

Clearing input buffer

I am writing a program, the program is basically a guessing game. Computer displays a number and the user has to guess whether their number is higher, lower or correct. I have already made the program and its all dandy, but the only not dandy part is that I cannot figure out how to get rid of the input buffer when the user decides to play the game again. Every time the user wants to play the game, the game starts again but with the same input as the last game. I have tried putting cin.clear() in any spot I could think and also cin.clear(). But it just seems to not work. How do I clear the input?
#include <iostream>
using namespace std;
int main ()
{
int num1 = 100;
char choice;
num1 = num1 / 2;
do
{
cout << "My guess is " << num1 << ". " << "Enter 'l' if your number is lower, 'h' if it is higher, 'c' if it is correct: ";
cin >> choice;
cin.clear();
if (choice == 'h')
{
num1 = num1 + 100;
num1 = num1 / 2;
}
if (choice == 'l')
{
num1 = num1 + num1;
num1 = num1 - 11;
num1 = num1 / 2;
}
if (choice == 'c')
{
cout << "Great! Do you want to play again (y/n)?: ";
cin >> choice;
}
} while (choice != 'c' || choice == 'Y' || choice == 'y' || choice == 'n' || choice == 'N');
return 0;
}
In order to restart the game, you need to reset num1. Put the inital value in a variable that you don't change.
const int init = 100;
char choice;
int num1 = init / 2;
When the computer has guessed correctly:
if (choice == 'c')
{
num1 = init / 2; // reset
cout << "Great! Do you want to play again (y/n)?: ";
cin >> choice;
}
You could also leave the loop condition at:
} while(choice != 'N' && choice != 'n');
You should also work on the divide and conquer algorithm. For the computer to be effective, it should always make a guess in the middle of the range that is still possible, and that's not what it's doing right now. It jumps up and down, even outside the established range. An alternative could be to keep two variables to be able to shrink the possible range effectively. You could also do two separate loops, one inner loop for guessing the number and one outer that only asks the user if he/she wants to play again.
Example:
#include <iostream>
int main() {
const int initlo = 1;
const int inithi = 100;
char choice;
do {
std::cout << "Think of a number [" << initlo << "," << inithi << "]\n";
int numlo = initlo; // initialize the range
int numhi = inithi;
int guess;
do {
guess = (numlo + numhi) / 2; // guess in the middle of the range
std::cout
<< "My guess is " << guess << ". "
<< "Enter 'l' if your number is lower, 'h' if it is higher, 'c' "
"if it is correct: ";
std::cin >> choice;
if(choice == 'h') // must be in the range (guess,numhi]
numlo = guess + 1;
else if(choice == 'l') // must be in the range [numlo,guess)
numhi = guess - 1;
// exit the loop if the user cheats or the answer is correct
} while(numlo <= numhi && choice != 'c');
if(choice == 'c') std::cout << "Great! ";
else std::cout << "Cheater! ";
std::cout << "Do you want to play again (y/n)?: ";
std::cin >> choice;
} while(choice == 'Y' || choice == 'y');
std::cout << "Bye\n";
}

C++ while loop insight request

basically I am having weird trouble with my while loop near the beginning of the program which checks for user validation on their choice of activity. When they choose the first activity and complete it, it works fine, but when they complete the second activity, it will go into runtime and keep requesting the user to input a valid choice, even though they haven't even gotten the chance to input a choice. Any tips?
#include <iostream>
using namespace std;
int main()
{
const int DIGITS_CHOICE = 1, IDENTIFIER_CHOICE = 2, DOUBLE_CHOICE = 3, EXIT_CHOICE = 4;
int choice;
int userNumber, storedNumber, factor = 10, digitCounter = 0, subtractor;
char ch;
do
{
cout << "\n\n\t\tPlease choose an option:\n\n"
<< "1. How many digits?\n"
<< "2. Is this a valid C++ Identifer?\n"
<< "3. Is this a double letter word?\n"
<< "4. Exit\n";
cout << endl << "Choice: ";
cin >> choice;
while (choice < DIGITS_CHOICE || choice > EXIT_CHOICE)
{
cout << endl << "Please enter a valid menu option: ";
cin >> choice;
}
if (choice != EXIT_CHOICE)
{
switch (choice)
{
case DIGITS_CHOICE:
cout << "Please enter an integer: ";
cin >> userNumber;
storedNumber = userNumber;
if (userNumber < 10)
{
digitCounter = 1;
}
else
{
while (userNumber != 0)
{
subtractor = userNumber % factor;
if (subtractor > 0)
{
userNumber = userNumber - subtractor;
factor *= 10;
digitCounter++;
}
else
{
userNumber = 0;
}
}
}
cout << storedNumber << " has " << digitCounter << " digit(s)." << endl;
factor = 10;
digitCounter = 0;
break;
case IDENTIFIER_CHOICE:
cout << "Please enter an identifier and press [Enter] immediately after. ";
cin >> ch;
if (ch >= 0 || ch <= 9 || ch <= 'a' || ch >= 'z' || ch <= 'A' || ch >= 'Z' || ch != '_')
{
if (ch >= 0 || ch <= 9)
{
cout << "Not a valid identifier." << endl;
cout << "Identifiers cannot start with a digit." << endl;
ch = '\n';
}
else
{
cout << "Not a valid identifier." << endl;
cout << "Inavlid character." << endl;
ch = '\n';
}
}
while (ch != '\n')
{
if (ch >= 'a' || ch <= 'z' || ch >= 'A' || ch <= 'Z')
{
cin.get(ch);
}
}
break;
case DOUBLE_CHOICE:
break;
}
}
} while (choice != EXIT_CHOICE);
return 0;
}
Also the program isn't complete yet. the third option has nothing and the 2nd option is almost complete. the first activity though is complete :)
Your check for valid characters is too broad, and doesn't really make sense:
if (ch >= 0 || ch <= 9 || ch <= 'a' || ch >= 'z' || ch <= 'A' || ch >= 'Z' || ch != '_')
Every possible value of ch is going to be greater than or equal to zero, so this expression is equivalent to (true || a || b || c || ... || z) and it's always going to resolve to true.
Instead, see if it's below 'A', between 'Z' and 'a' or beyond 'z' and if so, it's invalid.
Also, when checking if it's a digit, you need to check if it's ≥ '0' and ≤ '9' as characters. It's important that you compare it to the character representation of 0 and 9 because the value of the character '0' not actually 0 (it turns out it's actually 48) and likewise with '9':
if ( ch < 'A'
|| (ch > 'Z' && ch < 'a')
|| ch > 'z')
{
if (ch >= '0' && ch <= '9')
{
cout << "Not a valid identifier." << endl;
cout << "Identifiers cannot start with a digit." << endl;
ch = '\n';
}
else
{
cout << "Not a valid identifier." << endl;
cout << "Invalid character." << endl;
ch = '\n';
}
}
It's not really clear what the check after that is meant to do? Is it only meant to allow letters? That seems strange after saying "Identifiers cannot start with a digit." anyway:
if (ch >= 'a' || ch <= 'z' || ch >= 'A' || ch <= 'Z')
This has essentially the same issue where every character is going to be either above 'a' or below 'z' or both, so this will always resolve to true. Instead, use && to check for being within a range:
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
Hopefully that addresses your question.
The logic is not great; i is valid, but your code says it's not. It at least goes back to the menu just fine. Your code is also behaving like it will respond immediately as letters are being typed. That is not the case. It won't print anything until the user presses Enter.
It seems the issue is your variable ch being a char. If I type anything that's longer than a single character, what will happen is that the single character gets evaluated, and the remaining characters I typed remain in the input stream. It looks like you are attempting to handle that, but it's not working. I am not going to spend time delving into the why, partly because it's complex, partly because I don't know the full intricacies of istream behavior.
What I will say is that if you want to handle a multi-character input, use cin.get() everywhere and not just sometimes. You can do processing of each character, but again, nothing will go to the screen until the user presses Enter.
But here's code that appears to work:
#include <cctype> // isalpha() and isalnum()
#include <string> // ch is now a std::string
// ...
case IDENTIFIER_CHOICE:
cout << "Please enter an identifier and press [Enter] immediately after. ";
std::cin.ignore(256, '\n'); // needed because of getline behavior
std::getline(std::cin, ch);
if (!(isalpha(ch[0]) || ch[0] == '_')) {
cout << "Not valid.\n";
break;
}
for (int i = 1; i < ch.size(); ++i) {
if (!isalnum(ch[i])) {
cout << "Not valid.\n";
break;
}
}
cout << "Valid.\n";
break;
// ...
With cin, when you press Enter, that keystroke is saved in the input stream. getline() doesn't behave the way we expect because while cin will typically ignore that keystroke, getline does not. So I just tell cin to ignore an arbitrary (but sufficient in this case) amount of characters in the stream up to and including the Enter keystroke (Mac and Linux, should still behave for Windows (I think)).
This is still far from bulletproof input validation (that's impossible), but I think it suffices for what you're working on.

Multiple 'if' statements without an 'else'

The code I have to write is basically a mini bank. It asks for an initial amount, the type of action, and a second operator for that action.
I'm not allowed to use else, but am allowed to use if statements (I don't understand why), nor am I allowed to use a loop or an array.
This is the code I have so far:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int operand1;
int operand2;
float output;
char action;
int main()
{
cout << fixed << showpoint << setprecision(2);
cout << "Enter the initial balance [1-1000]: " << endl;
cin >> operand1;
cout << "Enter an action (D, W, I or C):" << endl;
cin >> action;
cout << "Enter the second operand:" << endl;
cin >> operand2;
if ((action != 'D' && action != 'W' && action != 'I' && action != 'C') || (operand1 > 1000 || operand1 < 1) ||
(action == 'I' && operand2 > 15 || operand2 < 1) || (action == 'C' && operand2 != 20 && operand2 != 10 && operand2 != 5) ||
(operand2 > 1000 || operand2 < 1))
{
cout << "Input out of range" << endl;
return 0;
}
if (action == 'D')
{
output = (operand1 + operand2);
cout << "The new account balance is " << output << endl;
}
if (action == 'W')
{
output = (operand1 - operand2);
if (output<0)
{
cout << "Input out of range" << endl;
return 0;
}
cout << "The new account balance is " << output << endl;
}
if (action == 'I')
{
output = ((float)operand1 + (((float)operand2 / 100) * (float)operand1));
cout << "The new account balance is " << output << endl;
}
if (action == 'C')
{
output = operand1 % operand2;
cout << operand1 / operand2 << " bills dispensed plus " << output << endl;
}
cin.get();
cin.get();
return 0;
}
On certain instances, I get multiple errors instead of just one. For example:
Enter the initial balance [1-1000]: 1030
Enter an action (D, W, I or C): D
Enter the second operand: 40
Input out of range
However, it seems to just move on when it sees the error anyway, and I get this output:
Enter the initial balance [1-1000]:
1030
Input out of range
Enter an action (D, W, I or C):
D
Enter the second operand:
40
The new account balance is 1070.00
I can't seem to figure out how to have only one output, and for it to just display the error with no balance, without using an else statement.
Use switch (action):
https://en.cppreference.com/w/cpp/language/switch
After the cases it can have a default.
Also lots of conventions forbid else, but not forbid elseif - are you sure elseif is forbidden in your case?
But even if elseif is allowed - switch is better to read and is a more elegant solution.
You can use switch by taking all the commands as different cases. This is what others have already said.
My contribution would be that you could put your first if statement i.e. the error case under the default case.
And before using switch statements, could you check if it is ever explicitly stated that you can't use 'else if' statements. If not, you should use that. It is not the same as an 'else' statement.
&& has a higher precedence than ||
if (
(action != 'D' && action != 'W' && action != 'I' && action != 'C') ||
(operand1 > 1000 || operand1 < 1) ||
// (action == 'I' && operand2 > 15 || operand2 < 1) ||
(action == 'I' && (operand2 > 15 || operand2 < 1)) ||
(action == 'C' && operand2 != 20 && operand2 != 10 && operand2 != 5) ||
(operand2 > 1000 || operand2 < 1))
{
cout << "Input out of range" << endl;
return 0;
}
To have more traceability, on what the code does, it would be worth the effort to do:
if (action != 'D' && action != 'W' && action != 'I' && action != 'C')
{
cout << "Input out of range; action " << action << endl;
return 0;
}
if (operand1 > 1000 || operand1 < 1)
{
cout << "Input out of range; 1st operand: " << operand1 << endl;
return 0;
}
...

My If statement isn't accepting '=='

I made a little game where the program jumbles up a word and asks for player input. However, one of the If statements are giving me an error and stopping me from compiling the program.
string isready;
cin >> isready;
if (isready == 'y' || 'Y')
Above I set up a string to be called isready, than asked the user for input. As seen above,
I wanted the if statement to activate if either y or capital y was typed in and received.
However, it just gives me the error:
invalid operands to binary expression ('string'
(aka 'basic_string, allocator >') and 'int')
Perhaps I'm missing a #include file?
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <unistd.h>
using namespace std;
int main()
{
enum fields {WORD, HINT, NUM_FIELDS};
const int NUM_WORDS = 5;
const string WORDS[NUM_WORDS][NUM_FIELDS] = //5x2 array
{
{"wall", "Do you feel you're banging your head against something?"},
{"glasses", "These might help you see the answer."},
{"labored", "Going slowly, is it"},
{"persistent", "Keep at it."},
{"jumble", "It's what the game is all about."}
};
srand(static_cast<unsigned int>(time(0)));
int choice = rand() % NUM_WORDS;
//Choice value in array, than area in array where word and hint are
string theWord = WORDS[choice][WORD]; //word to guess
string theHint = WORDS[choice][HINT]; //hint for word
string jumble = theWord; //jumbled version of word
int length = jumble.size();
//Index1 and index2 are random locations in the string theWord
//last two lines swaps areas, ending the for function with a different
//jumble variable every time.
for (int i = 0; i < length; ++i)
{
int index1 = rand() % length;
int index2 = rand() % length;
char temp = jumble[index1];
jumble[index1] = jumble[index2];
jumble[index2] = temp;
}
cout << "\t\tWelcome to Word Jumble!\n\n";
cout << "Unscramble the letters to make a word.\n";
cout << "\n\n\nReady? (y/n)";
//I'm asking here if the player is ready
string isready;
cin >> isready;
if (isready == 'y' || 'Y')
{
cout << "Ok this is how the scoring works\n";
cout << "The length of the word you will guess is times by 5000.\n";
cout << "If you ask for a hint, your score will go down by half.\n";
cout << "If you get the wrong answer, your score will go down by 1000.";
cout << "\nOk, lets start!\n\n\n";
int counter = 3;
for(int i = 0; i < 3; ++i)
{
cout << counter << "..." << endl;
counter--;
}
sleep(1);
}
else
{
cout << "check";
}
cout << "Enter 'quit' to quit the game.\n";
cout << "Enter 'hint' for a hint.\n";
cout << "The jumble is: " << jumble;
//Score system
unsigned long int score;
int amount_of_guesses, amount_of_wrong = 0;
string guess;
cout << "\n\nYour guess: ";
cin >> guess;
while ((guess != theWord) && (guess != "quit"))
{
if (guess == "hint")
{
cout << theHint;
amount_of_guesses++;
}
else
{
cout << "Sorry, that's not it.";
amount_of_wrong++;
}
cout << "\n\nYour guess: ";
cin >> guess;
}
score = theWord.length() * 1000 -(amount_of_wrong * 1000)
/ 2 * amount_of_guesses;
if (guess == theWord)
{
cout << "\nThat's it! You guessed it!\n";
}
cout << "Your score is: " << score;
cout << "\nThanks for playing.\n";
return 0;
}
here
(isready == 'y' || 'Y')
you are trying to use operator== on std::string and char, because 'y' is char. Apart from this conditions should be in parenthesis because || has lower precedence than ==
Correct version is:
( (isready == "y") || ( isready == "Y")) // use bool operator==
(const string& lhs,
const string& rhs);
Operator || takes logical expressions on both sides:
if (isready == "y" || isready == "Y")
Note the double quotes above, because isready is a std::string. You could also change isready to char, and use character constants (i.e. 'y' and 'Y' in single quotes).
Your current expression is syntactically valid, but it will be evaluated as unconditional true, because it is interpreted as follows:
if (isready == 'y' || 'Y' != 0)
// ^^^^^^^^
// != 0 part is implicit;
// `Y` != 0 is always true, so the entire OR is also always true
Change this statement
if (isready == 'y' || 'Y')
to
if ( isready == "y" || isready == "Y")
Take into account that there are double quotes.
The problem is that there is no such operator == that can compare an object of type std::string with an object of type char. There is no such a constructor in class std::string that could convert implicitly an object of type char to an object of type std::string. However class std::string has a constructor that can convert a string literal to an object of type std:string. So the right operand that is "y" or "y" is implicitly converted to a temporary object of type std::string. As the result in the condition above two objects of type std::string are compared.
Also the condition you wrote initially is invalid even if you would use string literals instead of character literals. If for example isready == "y" was equal to false then you will get
false || "y"
In this expression string literal "y" is converted to a pointer to its first character. As this pointer is not equal to NULL then the whole expression will be true independing of the value in isready
(isready == 'y' || 'Y')
You should check for each character seperately.
((isready == "y" || (isready == "Y"))
if (isready == 'y' || 'Y')
should be
if (isready == "y" || isready == "Y")

C++ Error C2040?

Error Message:
What does this mean?
And how do I fix it?
error C2040: '==' : 'int' differs in levels of indirection from 'const char [2]'
Code:
#include <iostream>
#include <cmath>
using namespace std;
int round(double number);
//Assumes number >=0.
//Returns number rounded to the nearest integer.
int main()
{
double doubleValue;
char ans;
do
{
cout << "Enter a double value: ";
cin >> doubleValue;
cout << "Rounded that number is " <<round(doubleValue)<< endl;
cout << "Again? (y/n): ";
cin >> ans;
}
//Here is the line generating the problem, while(...);
while (ans == 'y' || ans == "Y");
cout << "End of testing.\n";
return 0;
}
//Uses cmath
int round(double number)
{
return static_cast<int>(floor(number + 0.5));
}
You need to single-quote char literals. You did this correctly for the first one but not the second:
while (ans == 'y' || ans == "Y");
This should be:
while (ans == 'y' || ans == 'Y');
Double quotes are for string (const char[]) literals.
You have double quotes instead of single ones on this line:
while (ans == 'y' || ans == "Y");
The capital Y is contained in double quotes, which creates a const char [2] (Y followed by null). You probably ment:
while (ans == 'y' || ans == 'Y');
I dont know this is useful or not but it may be like following:
while ((ans == 'y') || (ans == 'Y'));