I'm curious about how c++ handles this nested conditional operator. I'm half sure that I understand how this works, but I'm curious, could anyone explain through a diagram how the loop would execute the nested conditional operator.
For example would the loop execute through the first expression of each conditional operator for each instance?
Also is this nested conditional operator structured as:
(i < 2) ? x[i] : y;
!i ? y : x[1];
I guess I'm just very curious about the nature of this. Please don't answer unless you are capable of giving me a thorough adequate explanation of how the loop executes this conditional operator.
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
const char x[2] [20] = {" Cloud "," at your service\n"};
const char * y = "Strife";
for (int i = 0; i < 7; i++)
cout << (( i < 2)? !i ? x [i] : y : x[1]);
cout << endl << endl << x[0] << endl << x[1] << endl;
cin.get();
cin.get();
return 0;
}
It seems you are asking how an expression like x ? y ? 1 : 2 : 3 is parsed.
If you think about it there is really only one possibility. Namely, the : furthest to the right must bind to the ? furthest to the left. Thus the expression parses as:
x ? (y ? 1 : 2) : 3
So, if x and y are true, then 1 is returned; if x but not y is true, then 2 is returned; and if x is false, then 3 is returned.
Sorry to not answer directly in the context of your problem but I felt like it would be easier to follow this way.
When in doubt, spell it out...
for (int i = 0; i < 7; i++)
{
if (i < 2) {
if (!i) { // technically, this is "if i == 1"
cout << x[i];
} else { // and this is "if i == 0"
cout <<y;
}
} else {
cout << x[1];
}
}
Simply go through the statement. Everything before a ? goes in an if, then just open a { until we see a :.
The operator is not structured as you write. Maybe it is clearer with parentheses:
cout << ((i < 2) ? (!i ? x [i] : y) : x[1]);
Some good analysis already of what the conditional means. Just wanted to contribute a couple suggestions:
consider writing or reordering such expressions such that the ? and : alternate,
consider breaking them on to multiple lines with indentation reflecting their processing.
Either or both of these should make it easier to keep track of what they do.
Consider:
i < 2 ? !i ? x[i] : y : x[1] # somewhat confusing...
Just indenting to reveal processing precedence:
i < 2 // if just put ? and : beneath related condition
? !i // then if
? x[i] // then
: y // else
: x[1] // else
Or to simplify while keeping one-liner concision, try:
i >= 2 ? x[1] : !i ? x[i] : y # equivalent but simpler to "grok" (see below)
Expression ordered to alternate ? and : work like a simple if / else if / else if / else chain, so you can process and eliminate possibilities steadily as you work your way through.
if (i >= 2)
(value is) x[1]
else if (!i)
x[i]
else
y;
I sometimes write alternating conditionals across lines too:
std::cout << (i >= 2 ? x[1] : // "if condition1 then value1 else
!i ? x[i] : // if condition2 then value2 else
y); // value3"
...or sometimes (depending on the line lengths and visual complexity) going the whole hog and lining up the : beneath ?...
std::cout << (i >= 2
? x[1]
: !i
? x[i]
: y);
As with many stylistic aspects of C++ source code, picking a nice layout is a bit of an art - but experimentation is a good way to get a feel for it.
Related
I am trying to efficiently deduct which conditions caused an if statement to be overlooked by the program without using a sequence of if statements to verify each variable's relative integrity individually.
Is this possible?
bool state = false;
int x = 0;
int y = 1;
int z = 3;
if(x == 0 && y == 1 && z == 2) {
// Do something...
state == true;
}
if(state == false) {
std::cout << "I did not execute the if statement because the following
conditions were not met: " << std::endl;
/*Find a way to make the program output that z != 3 stopped the
conditional from running without directly using if(z != 2)*/
}
You could introduce a counter as a "condition" between each of the conditions in the if to see when short-circuit evaluation of operator && prohibits execution of the latter conditions:
int nrOfConditionFailing = 1;
if(x == 0 &&
nrOfConditionFailing++ && y == 1 &&
nrOfConditionFailing++ && z == 2) {
state = true;
}
if (!state) {
cout << "failed due to condition nr " << nrOfConditionFailing << endl;
}
If you want to check all the conditions, you cannot do it in a single if-statement; Short-circuit evaluation of operator && will prevent the latter conditions to be even checked/evaluated if one of the former conditions evaluates to false.
However, you could do such a check as an expression that marks a bit in an unsigned int for each condition that is not met:
int x = 1;
int y = 1;
int z = 3;
unsigned int c1 = !(x == 0);
unsigned int c2 = !(y == 1);
unsigned int c3 = !(z == 2);
unsigned int failures =
(c1 << 0)
| (c2 << 1)
| (c3 << 2);
if (failures) {
for(int i=0; i<3; i++) {
if (failures & (1 << i)) {
cout << "condition " << (i+1) << " failed." << endl;
}
}
}
else {
cout << "no failures." << endl;
}
If this is something you want to display to the end user, and not just while debugging, as suggested in the comments, you can design a simple data structure for yourself. It would be a list / vector / array of entries, each of which contain a) a value to compare against, b) a value to test, and optionally c) a description of the test.
Then simply iterate the list, and check if equality holds for all of them. If not, you can stop the flow of the programme and print out the description.
To more directly answer your question: no, there is nothing in C++ that would allow you to examine the results of previous statements. The statements and operations you see in the source code get compiled and possibly won't even be trivially recognisable among the assembly instructions. Being able to check the results would mean the data has to be stored somewhere, which would be an incredible waste of memory and processing time. That is why you have to do this yourself.
Is this possible?
It is not possible in the way you were thinking about the problem. You can solve your problem instead by running each test individually, storing the result, and then identifying which of them were false:
std::vector<std::tuple<std::string,bool> > tests = {
{"x==0",x==0}, // test name as a string followed by the actual test
{"y==1",y==1},
{"z==2",z==2}
};
if(!all_of(tests.begin(),tests.end(),[](std::tuple<std::string,bool> &t) { return std::get<1>(t); }))
{
std::cout << "The following tests failed: ";
//remove all tests that passed
tests.erase(
std::remove_if(tests.begin(),tests.end(),[](std::tuple<std::string,bool> &t) { return std::get<1>(t); }),
tests.end());
//This will only print out the tests that failed
std::transform(tests.begin(),tests.end(),std::ostream_iterator<std::string>(std::cout, " "),[](std::tuple<std::string,bool> &t) { return std::get<0>(t); });
std::cout << std::endl;
} else {
//what to do if all tests were true
}
This will evaluate all tests (i.e., it won't use &&'s short-circuiting) and print all the ones that failed. You could likely wrap this into a class to make this more generalizable and user friendly.
The original code tests each variable individually. The && series is exactly equivalent to a series of if...else statements. There's nothing inefficient about one compared to the other, and there's nothing "clever" about using some tricky solution that achieves the same end result as straightforward code.
I might write:
char const *reason = nullptr;
if(x != 0)
reason = "x failed";
else if (y != 1)
reason = "y failed";
else if (z != 2 )
reason = "z failed";
if ( reason )
std::cout << reason << '\n';
else
{
// success code here...
}
I would typically do something like the following to determine if a series of validity checks worked and to mark which ones failed.
unsigned long ulFlags = 0;
int x = 0;
int y = 1;
int z = 3;
ulFlags |= (x == 0) : 0 ? 0x0001; // if bit set then condition failed.
ulFlags |= (y == 1) : 0 ? 0x0002; // if bit set then condition failed.
ulFlags |= (z == 2) : 0 ? 0x0004; // if bit set then condition failed.
if(ulFlags == 0) {
// Do something since all conditions are met and valid ...
} else {
std::cout << "I did not execute if statement because: " << std::hex << ulFlags << std::endl;
/* Find a way to make the program output that z != 3 stopped the
conditional from running without directly using if(z != 2) */
}
This is the same idea as some of the other answers, but with a template to simplify the syntax to use it. Stores all the individual checks in an std::array<bool, N> and one additional bool to be able to re-check the full statement without going through the individual results again.
No dynamic allocation is a plus as well.
#include <iostream>
#include <array>
#include <type_traits>
template <typename... N>
struct what_failed {
what_failed(N... n) : arr{n...}, status{(... && n)} {
static_assert(std::conjunction_v<std::is_same<N, bool>...>, "Only pass bools");
}
std::array<bool, sizeof...(N)> arr;
bool status;
operator bool() { return status; }
};
int main() {
auto check = what_failed(2 == 5, 2 < 5, 2 > 5, 1 == 1);
if (check)
std::cout << "Check: All true";
else {
std::cout << "Check: ";
for (auto c : check.arr)
std::cout << c << ' ';
}
return 0;
}
This requires c++17 due to fold expressions and template deduction in a constructor, but that can be worked around for c++11 with a couple of extra help-templates.
Suppose I have an if-statement like this:
if ( x < 0 || y < 0 || z < 0) {
cout << "Something is less than zero!";
}
Is there anyway to know which disjunct in the disjunction triggered the if-statement? Or is it necessary to write three separate if-statements to achieve that end?
EDIT: The goal would be to short-circuit the process. Obviously, writing any more code than three separate if-then statements (for this case) would not work for this goal.
Speaking of convoluted methods that would be stupid:
convoluted_and_stupid( x < 0, y < 0, z < 0 );
void convoluted_and_stupid( bool xlz, bool ylz, bool zyz )
{
if( xlz || ylz || zlz )
cout << "something is less than zero!\n";
if( xlz )
cout << "it is x!\n";
if( ylz )
cout << "it is y!\n";
if( zlz )
cout << "it is z!\n";
}
Just with that context the answer is no, you cannot really tell which of the three variables is < 0 without adding extra nested ifs for each of the variables. All you know is that at least one of them (but maybe more than one) is.
I'm doing the first project euler problem and I just did this
#include <iostream>
using namespace std;
int main(){
int threes =0;
int fives = 0;
int both = 0;
for (int i = 0; i < 10; i++){
if(i%3==0){
threes += i;
}
if(i%5==0){
fives += i;
}
if ( i % 5 == 0 && i % 3 == 0){
both += i;
}
}
cout << "threes = " << threes << endl;
cout << "fives = " << fives << endl;
cout << "both = " << both << endl;
cout << " threes + fives - both = " << endl;
int result = (threes + fives) - both;
cout << result<< endl;
return 0;
}
My professor recently corrected me for doing this in a different problem saying something about else statements,
but I don't understand WHY i have to add else in front of the next if. for what its worth I have another version with else if(i%5){ fives += .... }
and they both work and get me the right answer.
My question is whats inherently wrong with this way of thinking, is it stylistic or am I not thinking logically about something?
If it works, why use switch statements ever?
The only thing that I see wrong with your implementation is that in the case where the number is both a multiple of 3 and a multiple of 5 not only is the both variable incremented but the fives and threes variables are also incremented. Based on what the professor described I believe he wants you to use an else-if so that the both variable is the only one that is incremented when you pass in a number that is both a multiple of 3 and a multiple of 5.
The reason you get the correct answer both ways is because you are only going to 10 in the for loop, if you increase it to i <= 15 you will get fives and threes being 1 higher than I think he intended.
For example:
for( int i = 0; i < 10; i++ )
{
if( ( ( i % 3 ) == 0 ) && ( ( i % 5 ) == 0 ) )
{
both++;
}
else if( ( i % 3 ) == 0 )
{
threes++;
}
else if( ( i % 5 ) == 0 )
{
fives++;
}
}
The else branch in an if-else statement is only executed if the if branch is false. If you just have two if statements in a row, they'll both be executed, which can be a waste. In the below code, the else prevents the second computation from running if the first is satisfied.
if (expensive_computation1()) {
...
}
else if (expensive_computation2()) {
...
}
Additionally, it's clearer to humans reading the code whether both if statements should be allowed to run or whether only one should.
In this case, maybe you really want this:
if (i % 5 == 0 && i % 3 == 0) {
both += i;
} else if (i % 3 == 0) {
threes += i;
} else if (i % 5 == 0) {
fives += i;
}
(why you do += i instead of ++ I don't know but you didn't explain, so I just copied it)
In your code, threes and fives were incremented even if it would also increase both, which depending on your problem may not be what you want. If you do the if/else way I've just presented, only one of the three variables is increased.
Why use if-else instead of multiple if's?
if-else & if would achieve the same results but if-else achieves them in a performance enhanced way. with multiple if's every if condition will have to be checked. With if-else only one conditional check will have to be performed and the rest of the conditions just don't need to be checked at all.
This would not affect a small program like the one you have but it will sure have some impact in potentially expensive function being called repeatedly over and over again.
If it works, why use switch statements ever?
With nested if-else conditions the code is hard to read and understand. The switch-case construct helps to represent the conditions in a much easier to read & understand format.
To me it looks like stylistics. You can use some autoreformating tool that follows certain established stylistic look (K&R, ANSI, GNU, etc.)
For example astyle is such tool, http://astyle.sourceforge.net/ - just reformat your code with it, and you might have a happy professor.
I am trying to create a function to find the square root of a number. For debugging purposes, it has instructions to print current variable values. The function squareRoot accepts two arguments, x and t. It then declares and initializes n and s. n is the amount to add or subtract, halving every time it is used. s is what is thought to be the current square root. When running, I can clearly see that n is adjusting correctly. However, s stops changing when the first four digits are correct. I am using this call in main():
cout << squareRoot(1000, 10) << "\n";
This should print the square root of 1000 to the nearest tenth, but two weird things happen:
It doesn't stop at 31.6.
It stops at 4 digits!
My theory as to why it stops at four digits is this: In multiplying, s loses some of its precision. Is this true? If so, can you tell me how to correct it? If not, what is causing this and how can I correct that?
I tried to solve it already by using another variable, s1, which would be multiplied and checked. Then s would be incremented by n, and s1 synchronized with s. This didn't work, so I went back to the original code.
My code is as follows:
#include <iostream>
using namespace std;
double squareRoot(double x, int t) {
double s = 0;
double n = 0.1;
while ((s*s) <= x) {
s += n;
n *= 2;
cout << n << "\n" << s << "\n";
}
cout << "\n";
s -= n;
// Keep changing until margin of error is reached
while ((((s*s) - x) < (1/t)) || ((x - (s*s) < (1/t)))) {
// If too high, lower s
if ((s*s) <= x) {
s += n;
n /= 2;
cout << "Adding 1/2 of previous n\n";
}
// If too low, raise s
else if ((s*s) >= x) {
s -= n;
n /= 2;
cout << "Subtracting 1/2 of previous n\n";
}
cout << s << "\n" << n << "\n\n";
}
return s;
}
I am running Windows 7 64 bit, MSVC++ 2008 Express. Thank you in advance for all answers!
It converges to the correct square root, but cout only prints six significant digits by default: 31.xxxx.
Also notice that your termination check does not work because (1/t) will always evaluate to 0 for t>1. Use 1./t instead.
Unrelated, but your sqrt algorithm can be sped up by using an existing one, such as Newton's Method.
It goes like this:
double mySqrt(double x, unsigned long accuracy = 10)
{
if(x < 0.0)
return(-1.0);
double retval = 1.0;
for(unsigned long rep = 0; rep < accuracy; rep++)
retval = ((x / retval) + retval) / 2.0;
return(retval);
}
Newton's method also works for cube roots, etc.
For decimal exponents, look up the Binomial Theorem.
The reason loop isn't stopping is that loop condition isn't correct. You have
while ((current - target < precision) || (target - current < precision)) {
...
}
But either value current - target or value target - current will be <= 0. And 0 < precision. Thus you have equivalent of while (true) {...} loop.
You need something like
while (abs(current - target) > precision) {
...
}
(don't know exact function for getting absolute value in C++)
edit
Just noticed, hamster3null wrote about 1/t before me.
I was going over the C++ FAQ Lite online. I was browsing inlines again since I haven't found a use for them and wanted to know how the stopped the circular dependency as showed in this answer. I first tried to do the, "Why inlines are better than defines." example with the following code:
#define unsafe(i) \
( (i) >= 0 ? (i) : -(i) )
inline
int safe(int i)
{
return i >= 0 ? i : -(i);
}
int f();
int main(void)
{
int x(5);
int ans;
ans = unsafe(x++);
cout << ans << endl;
ans = unsafe(++x);
cout << ans << endl;
ans = safe(x++);
cout << ans << endl;
ans = safe(++x);
cout << ans << endl;
std::cin.get();
return 0;
}
EDIT:
Great. Got the typo out of the way. Not that I'm bitter that I don't find such errors or anything.
The output is now 6, 9, 9, 11.
However, even with pre-incrementation, shouldn't the first value result in 7?
If the macro is being called twice, then doesn't it go like this:
unsafe(x) // pre-incrementation doesn't modify the value when called.
unsafe(++x) // for all intents and purposes, the incrementation happens before the second call, so the ++x. This is for the first ans = unsafe(x++) if it's being called twice.
By the time we reach the second ans = unsafe(++x), shouldn't the x have been incremented twice? Once by the double call and once when the first double call was finished?
Instead of:
#define unsafe(i) \
( (i) >= 0 = (i) : -(i) )
I think you want:
#define unsafe(i) \
( (i) >= 0 ? (i) : -(i) )
In response to your edit:
After the first call to unsafe(x++), x is 7, even though the ans is 6. This is because you have the statement:
ans = ( (x++) >= 0 ? (x++) : -(x++) )
ans is assigned to the middle x++ after the left-most x++ is evaluated. As a result, ans == 6 but x == 7. The difference with unsafe(++x) is that ans is assigned to ++x, meaning the result is ans == x == 9.