Sorry, I couldn't find a better fitting title, feel free to edit the title if you find a more suthing one. Here is my question, I know I can create a small version of IF/ELSE statement like this:
(condiction) ? numFound = true : numFound = false;
but, is there a way of having two statements inside the first condition, ex.
(condition) ? numFound = true, break: numFound = false;
normal version of if/else statement I want to write
if (condition)
{
numFound = true;
break;
}
else
numFound = false;
Sorry for the noob question, and thanks for the help!
In short, it isn't possible. The Ternary operator requires the operands to evaluate to a value, and code blocks don't. Comma expressions don't work, because they will set the value to the last one executed- break doesn't evaluate to a value. Additionally, break isn't a function to be evaluated, it's a statement.
The advice is to not use conditionals/ternary operators when you are doing things more complex than their base use- they're harder to parse by humans and any decent compiler will compile x = condition ? this:that the same as if(condition){x=this}else{x=that} (or optimize both to the same assembly).
No you cannot do that. The "small version" of the if/else is called the conditional operator. It is the only operator in c++ taking three operands and commonly also simply called "the ternary operator". From here:
Exp1 ? Exp2 : Exp3;
where Exp1, Exp2, and Exp3 are expressions. Notice the use and
placement of the colon. The value of a ? expression is determined like
this: Exp1 is evaluated. If it is true, then Exp2 is evaluated and
becomes the value of the entire ? expression. If Exp1 is false, then
Exp3 is evaluated and its value becomes the value of the expression.
And for some clarification what is an expression see this question. break is not an expression, but a statement, hence you cannot use it inside a ternary.
Anyhow I would advise you not to hide the break within more stuff in a single line. In a loop a break is something extremely important and it makes sense to make it stand out from the "normal" buissness that happens inside the loop. If I dont immediately see a break (or a return) in a loop then I assume that it does its full iteration. Overlooking a break can cause mayor confusion and misunderstanding.
You could use comma expressions. A comma expression of the form (expr1, expr2) evaluates expr1 (and ignores the value to which it evaluates) and then expr2, which's value is then the result of the overall comma expression.
int main(int argc, char* argv[]) {
bool r = (argc==1) ? (printf("no parameters"),true) : (printf("parameters"),false);
return 0;
}
My friend you're in luck. Use comma operator:
(condition) ? numFound=true, x=1, y=2: numFound = false;
Of course if you're specific to break; it won't work.
Your break doesn't work here but the task itself works. But be careful! Strange things can happen. See these examples:
0?printf("One"),printf("One"):printf("Two"),printf("Two"); /* TwoTwo */
0?(printf("One"),printf("One")):(printf("Two"),printf("Two")); /* TwoTwo */
1?printf("One"),printf("One"):printf("Two"),printf("Two"); /* OneOneTwo (!) */
1?(printf("One"),printf("One")):(printf("Two"),printf("Two")); /* OneOne */
This happens because of the comma operator which evaluates an expression fomr left to right and returns the value of the second statement for the whole expression.
The next step is to check the binding precedence of (), ?: and ,. We find here that the opertators are ordered from strong to weak like
()
?:
,
Therefore the third example I posted is evaluated as follows:
1?printf("One"),printf("One"):printf("Two"),printf("Two")
-> (1?printf("One"),printf("One"):printf("Two")),printf("Two")
-> (printf("One"),printf("One")),printf("Two")
-> OneOneTwo
I do really not recommend using the so called ternary operator in more complicated cases. Stick to clear code. You know "Code is read more than it is written."
Related
I have a sql statement and for debugging I want to print it. The statement contains placeholders and I want to fill the placeholders in one instruction line before I print. Is this valid or UB?
std::string query("SELECT A, B FROM C WHERE D = ? and E = ?;");
std::cout << query.replace(query.find("?"), 1, "123").replace(query.find("?"), 1, "234") << std::endl;
Is the order of the instructions
Find position of first question mark
Replace first string in query
Find position of second question mark after first replacement
Replace second string in query
guaranteed or is it possible that both find operations can be called before both replace operations like
Find position of first question mark
Find position of second question mark before first replacement
Replace first string in query
Replace second string in query
I'm asking because:
Order of evaluation of the operands of almost all C++ operators
(including the order of evaluation of function arguments in a
function-call expression and the order of evaluation of the
subexpressions within any expression) is unspecified. The compiler can
evaluate operands in any order, and may choose another order when the
same expression is evaluated again.
EDIT:
It's not possible to use third party dependencies in this project.
In query.replace(query.find("?"), 1, "123").replace(query.find("?"), 1, "234")
query.find("?") is un-sequenced from each other.
so result is unpredictable between possible sequences.
I cannot find anything in the rules of order of evaluation that strictly specifies the ordering of the function arguments of chained functions. That is to say that in your case you can know that:
The first replace is sequenced before the second one, because the second one operates on its return value
Each find call is sequenced before the replace that uses its return value as an argument
But what you want is for the first replace to be sequenced before the second find and there is no such guarantee. For reference, see the rules here.
You can use boost::algorithm::replace_first multiple times:
#include <boost/algorithm/string/replace.hpp>
#include <iostream>
#include <string>
int main() {
std::string query("SELECT A, B FROM C WHERE D = ? and E = ?;");
for(auto replacement : {"123", "1"})
boost::algorithm::replace_first(query, "?", replacement);
std::cout << query << '\n';
}
Note that this simple string replacement won't work for replacement strings that need quoting.
I am currently learning C++ from 'Problem solving with C++' (9th, W. Savitch). The book shows an example of a while loop. The while loop looks as follows.
while (ans = = 'Y' || ans = = 'y')
{
//compound statement
}
ans is of type char.
The boolean expression appears to be trying to use the equality operator, and in the context of the //compound statement this makes sense. However, I always thought whitespace was illegal within the equality operator. i.e == is legal, but = = is illegal.
When I copy the code and compile it, my compiler throws the error 'expected expression' when it hits = = as if I am trying to assign an expression to a variable. I am almost certain this is a typo within the book. However, just in case the book is trying to throw a curveball I thought I would ask...
Many thanks!
Is whitespace between the two ='s in an equality operator legal in C++?
No. = = is two = tokens. == is one == token. You can't use the former when you mean the latter.
In the following SPARQL query, I'm not sure how to use if to bind one of two strings to the variable ?result. I heard that there are concepts of “in scope” and “out of scope,” but I don't really see the difference. I've also tried putting the if clause in the select line, but it didn't work either. How can I fix this query to bind ?result to one of the two strings based on the condition?
SELECT ?result
WHERE{
?chain rdf:type rdfs:Property .
?chain rdfs:domain <http://www.vs.cs.hs-rm.de/ontostor/SVC#MDiskGroup> .
?chain rdfs:range <http://www.vs.cs.hs-rm.de/ontostor/SVC#IOgroup> .
?this ?chain ?arg .
?arg io:id ?var .
IF(?var = "0"^^xsd:integer,
BIND(" *"^^xsd:string AS ?result),
BIND(""^^xsd:string AS ?result)) .
}
The if operator in SPARQL isn't a statement as it sometimes is in a programming language, but rather is an "function form" for creating an expression (with special evaluation semantics). The value of if(test,a,b) is a if test is true, and b if test is false. As the documentation says:
17.4.1.2 IF
rdfTerm IF (expression1, expression2, expression3)
The IF function form evaluates the first argument, interprets it as a
effective boolean value, then returns the value of expression2 if the
EBV is true, otherwise it returns the value of expression3. Only one
of expression2 and expression3 is evaluated. If evaluating the first
argument raises an error, then an error is raised for the evaluation
of the IF expression.
Examples: Suppose ?x = 2, ?z = 0 and ?y is not bound in some query
solution:
IF(?x = 2, "yes", "no") returns "yes"
IF(bound(?y), "yes", "no") returns "no"
IF(?x=2, "yes", 1/?z) returns "yes", the expression 1/?z is not evaluated
IF(?x=1, "yes", 1/?z) raises an error
IF("2" > 1, "yes", "no") raises an error
So, if isn't a statement like it might be in a programming language, but it's simply a function (though lazily evaluated) that takes three arguments and returns a value. SPARQL is a query language, and doesn't have statements that get executed; it's a query language for matching patterns in a graph and binding variables to values. So if is a function, and it just so happens that if the first argument is true, then it returns the second argument, otherwise it returns the third. In general, you'd bind the value of a function to a variable with
bind( function(args...) as ?variable )
and this case is no different. You'd call the if function and bind its result to a variable with
bind( if(condition,then,else) as ?result )
In your case, this means that you would use the following query. I've added some newlines to help the readability, but they're not necessary. Integers in a SPARQL query are shorthand for a literal with type xsd:integer, so I've also used (thanks to RobV's comment) 0 instead of "0"^^xsd:integer. (See 2.3.2 Matching Literals with Numeric Types.)
bind(if(?var = 0,
" *"^^xsd:string,
""^^xsd:string )
as ?result)
If we actually want to shorten this even more, then we can use xsd:string as a constructor, and do (see 17.5 XPath Constructor Functions):
bind(xsd:string(if(?var = 0," *", "")) as ?result)
This might seem a little bit odd at first if you're used to doing things like
String result;
if ( var == 0 ) {
result = "case 1";
}
else {
result = "case 2";
}
but many language actually provide a ternary operator that lets you do the much shorter
String result = (var == 0) ? "case 1" : "case 2";
instead. This is the functionality you're getting with SPARQL.
This question already has answers here:
How does the Comma Operator work
(9 answers)
Closed 9 months ago.
I came across unexpected (to me at least) C++ behavior today, shown by the following snippit:
#include <iostream>
int main()
{
std::cout << ("1", "2") << std::endl;
return 0;
}
Output:
2
This works with any number of strings between the parentheses. Tested on the visual studio 2010 compiler as well as on codepad.
I'm wondering why this compiles in the first place, what is the use of this 'feature'?
Ahh, this is the comma operator. When you use a comma and two (or more) expressions, what happens is that all expressions are executed, and the result as a whole is the result of the last expression. That is why you get "2" as a result of this. See here for a bigger explanation.
It's called the comma operator: in an expression x, y, the compiler
first evaluates x (including all side effects), then y; the results
of the expression are the results of y.
In the expression you cite, it has absolutely no use; the first string
is simply ignored. If the first expression has side effects, however,
it could be useful. (Mostly for obfuscation, in my opinion, and it's
best avoided.)
Note too that this only works when the comma is an operator. If it can
be anything else (e.g. punctuation separating the arguments of a
function), it is. So:
f( 1, 2 ); // Call f with two arguments, 1 and 2
f( (1, 2) ); // Call f with one argument, 2
(See. I told you it was good for obfuscation.)
Comma operator ( , )
The comma operator (,) is used to separate two or more expressions that are included where only one expression is expected. When the set of expressions has to be evaluated for a value, only the rightmost expression is considered.
For example, the following code:
a = (b=3, b+2);
Ref:http://www.cplusplus.com/doc/tutorial/operators/
The result of the comma (",") is the right subexpression.
I use it in loops over stl containers:
for( list<int>::iterator = mylist.begin(), it_end = mylist.end(); it != it_end; ++it )
...
The comma operator evaluates the expressions on both sides of the comma, but returns the result of the second.
everyone, I have some question about C++, what do You actually prefer to use
int* var = 0;
if(!var)...//1)
or
if(var == 0)..//2)
what are the pros and cons? thanks in advance
I prefer if (!var), because then you cannot accidentally assign to var, and you do not have to pick between 0 and NULL.
I've always been taught to use if (!var), and it seems that all the idiomatic C(++) I've ever read follows this. This has a few nice semantics:
There's no accidental assignment
You're testing the existence of something (ie. if it's NULL). Hence, you can read the statement as "If var does not exist" or "If var is not set"
Maps closely to what you'd idiomatically write if var was a boolean (bools aren't available in C, but people still mimic their use)
Similar to the previous point, it maps closely to predicate function calls, ie. if (!isEmpty(nodeptr)) { .. }
Mostly personal preference. Some will advise that the first is preferred because it becomes impossible to accidentally assign instead of compare. But by that same token, if you make a habit of putting the rvalue on the left of the comparison, the compiler will catch you when you blow it:
if( 0 == var )
...which is certainly true. I simply find if( !var ) to be a little more expressive, and less typing.
They will both evaluate the same, so there's no runtime difference. The most important thing is that you pick one and stick with it. Don't mix one with the other.
Either one is good, though I personally prefer 2 - or something like it.
Makes more sense to me to read:
if ( ptr != NULL )
than
if ( ptr )
The second I may confuse for just being a boolean to look at, but the first I'd be able to tell immediately that it's a pointer.
Either way, I think it's important to pick one and stick with that for consistency, though - rather than having it done in different ways throughout your product.
A few years has passed...
The C++11 standard introduced nullptr to check for null pointers and it should be used as it ensure that the comparison is actually done on a pointer.
So the most robust check would be to do:
if(myPtr != nullptr)
The problem with !var is that it's valid if var is a boolean or a numerical values (int, byte etc...) it will test if they are equal 0 or not.
While if you use nullptr, you are sure that you are checking a pointer not any other type:
For example:
int valA = 0;
int *ptrA = &valA;
if(!valA) // No compile error
if(!*ptrA) // No compile error
if(!ptrA) // No compile error
if(valA != nullptr) // Compile error, valA is not a pointer
if(*ptrA != nullptr) // Compile error, *ptrA is not a pointer
if(ptrA != nullptr) // No compile error
So, it's pretty easy to make a mistake when manipulating pointer to an int as in your example, that's why nullptr should be used.
I would prefer option 3:
if(not var)
{
}
The new (well since 1998) operator keywords for C++ can make code easier to read sometimes.
Strangely enough, they seem to be very unknown. There seem to be more people who know what trigraphs are (thank you IOCCC!), than people who know what operator keywords are. Operator keywords have a similar reason to exist: they allow to program in C++ even if the keyboard does not provide all ANSII characters. But in contradiction to trigraphs, operator keywords make code more readable instead of obfuscating it.
DON'T use NULL, use 0.
Strictly speaking, pointer is not bool, so use '==' and '!=' operators.
NEVER use 'if ( ptr == 0 )', use 'if ( 0 == ptr )' instead.
DON'T use C-pointers, use smart_ptr instead. :-)
According to the High Integrity C++ coding Standard Manual: for comparison between constants and variables you should put the constant on the left side to prevent an assignment instead of an equality comparison, for example:
Avoid:
if(var == 10) {...}
Prefer
if(10 == var) {...}
Particularly in your case I prefer if(0 == var) because it is clear that you are comparing the pointer to be null (0). Because the ! operator can be overloaded then it could have other meanings depending on what your pointer is pointing to: if( !(*var) ) {...}.