Two strings between brackets separated by a comma in C++ [duplicate] - c++

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.

Related

Replacing '(' with '-' in C++ [duplicate]

This question already has answers here:
How to replace all occurrences of a character in string?
(17 answers)
Closed 4 years ago.
I've tried:
versionString = versionString.replace(versionString.begin(), versionString.end(), '(' , '-' );
The result is: "--------------". Basically replacing all the characters. What is that?
versionString is a basic string.
If you look at e.g. this std::string::replace reference you will see that there's no overload that takes the arguments you pass. Something the compiler really should warn you about.
The closes one is number 6:
basic_string& replace( const_iterator first, const_iterator last,
size_type count2, CharT ch );
which replaces the range with count2 copies of ch.
That is, you replace your string with '(' number of dashes. With ASCII that '(' will be converted to the integer 40 (it's this conversion the compiler should have warned you about).
One solution is to repeatedly find the character you want to replace, and replace only that single character.
A much simpler solution is to use the standard algorithm function std::replace:
std::replace(begin(versionString), end(versionString), '(', '-');

Multiple string replaces in one line

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.

cin and continue separated by comma in a single line

Why does following code doesn't compile?
for(int i = 0; i < 10; i++){
if(i == 5) i = 7, continue;
}
Comma can be used as a separator as well as operator. And if it acts like operator, it evaluates both the expressions and returns the last. I understand that it is not acting as operator here since continue is not an operand. But why is it not acting as separator of two statements.
It shows the following error-
error: expected primary-expression before ‘continue’
if(i == 5) i = 7, continue;
The comma token can act as a separator. But those contexts are explicitly enumerated. It's a separator for declarations, function/template parameters, function call/template instantiation arguments, and in initializers like {1, 2}. It is not a separator for statements, that's the role of a semi-colon.
The comma operator separates expressions. And a continue statement is not an expression.
Don't be a "clever" coder. Write clear code, understandable at a glance. Put the assignment in its own statement and wrap the two statements in one block scope for the if to execute.

What is the use of "," in while loop condition c++? [duplicate]

This question already has answers here:
comma separated expression in while loop in C
(5 answers)
How does the Comma Operator work
(9 answers)
Closed 5 years ago.
string command;
string bookName;
while (cin >> command, command != "END")
{...}
Here in while loop's condition, there is a comma.
I know that multiple conditions can be added using && or ||.
But why use ,?
Is there any certain benefits? Can you please explain the usage and syntax?
It's the comma operator, also known as the "evaluate and forget" operator. The effect of a, b is:
Evaluate a, including any side effects
Discard its value (i.e. do nothing with it)
Evaluate b
Use the result of b as the result of the entire expression a, b
The author of the loop wanted to express the following:
Read command from cin, and then enter the loop body unless command is equal to "END"
However, they would have been better off using && instead of , here, because cin >> command can fail (i.e. if the end of input is reached before the word END is found). In such case, the condition with , will not do what was intended (it will likely loop forever, as command will never receive the value END), while the condition with && would do the right thing (terminate).

Shorthand If/Else statement with two statements inside IF

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."