Group multiple cases together in the switch statement - c++

Here below is my code for a switch statement:
switch(pin)
{
case 1:
break;
case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11:
case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20:
case 21: case 22: case 23: case 24:case 25:case 26:case 27:case 28:case 29: case 30: case 31:
case 32: case 33: case 34: case 35:
dataOut[pin-2] = 1;
DAQmxWriteDigitalLines(taskHandleOut,1,1,10.0,DAQmx_Val_GroupByChannel,dataOut,NULL,NULL);
break;
default:
break;
In the above, the case 2-35 are to be grouped together for which, I mean, when pin is equal to 2-35, the specific task is to be performed.
I want to know if the above code is valid or not. I haven't seen case grouping in switch statements. Any weblinks for similar multiple case grouping is appreciated. Maybe there is some better way to do so instead of grouping multiple cases.

While your case may be better served with an if-check if (pin >= 2 && pin <= 35), it is common to group case labels like that.
gcc/clang/tinycc even have syntactic sugar for it:
switch(pin){
case 2 ... 35: /*nonstandard GNU extension; note well the whitespace*/
};

Yes, this is absolutely fine, although I'd write
if (pin >= 2 && pin <= 35){
dataOut[pin-2] = 1;
DAQmxWriteDigitalLines( ...
}
if I were you. If you are using gcc exclusively as your compiler, then you could also use case ranges.

It is valid. It's called fallthrough, and it's the reason you have to put breaks to separate cases. That is, if you don't break, the instructions following your case will get executed anyway. Like in
int i = 1;
switch(i) {
case 1:
cout<<1<<endl;
case 2:
cout<<"nope!\n";
}
This will output
1
nope!
because there's no break before case 2:.
But in your case you may as well do
if (pin >= 2 && pin <= 35) {
dataOut[pin-2] = 1;
DAQmxWriteDigitalLines(taskHandleOut,1,1,10.0,DAQmx_Val_GroupByChannel,dataOut,NULL,NULL);
}

Yes, you can. C++ provides fall-through for switch case statements. So unless you provide a break; at the end of the case:, control falls-through to the next case allowing you to do exactly what you describe with a switch. Some compilers allow short-hand for describing multiple case statements at once, but for portable C++, simply providing each case without a break; is all you need, e.g.
switch(pin)
{
case 1:
break;
case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9:
case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17:
case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25:
case 26: case 27: case 28: case 29: case 30: case 31: case 32: case 33:
case 34: case 35:
/* do what you need with pins 2 - 35 */
dataOut[pin-2] = 1;
DAQmxWriteDigitalLines (taskHandleOut, 1, 1, 10. 0,
DAQmx_Val_GroupByChannel, dataOut, NULL, NULL);
break;
default:
break;
}
Now any case 2-35 will execute your desired statements:
dataOut[pin-2] = 1;
DAQmxWriteDigitalLines (taskHandleOut, 1, 1, 10. 0,
DAQmx_Val_GroupByChannel, dataOut, NULL, NULL);

It's valid code but I would rather use default in your case especially when you have planned to use other numbers for other cases. default will be used like else in an if/else statement. Here default would be called for every number you don't have an case specified.

Related

Converting two number digit into words

I have written a program in c++ to convert number into words. The output for 0-19 is fine but it is giving wrong output for numbers between 20-99.
//This program converts numbers from 0-99 into words
#include<iostream>
using namespace std;
int main()
{
int number,unit,ten;
cout<<"Please enter any number between 0-99: ";
cin >>number;
ten=number/10;
unit=number%10;
if(number<0 | number>99)
cout<<"Number is out of range";
if(number>=11 & number <=19)
{
if(number==11) cout<<"eleven";
if(number==12) cout<<"twelve";
if(number==13) cout<<"thirteen";
if(number==14) cout<<"fourteen";
if(number==15) cout<<"fifteen";
if(number==16) cout<<"sixteen";
if(number==17) cout<<"seventeen";
if(number==18) cout<<"eighteen";
if(number==19) cout<<"ninteen";
}
else
{
if(unit==0) cout<<"zero";
if(unit==1) cout<<"one";
if(unit==2) cout<<"two";
if(unit==3) cout<<"three";
if(unit==4) cout<<"four";
if(unit==5) cout<<"five";
if(unit==6) cout<<"six";
if(unit==7) cout<<"seven";
if(unit==8) cout<<"eight";
if(unit==9) cout<<"nine";
if(ten==10) cout<<"Ten";
if(ten==20) cout<<"twenty";
if(ten==30) cout<<"thirty";
if(ten==40) cout<<"fourty";
if(ten==50) cout<<"fifty";
if(ten==60) cout<<"sixty";
if(ten==70) cout<<"seventy";
if(ten==80) cout<<"eighty";
if(ten==90) cout<<"ninty";
}
}
Output:
Please enter any number between 0-99: 25
five
Actually, your program is working correctly. For input 25 it should give five because you are doing unit = number%10 which returns 5 and if(unit==5) cout<<"five"; right from your own code.
If you want to get twenty five in return you should change the code.
Instead of making direct matching, store numbers in map and check the value of it. and another approch is to store them in 2 different lists like: d1 = ['zero','one' ...] and d10 = ['ten', 'twenty', 'thirty', ...]. By this, you will not repeat anything. Furthermore, you can check the length of the input and know if it one decimal number or two and if 2 decimal number you can get the first one with number/10 and the second one with number%10 and concatenate the result.
Let' take 25 you will search 2 in the d10 list and 5 in the d1 list and at the end, you end up 'twenty' + 'five'
n1 = number/10
n2 = number%10
for i in d10:
if i == n1:
for j in d1:
if j == n2:
print(i+' ' +j)
else:
break
else:
break
NOTE: the code is in python 3.x
There are only two places where you need to just do minor changes and you will get you desired result
first when you are separing the ten part, multiply it with 10 aftwards to checking for multiple of 10 in your if conditions of multiple of 10 i.e. 10 , 20 ,..
and then you need to just change the position of all the ten position comparison to above all other one's digit number comparisons
I copied your code and did changes,
I have commented below where you need to change
//This program converts numbers from 0-99 into words
#include<iostream>
using namespace std;
int main()
{
int number,unit,ten;
cout<<"Please enter any number between 0-99: ";
cin >>number;
ten=number/10;
unit=number%10;
ten=ten*10;// multiply again it make it power of 10 so that you can check for if for multiple of 10
if(number<0 | number>99)
cout<<"Number is out of range";
if(number>=11 & number <=19)
{
if(number==11) cout<<"eleven";
if(number==12) cout<<"twelve";
if(number==13) cout<<"thirteen";
if(number==14) cout<<"fourteen";
if(number==15) cout<<"fifteen";
if(number==16) cout<<"sixteen";
if(number==17) cout<<"seventeen";
if(number==18) cout<<"eighteen";
if(number==19) cout<<"ninteen";
}
else
{
if(ten==10) cout<<"Ten";
if(ten==20) cout<<"twenty";
if(ten==30) cout<<"thirty";
if(ten==40) cout<<"fourty";
if(ten==50) cout<<"fifty";
if(ten==60) cout<<"sixty";
if(ten==70) cout<<"seventy";
if(ten==80) cout<<"eighty";
if(ten==90) cout<<"ninty";
//all ten position comparisons has been shifted before all one's position comparisons
if(unit==0) cout<<"zero";
if(unit==1) cout<<"one";
if(unit==2) cout<<"two";
if(unit==3) cout<<"three";
if(unit==4) cout<<"four";
if(unit==5) cout<<"five";
if(unit==6) cout<<"six";
if(unit==7) cout<<"seven";
if(unit==8) cout<<"eight";
if(unit==9) cout<<"nine"; }
}

How to get the right value?

What must I do to get the right Level?
example:
int gXP = globalDoHandle::PlayerStats_XP(p);
ostringstream sXP; sXP << "XP(RP): " << gXP;
ostringstream sLEVEL; sLEVEL << "Level: " << gLEVEL;
I want use the XP value to get the right Level then.
If I get the the value 24450 should give me it then "10" back
I know I can use something like this, but that are 8000 Level in the Game!
if (gXP < 800) { Rank = "1"; }
else if (gXP < 2100) { Rank = "2"; }
else if (gXP < 3800) { Rank = "3"; }
...
LEVEL: XP
Level 1: 0
Level 2: 800
Level 3: 2100
Level 4: 3800
Level 5: 6100
Level 6: 9500
Level 7: 12500
Level 8: 16000
Level 9: 19800
Level 10: 24000
Level 11: 28500
Level 12: 33400
Level 13: 38700
Level 14: 44200
Level 15: 50200
Level 16: 56400
Level 17: 63000
Level 18: 69900
Level 19: 77100
Level 20: 84700
...Level 8000: 1787576850
To do such a job, you need std::lower_bound. std::lower_bound(l, h, v) returns an iterator it inside the range [l, h) for which the value on the range is the smallest verifying *it > v.
constexpr std::array<unsigned, 10> levels = { /* ... */ }; // xp needed for each level
unsigned level(unsigned xp)
{
auto it = std::lower_bound(cbegin(levels), cend(levels), xp);
return std::distance(begin(levels), it);
}
level(xp) returns the level reached with xp experience points with respect to the values of levels.
Se a full demo online
Use a std::array with your exp values in.
std::array<int, 8000> exp_table = { 0, 800, 2100... };
int level=0;
for(; level < exp_table.size() && exp_table[level] < gXP; ++level);
Rank = std::to_string(level); // If this is needed?
After this level will be set correctly. The only thing left is how you generate your exp_table. Read it from a file. Use some math formula.

C++ - Variable Decrement

Heys.
I have this code, which sets a table for some mystery reason. Size is 6x60. Which means SIZEY defined as 6, and SIZEX as 60.
void set_table(char** table)
{
int i,j,k=0;
for(i=0;i<SIZEY;i+=3){
for(j=0;j<SIZEX;j++){
switch(k++%5){
case 0:
table[i][j]='|';
break;
case 1:
table[i][j]=' ';
break;
case 2:
table[i][j]=(char)((((k-2)/50)%10)+48);
break;
case 3:
table[i][j]=(char)((((k-3)/5)%10)+48);
break;
case 4:
table[i][j]=' ';
break;
default:
continue;
}
}
}
}
I am doing this with 3 variables, as you can see. Question is, can i do that with 2 variables, or even with only 1 ?
Thanks in advance.
Here's a simplification for you:
switch(k++%5){
case 0:
table[i][j]='|';
break;
case 1:
case 4:
table[i][j]=' ';
break;
case 2:
case 3:
table[i][j]= '0';
break;
default:
continue;
}
With C++, one case can fall into another, such as with cases 1 and 2 above.
Your expressions for case 2 and 3 can be simplified. I'll use case 2 as an example:
((((k-2)/50)%10)+48)
Substituting 2 for k yields
((((2-2)/50)%10)+48)
Simplify:
((((0)/50)%10)+48)
Zero divided by anything is zero, simplifying again:
(((0)%10)+48)
Zero mod anything is zero, since it involves division:
((0)+48)
Simplifying:
(48)
Replacing with the equivalent character (since your array is char):
'0'

Can I match a range instead of a single value in a C++ switch statement?

I am new into programming. Is it possible to use <, > in a switch case?
For instance,
...
...
...
int i;
cin>> i;
...
...
switch(i){
case 20<i<35
...
C++ does not offer a switch syntax for matching ranges.
When ranges are relatively small, you could supply case labels, and rely on fall-through:
switch(i) {
case 20:
case 21:
case 22:
case 23:
case 24:
case 25: doSomething();
break;
case 26:
case 27:
case 28:
case 29: doSomethingElse();
break;
...
}
For medium-size ranges (1000 elements or so) you could use a vector of function objects to dispatch to a particular logic, but that requires a lot more work than writing a simple switch statement.
For large ranges your best bet is a chain of if-else statements.

converting an if statement to a switch statement

How can I convert the following if=statement to a switch-statement WITHOUT needing to create a case for every number between that interval (41-49)? Is it possible?
if (num < 50 && num > 40)
{
printf("correct!");
}
You have to enumerate every case for a switch. The compiler converts this to a jump table, so you can't use ranges. You can, however, have multiple cases use the same block of code, which may be closer to what you want.
switch(num) {
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
case 48:
case 49:
printf("correct!");
break;
default:
break;
}
What about this?
switch ((num-41)/9) {
case 0:
printf("correct!");
break;
}
bool criteria1 = (num < 50 && num > 40);
switch criteria1: ...
It may result in multilevel decision networks.. scary?
In C or C++ (since you are using printf, I'll assume that's what it is), cases need to be enumerated for each choice.
The only difference between switch/case and if is the possibility that the compiler can turn it into a computed goto instead of checking ranges. If switch/case supported ranges, that would defeat the purpose of opening the possibility of this optimizaton.