C++ Multiple statements for conditional operator - c++

I'm trying to use a conditional statement that does one thing in one condition but does two things if the other condition applies.
Consider the following:
( h >= 0 && h < 24 ? hour = h : hour = 0, cout << "Invalid Hour Detected\n")
If "h" is set to 25, it sets "hour" to 0 correctly.
If "h" is set to 12, it correctly sets "hour" to 12.
The problem is that it outputs "Invalid Hour Detected" for both true and false conditions.
I only want it to output if the conditions aren't met.
Essentially, I'm wondering if it is possible in a conditional statement to do two things for one condition.
Also tried:
( h >= 0 && h < 24 ? hour = h : hour = 0 && cout << "Invalid Hour Detected\n")
but that didn't run the cout on either case.

If you really want to do this, add proper parentheses and invert the order of the assignment and the output insertion (when using the comma operator, the value of the left expression is discarded):
( h >= 0 && h < 24 ) ? ( hour = h ) : (std::cout << "Invalid Hour Detected\n", hour = 0);
However, my advice is to make your code readable and abandon this kind of coding style.

I'm trying to use a conditional statement that does one thing in one condition but does two things if the other condition applies.
That's not a conditional statement, it's a conditional expression+. Conditional statement would be a lot more appropriate here from the readability perspective:
if( h >= 0 && h < 24) {
hour = h;
} else {
hour = 0;
cout << "Invalid Hour Detected\n";
}
+ C++ follows C in allowing use of standalone expressions as statements. That's why you can eventually "shoehorn" your solution into the right syntax by using parentheses and switching the order of operations. The readability of that solution suffers a lot compared to that of a plain, familiar if.

Try
( h >= 0 && h < 24 ? hour = h : (hour = 0 || cout << "Invalid Hour Detected\n"))
Or
( h >= 0 && h < 24 ? hour = h : (hour = 0 & cout << "Invalid Hour Detected\n"))

The comma operator has the lowest precedence of all the operators. Consequently, your expression is evaluated like this:
(( h >= 0 && h < 24 ? hour = h : hour = 0), cout << "Invalid Hour Detected\n")
You could express this in a conditional expression, with grouping and proper usage of the comma operator. But, if at all possible, it would be better to express this in an if/else statement. If you need to use it in an expression, consider placing it in a function.

Well I know that this is probably not the answer you are looking for but if you refactored a little this would be cleared up "naturally".
// Handy as a utility free function (in apt namespace)
bool isValidHour(unsigned int hour) {
return hour >= 0 && hour < 24;
}
isValidHour(h) ? hour = h : handleInvalidHour();
//...more
// If this is not in a class then you should pass "hour" as a reference.
void MyClass::handleInvalidHour() {
hour = 0;
cout << "Invalid Hour Detected\n";
}
Of course you should be using the new std::chrono stuff if possible. It's lovely and expressive.

Related

Are the answers of this C++ quiz correct?

In the university I had a quiz today. The quiz is over but I can't understand some of its questions are their correct answers.
Note: I am not asking this to solve my quiz. Quiz is over I am just confused in some questions.
Question 1:
Consider the following variable declarations:
int catHeight = 6;
int dogHeight = 7;
string dogName = "Rover";
string catName = "Sylvester";
float catWeight = 15.0;
float dogWeight = 20.0;
bool dogRabies = true;
bool catRabies = false;
Choose Boolean expressions equivalent to following statements.
the cat has rabies and does not weigh 20 pounds or less
catRabies && catWeight > 20
!( catRabies && catWeight <=20)
! catRabies && catWeight >=20(This was marked as correct. I think the first option is correct)
the cat height and the dog height are not 10 (Hint: more than 1 answer)
catHeight > 10 && dogHeight >10
(catHeight && dogHeight) != 10
catHeight !=10 && dogHeight != 10
2nd and third are were marked as correct in result. But I think that only third one is correct. Please explain if I am wrong.
Question 2:
if numNeighbors >= 3 || numNeighbors = 4
++numNeighbors;
cout << "You are dead" << endl;
else
--numNeighbors;
What is wrong with the following if statement (there are at least 3 errors). The
indentation indicates the desired behavior
syntax error; else without previous if(marked as correct)
syntax error; value required of left operand (marked as correct)
syntax error; Parenthesis missing (marked as corrent)
syntax error; statement missing
I understand why 1 and 3 are correct but can't get the meaning of second one. Kindly explain it.
3 errors in question 2:
missing ( ) around the if condition
in the second part of the if condition there must be double ==
{ } are missing
To be a valid code it must be set like this:
if (numNeighbors >= 3 || numNeighbors == 4)
{
++numNeighbors;
cout << "You are dead" << endl;
}
else
--numNeighbors;
This was marked as correct. I think the first option is correct
Yes, you're right.
But I think that only third one is correct.
You're also right here.
Question 2
This one does not make sense unless you are trying to parse like a compiler. For instance, "else without previous if" only makes sense if you consider the current state of the code and not what you are trying to achieve. But the question tells you what you are trying to achieve.
syntax error; value required of left operand (marked as correct)
This means the condition is being parsed as (numNeighbors >= 3 || numNeighbors) = 4; which makes clear that the left side is not something you can assign to.
Your understanding of (1.1) and (1.2) seems to be correct.
In (2), if you fix the other errors,
if (numNeighbors >= 3 || numNeighbors = 4)
will be parsed as
if ((numNeighbors >= 3 || numNeighbors) = 4)
For this GCC outputs error: lvalue required as left operand of assignment, which reads similar to "value required of left operand".

Why will my elseif statment never executed

Any idea why the else if statment will be never executed ? The value of difference is constantly changing when the program runs.
double difference = abs(reale_x[0] - reale_x[1]);
if (0 <= difference < 45) {
timer_counter += 1;
if (timer_counter == 30) {
cout << "CLICK" << '\n';
}
}
else if (difference > 50) {
timer_counter = 0;
}
That is not how comparation works in c++.
What this code
if (0 <= difference < 45) {
does is it first compares if 0 is smaller or equal to difference. It is then "replaced" by a bool value either true or false. And then a bool value (so either 1 or 0) is compared to 45. And it will always be smaller than 45. What you have there is an always true statement.
So the way you would write this if statement is
if (difference >= 0 && difference < 45){
Note that because of your else if statement it will not execute if the difference is >44 and <51
if (0 <= difference < 45) will be executed as if ((0 <= difference) < 45), which will be either 0<45 or 1<45 and will always be true. That's why the else part is not getting executed.
in mathematics, we see and write 0 <= x < 45 or something like that to define the range of the variable x. But in order to tell the computer the same thing, you have to tell more clearly. Saying, to have to tell the compiler, that the value of x is greater than or equal to zero and at the same time, that value will be less than 45, and you can tell the compiler by this statement: difference >= && difference < 45 . the && is an 'AND' operator in most of the languages.

c++ && conditional never executed

I'm trying to create a program for an assignment that computes the rate for a long distance call, that takes in the starting time and length of call and outputs the gross cost and net cost.
There are several parameters involved, which i've implemented in conditional statements,
Any call started at or after 6:00 pm (1800) but before 8:00 am (800) is discounted 50%.
All calls are subject to a 4% federal tax.
The regular rate is $0.35 per minute.
Any call longer than 60 minutes receives a 16% discount on its cost (after any other discount is subtracted but before tax is added).
However, the first conditionals code is never executed and I've tried several different operands and still have not figured it out.
#import <iostream>
using namespace std;
int main() {
//declare variables
int startTime;
int callLength;
double grossCost = 0;
double netCost;
const double callRate = 0.35;
const double fedTax = 0.04;
const double discount1 = 0.50;
const double discount2 = 0.16;
//begin user prompt
cout << "Enter start time: " << endl;
cin >> startTime;
cout << "Enter length of call in minutes: " << endl;
cin >> callLength;
//define our grossCost
grossCost = (callLength * callRate);
//lez do some conditionals
if ((startTime >= 1800) && (startTime <= 800)){
netCost = grossCost - (grossCost * discount1);
netCost *= fedTax;
}
else if (callLength > 60){
netCost = grossCost - (grossCost * discount2);
netCost *= fedTax;
}
else{
netCost = (grossCost * fedTax);
}
//print out our final costs
cout << "gross cost : " << "$" << grossCost << endl;
cout << "net cost: " << "$" << netCost << endl;
return 0;
}
So, when trying an input of:
Enter start time: 2322
Enter length of call in minutes: 67
gross cost : $23.45
net cost: $0.78792
The netcost is not being evaluated correctly, as it is skipping the first conditional, even though the values of startTime meet the parameters.
The output should be:
Enter start time: 2322
Enter length of call in minutes: 67
gross cost: $23.45
net cost: $10.24
I'm not looking for someone to do my homework, just some pointers to lead me in the right direction, i've gone over the conditional several times and I'm still confused as to why it's not evaluating. Any help is appreciated, thanks.
You have a logic error here: a number can not be greater or equal than 1800 and less or equal than 800 at the same time. Revise the first conditional. I would break it in two parts
if((time >= 1800 & <=2400) || (time >= 0 && time <= 800)).
The actual logical mistake here is that calls after 6PM and before 8AM would exist in different days! So we do need two conditions that check on the days' boundaries as well, combined.
Edit per comment by #Reto Koradi:
The outcome won't change if we omit the boundary checks. As mentioned above, the gist of the change is to highlight the mutual exclusiveness of th two conditions, which is achieved by swapping the && out with an ||:
if (time >= 1800 || time <= 800)
The explanation why it's not working is fairly obvious, and already covered in other answers. This expression can never be true because no number is both greater than 1800 and also less than 800.
if ((startTime >= 1800) && (startTime <= 800)){
The && operator tests for both conditions to be true.
The more interesting part is why people make this mistake. And you're neither the first nor the last person to fall into this trap when starting out with logical expressions.
I believe the reason is that in natural language, we use the word "and" in ways that are very different from the logical operator. When you say "before 8 am and after 6 pm", the "and" corresponds much more to the "union" set operation. You're basically defining a set that contains "all times before 8 am" and "all times after 6 pm", which is a set union.
The logical operator that matches the "union" set operation is the logical "or". Any element that is in at least one of the input sets is part of the union. So for the union of two sets, the union is the set with elements that are in the first set or the second set.
With that understood, the correct condition is:
if ((startTime >= 1800) || (startTime <= 800)){
where || is the logical "or" operator.
Logical operations working differently from the way they are used in everyday language is not unusual at all. So you always need to be careful when translating language to logical expressions. Another popular example is that "or" in natural language mostly corresponds to an exclusive or, while the "or" operator is inclusive. So if somebody tells you that "you can take it or leave it", it means that you have to decide, while the standard logical "or" operator would actually allow you to do both.
The problem is
if ((startTime >= 1800) && (startTime <= 800)){
The two conditions are mutually exclusive. There is no number greater than 1800 and at the same time smaller than 800. You might want to fix the comparison condition like this (improved for future readers thanks to iksemyonov's comments. Please refer to his answer to this same question)
if ((startTime >= 1800) || (startTime <= 800)){
How can x > 1800 and x < 800 ever be true at the same time?. If the first is true, the statement will always be false.

Determining if a number is either a multiple of ten or within a particular set of ranges

I have a few loops that I need in my program. I can write out the pseudo code, but I'm not entirely sure how to write them logically.
I need -
if (num is a multiple of 10) { do this }
if (num is within 11-20, 31-40, 51-60, 71-80, 91-100) { do this }
else { do this } //this part is for 1-10, 21-30, 41-50, 61-70, 81-90
This is for a snakes and ladders board game, if it makes any more sense for my question.
I imagine the first if statement I'll need to use modulus. Would if (num == 100%10) be correct?
The second one I have no idea. I can write it out like if (num > 10 && num is < 21 || etc.), but there has to be something smarter than that.
For the first one, to check if a number is a multiple of use:
if (num % 10 == 0) // It's divisible by 10
For the second one:
if(((num - 1) / 10) % 2 == 1 && num <= 100)
But that's rather dense, and you might be better off just listing the options explicitly.
Now that you've given a better idea of what you are doing, I'd write the second one as:
int getRow(int num) {
return (num - 1) / 10;
}
if (getRow(num) % 2 == 0) {
}
It's the same logic, but by using the function we get a clearer idea of what it means.
if (num is a multiple of 10) { do this }
if (num % 10 == 0) {
// Do something
}
if (num is within 11-20, 31-40, 51-60, 71-80, 91-100) { do this }
The trick here is to look for some sort of commonality among the ranges. Of course, you can always use the "brute force" method:
if ((num > 10 && num <= 20) ||
(num > 30 && num <= 40) ||
(num > 50 && num <= 60) ||
(num > 70 && num <= 80) ||
(num > 90 && num <= 100)) {
// Do something
}
But you might notice that, if you subtract 1 from num, you'll have the ranges:
10-19, 30-39, 50-59, 70-79, 90-99
In other words, all two-digit numbers whose first digit is odd. Next, you need to come up with a formula that expresses this. You can get the first digit by dividing by 10, and you can test that it's odd by checking for a remainder of 1 when you divide by 2. Putting that all together:
if ((num > 0) && (num <= 100) && (((num - 1) / 10) % 2 == 1)) {
// Do something
}
Given the trade-off between longer but maintainable code and shorter "clever" code, I'd pick longer and clearer every time. At the very least, if you try to be clever, please, please include a comment that explains exactly what you're trying to accomplish.
It helps to assume the next developer to work on the code is armed and knows where you live. :-)
If you are using GCC or any compiler that supports case ranges you can do this, but your code will not be portable.
switch(num)
{
case 11 ... 20:
case 31 ... 40:
case 51 ... 60:
case 71 ... 80:
case 91 ... 100:
// Do something
break;
default:
// Do something else
break;
}
This is for future visitors more so than a beginner. For a more general, algorithm-like solution, you can take a list of starting and ending values and check if a passed value is within one of them:
template<typename It, typename Elem>
bool in_any_interval(It first, It last, const Elem &val) {
return std::any_of(first, last, [&val](const auto &p) {
return p.first <= val && val <= p.second;
});
}
For simplicity, I used a polymorphic lambda (C++14) instead of an explicit pair argument. This should also probably stick to using < and == to be consistent with the standard algorithms, but it works like this as long as Elem has <= defined for it. Anyway, it can be used like this:
std::pair<int, int> intervals[]{
{11, 20}, {31, 40}, {51, 60}, {71, 80}, {91, 100}
};
const int num = 15;
std::cout << in_any_interval(std::begin(intervals), std::end(intervals), num);
There's a live example here.
The first one is easy. You just need to apply the modulo operator to your num value:
if ( ( num % 10 ) == 0)
Since C++ is evaluating every number that is not 0 as true, you could also write:
if ( ! ( num % 10 ) ) // Does not have a residue when divided by 10
For the second one, I think this is cleaner to understand:
The pattern repeats every 20, so you can calculate modulo 20.
All elements you want will be in a row except the ones that are dividable by 20.
To get those too, just use num-1 or better num+19 to avoid dealing with negative numbers.
if ( ( ( num + 19 ) % 20 ) > 9 )
This is assuming the pattern repeats forever, so for 111-120 it would apply again, and so on. Otherwise you need to limit the numbers to 100:
if ( ( ( ( num + 19 ) % 20 ) > 9 ) && ( num <= 100 ) )
With a couple of good comments in the code, it can be written quite concisely and readably.
// Check if it's a multiple of 10
if (num % 10 == 0) { ... }
// Check for whether tens digit is zero or even (1-10, 21-30, ...)
if ((num / 10) % 2 == 0) { ... }
else { ... }
You basically explained the answer yourself, but here's the code just in case.
if((x % 10) == 0) {
// Do this
}
if((x > 10 && x < 21) || (x > 30 && x < 41) || (x > 50 && x < 61) || (x > 70 && x < 81) || (x > 90 && x < 101)) {
// Do this
}
You might be overthinking this.
if (x % 10)
{
.. code for 1..9 ..
} else
{
.. code for 0, 10, 20 etc.
}
The first line if (x % 10) works because (a) a value that is a multiple of 10 calculates as '0', other numbers result in their remainer, (b) a value of 0 in an if is considered false, any other value is true.
Edit:
To toggle back-and-forth in twenties, use the same trick. This time, the pivotal number is 10:
if (((x-1)/10) & 1)
{
.. code for 10, 30, ..
} else
{
.. code for 20, 40, etc.
}
x/10 returns any number from 0 to 9 as 0, 10 to 19 as 1 and so on. Testing on even or odd -- the & 1 -- tells you if it's even or odd. Since your ranges are actually "11 to 20", subtract 1 before testing.
A plea for readability
While you already have some good answers, I would like to recommend a programming technique that will make your code more readable for some future reader - that can be you in six months, a colleague asked to perform a code review, your successor, ...
This is to wrap any "clever" statements into a function that shows exactly (with its name) what it is doing. While there is a miniscule impact on performance (from "function calling overhead") this is truly negligible in a game situation like this.
Along the way you can sanitize your inputs - for example, test for "illegal" values. Thus you might end up with code like this - see how much more readable it is? The "helper functions" can be hidden away somewhere (the don't need to be in the main module: it is clear from their name what they do):
#include <stdio.h>
enum {NO, YES, WINNER};
enum {OUT_OF_RANGE=-1, ODD, EVEN};
int notInRange(int square) {
return(square < 1 || square > 100)?YES:NO;
}
int isEndOfRow(int square) {
if (notInRange(square)) return OUT_OF_RANGE;
if (square == 100) return WINNER; // I am making this up...
return (square % 10 == 0)? YES:NO;
}
int rowType(unsigned int square) {
// return 1 if square is in odd row (going to the right)
// and 0 if square is in even row (going to the left)
if (notInRange(square)) return OUT_OF_RANGE; // trap this error
int rowNum = (square - 1) / 10;
return (rowNum % 2 == 0) ? ODD:EVEN; // return 0 (ODD) for 1-10, 21-30 etc.
// and 1 (EVEN) for 11-20, 31-40, ...
}
int main(void) {
int a = 12;
int rt;
rt = rowType(a); // this replaces your obscure if statement
// and here is how you handle the possible return values:
switch(rt) {
case ODD:
printf("It is an odd row\n");
break;
case EVEN:
printf("It is an even row\n");
break;
case OUT_OF_RANGE:
printf("It is out of range\n");
break;
default:
printf("Unexpected return value from rowType!\n");
}
if(isEndOfRow(10)==YES) printf("10 is at the end of a row\n");
if(isEndOfRow(100)==WINNER) printf("We have a winner!\n");
}
For the first one:
if (x % 10 == 0)
will apply to:
10, 20, 30, .. 100 .. 1000 ...
For the second one:
if (((x-1) / 10) % 2 == 1)
will apply for:
11-20, 31-40, 51-60, ..
We basically first do x-1 to get:
10-19, 30-39, 50-59, ..
Then we divide them by 10 to get:
1, 3, 5, ..
So we check if this result is odd.
As others have pointed out, making the conditions more concise won't speed up the compilation or the execution, and it doesn't necessarily help with readability either.
It can help in making your program more flexible, in case you decide later that you want a toddler's version of the game on a 6 x 6 board, or an advanced version (that you can play all night long) on a 40 x 50 board.
So I would code it as follows:
// What is the size of the game board?
#define ROWS 10
#define COLUMNS 10
// The numbers of the squares go from 1 (bottom-left) to (ROWS * COLUMNS)
// (top-left if ROWS is even, or top-right if ROWS is odd)
#define firstSquare 1
#define lastSquare (ROWS * COLUMNS)
// We haven't started until we roll the die and move onto the first square,
// so there is an imaginary 'square zero'
#define notStarted(num) (num == 0)
// and we only win when we land exactly on the last square
#define finished(num) (num == lastSquare)
#define overShot(num) (num > lastSquare)
// We will number our rows from 1 to ROWS, and our columns from 1 to COLUMNS
// (apologies to C fanatics who believe the world should be zero-based, which would
// have simplified these expressions)
#define getRow(num) (((num - 1) / COLUMNS) + 1)
#define getCol(num) (((num - 1) % COLUMNS) + 1)
// What direction are we moving in?
// On rows 1, 3, 5, etc. we go from left to right
#define isLeftToRightRow(num) ((getRow(num) % 2) == 1)
// On rows 2, 4, 6, etc. we go from right to left
#define isRightToLeftRow(num) ((getRow(num) % 2) == 0)
// Are we on the last square in the row?
#define isLastInRow(num) (getCol(num) == COLUMNS)
// And finally we can get onto the code
if (notStarted(mySquare))
{
// Some code for when we haven't got our piece on the board yet
}
else
{
if (isLastInRow(mySquare))
{
// Some code for when we're on the last square in a row
}
if (isRightToLeftRow(mySquare))
{
// Some code for when we're travelling from right to left
}
else
{
// Some code for when we're travelling from left to right
}
}
Yes, it's verbose, but it makes it clear exactly what's happening on the game board.
If I was developing this game to display on a phone or tablet, I'd make ROWS and COLUMNS variables instead of constants, so they can be set dynamically (at the start of a game) to match the screen size and orientation.
I'd also allow the screen orientation to be changed at any time, mid-game - all you need to do is switch the values of ROWS and COLUMNS, while leaving everything else (the current square number that each player is on, and the start/end squares of all the snakes and ladders) unchanged.
Then you 'just' have to draw the board nicely, and write code for your animations (I assume that was the purpose of your if statements) ...
You can try the following:
// Multiple of 10
if ((num % 10) == 0)
{
// Do something
}
else if (((num / 10) % 2) != 0)
{
// 11-20, 31-40, 51-60, 71-80, 91-100
}
else
{
// Other case
}
I know that this question has so many answers, but I will thrown mine here anyway...
Taken from Steve McConnell's Code Complete, 2nd Edition:
"Stair-Step Access Tables:
Yet another kind of table access is the stair-step method. This access method isn’t as direct as an index structure, but it doesn’t waste as much data space. The general idea of stair-step structures, illustrated in Figure 18-5, is that entries in a table are valid for ranges of data rather than for distinct data points.
Figure 18-5 The stair-step approach categorizes each entry by determining the level at which it hits a “staircase.” The “step” it hits determines its category.
For example, if you’re writing a grading program, the “B” entry range might be from 75 percent to 90 percent. Here’s a range of grades you might have to program someday:
To use the stair-step method, you put the upper end of each range into a table and then write a loop to check a score against the upper end of each range. When you find the point at which the score first exceeds the top of a range, you know what the grade is. With the stair-step technique, you have to be careful to handle the endpoints of the ranges properly. Here’s the code in Visual Basic that assigns grades to a group of students based on this example:
Although this is a simple example, you can easily generalize it to handle multiple students, multiple grading schemes (for example, different grades for different point levels on different assignments), and changes in the grading scheme."
Code Complete, 2nd Edition, pages 426 - 428 (Chapter 18).

While loop condition not working

Hey basically i want both the player and the wolves to attack each other until one another are dead. But the while loop is infinite so obviously the condition is not met. But i cant see where i am going wrong with this if ( choice1 == 1) // if statement is used throughout the game to allow the user to interact through the game with choices.
while((Status.health != 0) && (Wolves.health != 0) )
{
int playerAttack = Status.strength + hitPoints() + Rock.attack;
cout<< "This is the player attack" << playerAttack;
Wolves.health = Wolves.health - playerAttack;
cout << "This is the wolves health" << Wolves.health;
if (Wolves.health <= 0)
{
cout << "\nThe wolves are dead\n ";
}
int wolfAttack = Wolves.attack + hitPoints();
Status.health - wolfAttack;
if(Status.health <= 0)
{
gameOver();
}// print out of object health.
}
Can anybody help ?
Compare:
Wolves.health = Wolves.health - playerAttack;
vs
Status.health - wolfAttack;
Notice any difference?
Well, i think the health was not exact 0 - because your condition looks only for != 0
it should be bigger than 0
while((Status.health > 0) && (Wolves.health > 0))
...
edit: also the missing = John Dibling found first
Are you sure that this is correct:
Status.health - wolfAttack;
This actually is a no-operation. Perhaps you meant:
Status.health -= wolfAttack;
in computer some of numbers cannot be represented for example 0.1, so if you calculate 1 - (0.1 * 10) its result not equal to zero. You checked only !=0 and ==0 condition. Try this:
=0 or <=0 also if your "health" variable is integer you give a error tolerance such as:
=(0.5) or <=(0.5) etc...
Most likely both values are never zero. That sounds likely, because you yourself use the <= condition.
I think your are getting negative values, I recomend to use
while((Status.health > 0) && (Wolves.health > 0) )