I'm trying to write in visual c++ to convert a condition text to a simple "if" conditional expression with arithmetic operators, parentheses.
For exemple :
text : "(((a+b)>0)or(c==10))and(d!=e))" or "(a>b)xor(c==d)", etc...
we have normally in c++ style :
int a,b,c,d,e;
...
...
char text[]="(((a+b)>0)or(c==10))and(d!=e))";
if(text_to_if(text)) { .... }
...
...
letters a, b, c, d, e in text correspond with existing integer or float variables.
Please mind that C++ is not an interpreted language. You can not change code, including if statements, at runtime. If you want runtime code evaluation you could try JavaScript with its eval() function 1.
Further on you won't be able to retrieve variable names from your code (except for debugging purposes).
Related
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."
I would like to define an expression in C++ with macros and I am having quite a bit of trouble.
The expression is :
MATCH string WITH other_string
where string and other_string do not require " "
For example: MATCH r1 WITH string1 is the result i desire.
The purpose of this macro would be to check if r1 string matches with r2.
(I already have the code for the matching)
UPDATE
I would like to call MATCH hello WITH hi
in my main function
int main(){
MATCH hello WITH hi
}
and call my function from this macro to compare them. **Both hello and hi are unquoted arguments and must be treated as variable names
It is always dubious to use macros to make your code look like a different language. It is probably better to consider using a separate parser for your "meta-language" that generates the C++ code for you.
In this case, since C++ syntax requires some way to indicate the end of a statement (close braces or semi-colon) you are in kind of a jam.
Consider your example:
int main () { MATCH hello WITH hi }
Since hi is the last token before the end of main, there is no chance to fix-up the syntax to match C++ requirements.
You can't do what you want, so you have to do something different
If you really intend to embed this syntax into your C++ code, you need sentinel tokens to allow you to fix-up the syntax. My proposed syntax is:
int main () {
BEGIN_MATCHING
MATCH hello WITH hi
MATCH hello WITH hi
END_MATCHING
};
If this syntax is acceptable, then you can use the following macros.
#define BEGIN_MATCHING ((void)0
#define MATCH ); my_function(
#define WITH ,
#define END_MATCHING );
This will cause the code in the proposed syntax example to expand to:
int main () {
((void)0
); my_function( hello , hi
); my_function( hello , hi
);
}
Live Demo
Simply stringify your arguments with #, something like:
#define MATCH_WITH(str1, str2) MATCH #str1 WITH #str2
That way:
MATCH_WITH(testing, testing)
becomes:
MATCH "testing" WITH "testing"
I'm working on an old network engine and the type of package sent over the network is made up of 2 bytes.
This is more or less human readable form, for example "LO" stands for Login.
In the part that reads the data there is an enormous switch, like this:
short sh=(((int)ad.cData[p])<<8)+((int)ad.cData[p+1]);
switch(sh)
{
case CMD('M','D'):
..some code here
break
where CMD is a define:
#define CMD(a,b) ((a<<8)+b)
I know there are better ways but just to clean up a bit and also to be able to search for the tag (say "LO") more easily (and not search for different types of "'L','O'" or "'L' , 'O'" or the occasional "'L', 'O'" <- spaces make it hard to search) I tried to make a MACRO for the switch so I could use "LO" instead of the define but I just can't get it to compile.
So here is the question: how do you change the #define to a macro that I can use like this instead:
case CMD("MD"):
..some code here
break
It started out as a little subtask to make life a little bit easier but now I can't get it out of my head, thanks for any help!
Cheers!
[edit] The code works, it the world that's wrong! ie. Visual Studio 2010 has a bug concerning this. No wonder I cut my teeth on it.
Macro-based solution
A string-literal is really an instance of char const[N] where N is the length of the string, including the terminating null-byte. With this in mind you can easily access any character within the string-literal by using string-literal[idx] to specify that you'd like to read the character stored at offset idx.
#define CMD(str) ((str[0]<<8)+str[1])
CMD("LO") => (("LO"[0]<<8)+"LO"[1]) => (('L'<<8)+'0')
You should however keep in mind that there's nothing preventing your from using the above macro with a string which is shorter than that of length 2, meaning that you can run into undefined-behavior if you try to read an offset which is not actually valid.
RECOMMENDED: C++11, use a constexpr function
You could create a function usable in constant-expressions (and with that, in case-labels), with a parameter of reference to const char[3], which is the "real" type of your string-literal "FO".
constexpr short cmd (char const(&ref)[3]) {
return (ref[0]<<8) + ref[1];
}
int main () {
short data = ...;
switch (data) {
case cmd("LO"):
...
}
}
C++11 and user-defined literals
In C++11 we were granted the possibility to define user-defined literals. This will make your code far easier to maintain and interpret, as well as having it be safer to use:
#include <stdexcept>
constexpr short operator"" _cmd (char const * s, unsigned long len) {
return len != 2 ? throw std::invalid_argument ("") : ((s[0]<<8)+s[1]);
}
int main () {
short data = ...;
switch (data) {
case "LO"_cmd:
...
}
}
The value associated with a case-label must be yield through a constant-expression. It might look like the above might throw an exception during runtime, but since a case-label is constant-expression the compiler must be able to evaluate "LO"_cmd during translation.
If this is not possible, as in "FOO"_cmd, the compiler will issue a diagnostic saying that the code is ill-formed.
I am porting some code I have written in C++ to D. At one point I introduced a convenience macro, that contains an assignment. Like
#define so_convenient(x) value = some_func(x,#x)
So I am using macros to
access the actual symbol and its string and
make an assignment.
How do I achieve this in D?
You can use a mixin statement to convert a string into code at compile time e.g.:
mixin("value = 123;");
The following function will generate a string containing a statement which would be the closest equivalent of your C macro:
string soConvenient(alias A)()
{
return std.string.format(
'value = someFunc(%1$s, "%1$s");',
__traits(identifier, A));
}
Which you would then use like this:
mixin(soConvenient!x); // equivalent to 'so_convenient(x) in C
Roughly speaking in C++ there are:
operators (+, -, *, [], new, ...)
identifiers (names of classes, variables, functions,...)
const literals (10, 2.5, "100", ...)
some keywords (int, class, typename, mutable, ...)
brackets ({, }, <, >)
preprocessor (#, ## ...).
But what is the semicolon?
The semicolon is a punctuator, see 2.13 ยง1
The lexical representation of C++ programs includes a number of preprocessing tokens which are used in
the syntax of the preprocessor or are converted into tokens for operators and punctuators
It is part of the syntax and therein element of several statements. In EBNF:
<do-statement>
::= 'do' <statement> 'while' '(' <expression> ')' ';'
<goto-statement>
::= 'goto' <label> ';'
<for-statement>
::= 'for' '(' <for-initialization> ';' <for-control> ';' <for-iteration> ')' <statement>
<expression-statement>
::= <expression> ';'
<return-statement>
::= 'return' <expression> ';'
This list is not complete. Please see my comment.
The semicolon is a terminal, a token that terminates something. What exactly it terminates depends on the context.
Semicolon denotes sequential composition. It is also used to delineate declarations.
Semicolon is a statement terminator.
The semicolon isn't given a specific name in the C++ standard. It's simply a character that's used in certain grammar productions (and it just happens to be at the end of them quite often, so it 'terminates' those grammatical constructs). For example, a semicolon character is at the end of the following parts of the C++ grammar (not necessarily a complete list):
an expression-statement
a do/while iteration-statement
the various jump-statements
the simple-declaration
Note that in an expression-statement, the expression is optional. That's why a 'run' of semicolons, ;;;;, is valid in many (but not all) places where a single one is.
';'s are often used to delimit one bit of C++ source code, indicating it's intentionally separate from the following code. To see how it's useful, let's imagine we didn't use it:
For example:
#include <iostream>
int f() { std::cout << "f()\n"; }
int g() { std::cout << "g()\n"; }
int main(int argc)
{
std::cout << "message"
"\0\1\0\1\1"[argc] ? f() : g(); // final ';' needed to make this compile
// but imagine it's not there in this new
// semicolon-less C++ variant....
}
This (horrible) bit of code, called with no arguments such that argc is 1, prints:
ef()\n
Why not "messagef()\n"? That's what might be expected given first std::cout << "message", then "\0\1\0\1\1"[1] being '\1' - true in a boolean sense - suggests a call to f() printing f()\n?
Because... (drumroll please)... in C++ adjacent string literals are concatenated, so the program's parsed like this:
std::cout << "message\0\1\0\1\1"[argc] ? f() : g();
What this does is:
find the [argc/1] (second) character in "message\0\1\0\1\1", which is the first 'e'
send that 'e' to std::cout (printing it)
the ternary operator '?' triggers casting of std::cout to bool which produces true (because the printing presumably worked), so f() is called...!
Given this string literal concatenation is incredibly useful for specifying long strings
(and even shorter multi-line strings in a readable format), we certainly wouldn't want to assume that such strings shouldn't be concatenated. Consequently, if the semicolon's gone then the compiler must assume the concatenation is intended, even though visually the layout of the code above implies otherwise.
That's a convoluted example of how C++ code with and with-out ';'s changes meaning. I'm sure if I or other readers think on it for a few minutes we could come up with other - and simpler - examples.
Anyway, the ';' is necessary to inform the compiler that statement termination/separation is intended.
The semicolon lets the compiler know that it's reached the end of a command AFAIK.
The semicolon (;) is a command in C++. It tells the compiler that you're at the end of a command.
If I recall correctly, Kernighan and Ritchie called it punctuation.
Technically, it's just a token (or terminal, in compiler-speak), which
can occur in specific places in the grammar, with a specific semantics
in the language. The distinction between operators and other punctuation
is somewhat artificial, but useful in the context of C or C++, since
some tokens (,, = and :) can be either operators or punctuation,
depending on context, e.g.:
f( a, b ); // comma is punctuation
f( (a, b) ); // comma is operator
a = b; // = is assignment operator
int a = b; // = is punctuation
x = c ? a : b; // colon is operator
label: // colon is punctuation
In the case of the first two, the distinction is important, since a user
defined overload will only affect the operator, not punctuation.
It represents the end of a C++ statement.
For example,
int i=0;
i++;
In the above code there are two statements. The first is for declaring the variable and the second one is for incrementing the value of variable by one.