c++ cannot appear in a constant-expression| [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I select a range of values in a switch statement?
I've been getting some errors, and I've been searching for some time now, but I have no idea what is the cause of the errors. (I'm quite new to programming.)
Here are the errors I'm getting:
error: 'Essais' cannot appear in a constant-expression| (line 200)
warning: overflow in implicit constant conversion| (line 202)
I have case and cote:
char AfficherCote (int Essais)
{
char Cote;
switch (Essais)
{
(line200) case Essais<=20:
{
(line 202) Cote='Excellent';
return (Cote);
break;
}
case Essais<=40:
{
Cote='Très bon';
return (Cote);
break;
}
case Essais<=60:
{
Cote='Bon';
return (Cote);
break;
}
case Essais<=80:
{
Cote='Moyen';
return (Cote);
break;
}
case Essais<=100:
{
Cote='Muvais';
return (Cote);
break;
}
case Essais>=100:
{
Cote='Très mauvais';
return (Cote);
}
}
}

switch-case only works with constant values(*) (such as 3 or 'a'), not with ranges (such as <=100). You also must not include the variable name in the case statement. Correct syntax would be as follows:
switch (Essais)
{
case 1:
/* ... */
break;
case 2:
/* ... */
break;
default:
/* ... */
}
If you need range tests, use if instead of switch-case:
if (Essais <= 80)
return "Cote";
else if (Essais <= 100)
return "Muvais";
Also note that you can't use single quotation marks ' for strings. Use double quotation marks " instead, and use variables of type std::string (not char) to store strings.
(*) To be precise, the condition given in the case statements must be a constant expression of integral type, enumeration type, or class type convertible to integer or enumeration type (see §6.4.2/2 of the C++ Standard for details).

That's not how switch blocks work. You would need to do something like this instead:
switch (Essais) {
case 20:
...
case 40:
...
case 60:
...
/* etc, etc */
}
Each case compares the value in the switch statement against a specific constant value. If they are equal, that block is executed. In your code, the compiler is complaining because an expression like Essais<=20 is not a constant that it can evaluate at compile time.
Given what you are trying to do, an if ... else if ... else chain would be more appropriate. switch blocks can only test against specific values and can't handle testing ranges, which is what it appears you are trying to do.

Related

Index of the condition that was satisfied inside if-statement

if(command[i]=='H' or command[i]=='h' or command[i]=='C' or command[i]=='c'){
do something;
}
Once the logic flow goes inside this if-statement, I want to know what exactly command[i] was. Surely I can make individual comparisons again in the inside block and find out, but is there a more elegant way of knowing, say, the index of the condition that was satisfied?
If you use
if((myC=command[i]) =='H' ||
(myC=command[i]) =='h' ||
(myC=command[i]) =='C' ||
(myC=command[i]) =='c')
then the value of the successful expression will end up in myC, because evaluation in a chain of "or"s stops at the first true subexpression.
If you go one step further you can get a number value identifying the subexpression by index.
if(((myC=1), command[i]) =='H' ||
((myC=2), command[i]) =='h' ||
((myC=3), command[i]) =='C' ||
((myC=4), command[i]) =='c')
Same concept, the first successful subexpüression is the last to be evaluated and the , operator ensures that only the second part gets used for the comparison.
Another option is to assign a value. You could use switch, an if..else tower, or a function with return statements. Here is a version with function:
int classify( char command )
{
switch( command )
{
case 'H': return 1;
case 'h': return 2;
case 'C': return 3;
case 'c': return 4;
default : return 0;
}
}
void func(void)
{
int result = classify( command[i] );
if ( result )
{
// use result value here as appropriate
}
}
It would also be possible, in fact preferable, to use an enumerator instead of magic numbers.
Just do this -
if(command[i]=='H' or command[i]=='h' or command[i]=='C' or command[i]=='c'){
print command[i]; //use whatever command is appropriate for printing
do something;
}

Why does this switch Statement not return anything when switching compilers from G++ to MSVC? [duplicate]

This question already has answers here:
Function with missing return value, behavior at runtime
(4 answers)
Closed 5 years ago.
I was helping a friend with one of his C++ assignments and we found the following code snippet would throw exceptions in MSVC, but when compiling with G++, the exact same code would work fine. The exceptions were return because this function called getValue() wasn't returning anything.
string getValue(int value) {
ostringstream convert;
string rtnValue;
switch (value) {
case 11:
{
rtnValue = "J";
break;
}
case 12:
{
rtnValue = "Q";
break;
}
case 13:
{
rtnValue = "K";
break;
}
case 14:
{
rtnValue = "A";
break;
}
default:
{
//
// if the value is a a number, we assume it is 2..10
//
convert << value; // use a stream to convert the number
rtnValue = convert.str(); // into a string
if (value < 2 || value > 10)
{
rtnValue = "ERROR" + rtnValue + "ERROR";
}
}
return rtnValue;
}
}
This program turns integers into strings. For the numbers 11-14 it uses switch statement (I know this isn't the best implementation but it's an introductory class).
We found that this could easily be solved by adding another return statement at the end.
string getValue(int value) {
ostringstream convert;
string rtnValue;
switch (value) {
case 11:
{
rtnValue = "J";
break;
}
case 12:
{
rtnValue = "Q";
break;
}
case 13:
{
rtnValue = "K";
break;
}
case 14:
{
rtnValue = "A";
break;
}
default:
{
//
// if the value is a a number, we assume it is 2..10
//
convert << value; // use a stream to convert the number
rtnValue = convert.str(); // into a string
if (value < 2 || value > 10)
{
rtnValue = "ERROR" + rtnValue + "ERROR";
}
}
return rtnValue;
}
return rtnValue;
}
And this now fixes it for MSVC (and I assume G++ if I checked).
Why did that fix work? Does MSVC and G++ treat parentheses differently with respect to switch statements?
In the first example, the return rtnValue is in the wrong place, and will only ever work when the default case is hit.
In the second example, you have added the return rtnValue in the correct place (and the other can be safely removed).
As to why it worked on GCC and not on MSVC, I don't know, without the return being in the correct place, it's not valid C++ (not all paths have a return value), so you should have got a compilation error on any C++ compiler.
I would suggest the problem is actually the way the braces {} are being used, and your friend thought that the closing brace of the default case, actually closed the switch statement, but it doesn't.
Also, there is no need to have braces on any of the case statements. Braces CAN be used in this way to introduce scoping (for example, temporary variables for a particular case), but in your example, just leads to confusion.
this is the problem
default:
{
convert << value; // use a stream to convert the number
rtnValue = convert.str(); // into a string
if (value < 2 || value > 10)
{
rtnValue = "ERROR" + rtnValue + "ERROR";
}
}
return rtnValue;
}
your return statement is in the wrong block, i.e , switch block.
what happens is that, when a case is satisfied it breaks out of the switch that is why it didn't return anything (because it is now out of switch statement).
In order to fix it you have to move your return statement to out of the switch statement to the end of the function.
This correction will we equivalent to the second code that you have provided.
But even in the second code remove the inner return statement.
Return value
Your return statement in the first sample applies to the default case only since the execution of the switch block ends with a break statement in every other case.
In a non-default case, you leave the return value of your function uninitialized. MSVC does warn about that while debugging (see https://learn.microsoft.com/en-us/visualstudio/debugger/how-to-use-native-run-time-checks for details) but GCC does not. This problem might be detected during compile time but you cannot rely on that.
The return statement added to the second sample is correct. You can remove the original one which becomes superfluous.
Braces
Notice that the braces inside the switch block are not necessary and introduce confusion here. They would be only useful if you created a local variable just to be used in a single case. Anyway, the braces should be indented more than the braces of the switch block. This part
}
return rtnValue;
}
demonstrates the misleading indentation clearly. The indentation used in the second example is one of the good solutions to this problem.

How to use case condition in switch as variable in c++? [duplicate]

This question already has answers here:
C++ Switch won't compile with externally defined variable used as case
(8 answers)
Closed 6 years ago.
Here x, y, z are integers but those are not known at start. During the running it will calculate the values of x, y, z. I want to use those values as case condition.
Is there any way to use those values in switch?
Instead of switch if I use if else loop, ho
id = 1;
switch(id){
case x:
//call some function
break;
case y:
//call some different function
break;
default:
//error
break;
}
No, the case labels need to be compile-time integral constants.
You will need to use conditional statements instead:
if (id == x) {
// ...
} else if (id == y) {
// ...
} else if (id == z) {
// ...
} else {
// "default case"
}
Consider also that x, y and z may not all be distinct, so the order of the statements matters. (But the order also matters for case labels in a switch if you fall through any of them.)
What you want is not supported (as pointed out by other answers). However, worse, it is not sensible and hence cannot be emulated in any way. This is because the cases in a switch are unique and their order insignificant (except in case of fall-through), so
switch(enum_object) {
case A: return foo<A>();
case B: return foo<B>();
default: return foo<C>();
}
and
switch(enum_object) {
default: return foo<C>();
case B: return foo<B>();
case A: return foo<A>();
}
gives the same code, but
if(id == run_time_value_A)
return foo<A>();
if(id == run_time_value_B)
return foo<B>();
return foo<C>();
is not the same as, say,
if(id == run_time_value_B)
return foo<B>();
if(id == run_time_value_A)
return foo<A>();
return foo<C>();
they differ if run_time_value_B==run_time_value_A.
As pointed out by n.m, Kerrek SB, and this SO answer, case labels need to be compile-time integral constants.
The answer of Kerrek SB shows the immediate and intuitive if - else if-cascade solution.
However, if you'd also like to make use of the break-functionality in switch-statements, then the following if - if - cascade as general pattern would apply:
bool isBreak = false;
if (id==x) {
...
isBreak = true;
}
if (!isBreak && id==y) {
...
}
if (!isBreak) {
...
}
Note that with this pattern you can express - in contrast to switch- also situations where more than one of the case-statements (denoted as ifs) match, as, e.g. when x == y.

Does case-switch work like this?

I came across a case-switch piece of code today and was a bit surprised to see how it worked. The code was:
switch (blah)
{
case a:
break;
case b:
break;
case c:
case d:
case e:
{
/* code here */
}
break;
default :
return;
}
To my surprise in the scenario where the variable was c, the path went inside the "code here" segment. I agree there is no break at the end of the c part of the case switch, but I would have imagined it to go through default instead. When you land at a case blah: line, doesn't it check if your current value matches the particular case and only then let you in the specific segment? Otherwise what's the point of having a case?
This is called case fall-through, and is a desirable behavior. It allows you to share code between cases.
An example of how to use case fall-through behavior:
switch(blah)
{
case a:
function1();
case b:
function2();
case c:
function3();
break;
default:
break;
}
If you enter the switch when blah == a, then you will execute function1(), function2(), and function3().
If you don't want to have this behavior, you can opt out of it by including break statements.
switch(blah)
{
case a:
function1();
break;
case b:
function2();
break;
case c:
function3();
break;
default:
break;
}
The way a switch statement works is that it will (more or less) execute a goto to jump to your case label, and keep running from that point. When the execution hits a break, it leaves the switch block.
That is the correct behavior, and it is referred to as "falling through". This lets you have multiple cases handled by the same code. In advanced situations, you may want to perform some code in one case, then fall through to another case.
Contrived example:
switch(command)
{
case CMD_SAVEAS:
{
this->PromptForFilename();
} // DO NOT BREAK, we still want to save
case CMD_SAVE:
{
this->Save();
} break;
case CMD_CLOSE:
{
this->Close();
} break;
default:
break;
}
This is called a fall-through.
It is exactly doing what you are seeing: several cases is going to execute same piece of code.
It is also convenient in doing extra processing for certain case, and some shared logic:
// psuedo code:
void stopServer() {
switch (serverStatus)
case STARTING:
{
extraCleanUpForStartingServer();
// fall-thru
}
case STARTED:
{
deallocateResources();
serverStatus = STOPPED;
break;
}
case STOPPING:
case STOPPED:
default:
// ignored
break;
}
This is a typical use of fall-through in switch-case. In case of STARTING and STARTED, we need to do deallocateResources and change the status to STOPPED, but STARTING need some extra cleanup. By the above way, you can clearly present the 'common logic' plus extra logic in STARTING.
STOPPED, STOPPING and default are similar, all of them fall thru to default logic (which is ignoring).
It is not always a good way to code like this but if it is well used it can present the logic better.
Luckily for us, C++ doesn't depend on your imagination :-)
Think of the switch labels as "goto" labels, and the switch(blah) simply "goes to" the corresponding label, and then the code just flows from there.
Actually the switch statement works the way you observed. It is designed so that you can combine several cases together until a break is encountered and it acts something like a sieve.
Here is a real-world example from one of my projects:
struct keystore_entry *new_keystore(p_rsd_t rsd, enum keystore_entry_type type, const void *value, size_t size) {
struct keystore_entry *e;
e = rsd_malloc(rsd, sizeof(struct keystore_entry));
if ( !e )
return NULL;
e->type = type;
switch (e->type) {
case KE_DOUBLE:
memcpy(&e->dblval, value, sizeof(double));
break;
case KE_INTEGER:
memcpy(&e->intval, value, sizeof(int));
break;
/* NOTICE HERE */
case KE_STRING:
if ( size == 0 ) {
/* calculate the size if it's zero */
size = strlen((const char *)value);
}
case KE_VOIDPTR:
e->ptr = rsd_malloc(rsd, size);
e->size = size;
memcpy(e->ptr, value, size);
break;
/* TO HERE */
default:
return NULL;
}
return e;
}
The code for KE_STRING and KE_VOIDPTR cases is identical except for the calculation of size in case of string.

Is It Possible To Do The Following In A Switch Statement - C++?

I am a programming student in my second OOP class, and I have a simple question that I have not been able to find the answer to on the internet, if it's out there, I apologize.
My question is this:
Is it possible have Boolean conditions in switch statements?
Example:
switch(userInputtedInt)
{
case >= someNum && <= someOtherNum
break;
// Is this possible?
}
No this is not possible in C++. Switch statements only support integers and characters (they will be replaced by their ASCII values) for matches. If you need a complex boolean condition then you should use an if / else block
As others have said you can't implement this directly as you are trying to do because C++ syntax doesn't allow it. But you can do this:
switch( userInputtedInt )
{
// case 0-3 inclusve
case 0 :
case 1 :
case 2 :
case 3 :
// do something for cases 0, 1, 2 & 3
break;
case 4 :
case 5 :
// do something for cases 4 & 5
break;
}
No, this is usually the purview of the if statement:
if ((userInputtedInt >= someNum) && (userInputtedInt <= someOtherNum)) { ... }
Of course, you can incorporate that into a switch statement:
switch (x) {
case 1:
// handle 1
break;
default:
if ((x >= 2) && (x <= 20)) { ... }
}
It's not possible directly -- a C or C++ switch statement requires that each case is a constant, not a Boolean expression. If you have evenly distributed ranges, you can often get the same effect using integer division though. e.g. if you have inputs from 1 to 100, and want to work with 90-100 as one group, 80-89 as another group, and so on, you can divide your input by 10, and each result will represent a range.
Or you can perhaps do this
switch((userInputtedInt >= someNum) && (userInputtedInt <= someOtherNum))
{
case true:
//do something
break;
case false:
//something else
break;
}
But that's just down-right terrible programming that could be handled with if-else statements.
This isn't possible. The closest you can some, if the values are reasonably close together is
switch(userInputtedInt)
{
case someNum:
case someNum+1:
// ...
case someOtherNum:
break;
}
C++ does not support that.
However, if you are not concerned with writing portable, standard code some compilers support this extended syntax:
switch(userInputtedInt)
{
case someNum...someOtherNum:
break;
}
Those values must be constant.
If you fancy the preprocessor you could write some kind of macro that auto-expands to the number of case statement required. However that would require a lengthly file with pretty much all case statements (ex: #define CASE0 case 0: #define CASE1 case 1: ...)
You shouldn't go there but it's fun to do...for fun! ;)
The standard does not allow for this:
6.4.2 The switch statement [stmt.switch]
[...] Any statement within the switch statement can be labeled with one or more case labels as follows:
case constant-expression :
where the constant-expression shall be an integral constant expression (5.19).
Some C++ compilers still support range notations today, 8 years after this question was originally asked. It surprised me.
I learned Pascal in 2012, Pascal do have range notations.
So it encouraged me to try the similar syntax in C++, then it worked unexpectedly fabulously.
The compiler on my laptop is g++ (GCC) 6.4.0 (from Cygwin project) std=c++17
There is a working example, which I wrote in hurry. repl.it
In addition, the source code is attached as follow:
#include <iostream>
using namespace std;
#define ok(x) cout << "It works in range(" << x << ")" << endl
#define awry cout << "It does\'t work." << endl
int main() {
/*bool a, b, c, d, e, f, g;
switch(true) {
case (a): break; These does not work any more...
case (b and c): break;
}*/
char ch1 = 'b';
switch(ch1) {
case 'a' ... 'f': ok("a..f"); break;
case 'g' ... 'z': ok("g..z"); break;
default: awry;
}
int int1 = 10;
switch(int1) {
case 1 ... 10: ok("1..10"); break;
case 11 ... 20: ok("11..20"); break;
default: awry;
}
return 0;
}