Why does my switch/case default when using enums? - c++

I have the following switch/case statement in Arduino 1.8.7 where the variable led is an integer:
switch (led) {
case ALL: {
/* do stuff */
break;
}
case LED1: {
/* do stuff */
break;
}
case LED2: {
/* do stuff */
break;
}
case LED3: {
/* do stuff */
break;
}
case LED4: {
/* do stuff */
break;
}
default: {
break;
}
}
I also have the following enum:
enum LED_References_e
{
ALL = 0,
LED1 = 1,
LED2 = 2,
LED3 = 3,
LED4 = 4
};
When using the enumerated values as cases to the statement, the statement always hits the default clause. If I substitute the enumerated values for the integers that they represent (i.e.case 0: ... case 1: ...) then the statement functions as expected.
I have tried, when using the enumerated values within the statement, to reference the enumerator as the value that the switch is performed on:
switch ((LED_References_e)led)
But this also defaults every time.
I am using another enumerator within my program and this functions correctly, however it is conditionally tested using if/else as opposed to switch/case.
My question is twofold:
Why does the switch/case statement seemingly not work with enumerated values?
What fundamental difference am I missing between if/else and switch/case?

Assuming Max Langhof is correct and there are other names ALL, LED1, etc... in scope at the switch so that the LED_References_e ones are shadowed, this should help:
I'm not 100% certain about the differences between standard C++ and Arduino C++, but you should be able to do the following:
enum LED_References_e
{
ALL = 0,
LED1 = 1,
LED2 = 2,
LED3 = 3,
LED4 = 4
};
switch (led) {
case LED_References_e::ALL: {
/* do stuff */
break;
}
case LED_References_e::LED1: {
/* do stuff */
break;
}
case LED_References_e::LED2: {
/* do stuff */
break;
}
case LED_References_e::LED3: {
/* do stuff */
break;
}
case LED_References_e::LED4: {
/* do stuff */
break;
}
default: {
break;
}
}
What this does is it tells the compiler you explicitly want LED1...LED4 from the LED_References_e enum.
If there are other LEDxes in the same scope, this should disambiguate.

Related

why does omp_get_schedule() return a monotonic schedule when OMP_SCHEDULE=static?

I am compiling my code with g++8.5 on redhat8 and I notice that when I set OMP_SCHEDULE=static, then inside my application omp_get_schedule() returns a "monotonic" schedule instead of a "static" schedule. Why could this be happening? If I set OMP_SCHEDULE to something else such as "dynamic" then my application recognizes it as "dynamic". Here is the code in question. Any ideas? Thanks
omp_sched_t kind;
int chunk_size;
omp_get_schedule(&kind, &chunk_size);
switch(kind)
{
case omp_sched_static:
{
schedule_msg = schedule_msg + "schedule=static, chunk_size="+std::to_string(chunk_size);
break;
}
case omp_sched_dynamic:
{
schedule_msg = schedule_msg + "schedule=dynamic, chunk_size="+std::to_string(chunk_size);
break;
}
case omp_sched_guided:
{
schedule_msg = schedule_msg + "schedule=guided, chunk_size="+std::to_string(chunk_size);
break;
}
case omp_sched_auto:
{
schedule_msg = schedule_msg + "schedule=auto, chunk_size="+std::to_string(chunk_size);
break;
}
default:
{
schedule_msg = schedule_msg + "schedule=monotonic, chunk_size="+std::to_string(chunk_size);
break;
}
}
omp_sched_t is defined as:
typedef enum omp_sched_t {
omp_sched_static = 1,
omp_sched_dynamic = 2,
omp_sched_guided = 3,
omp_sched_auto = 4,
omp_sched_monotonic = 0x80000000
} omp_sched_t;
Note that omp_sched_monotonic is a modifier not a type, so monotonic:static is expressed as omp_sched_monotonic | omp_sched_static (and its value is 0x80000001).
According to OpenMP standard:
If the static schedule kind is specified or if the ordered
clause is specified, and if no monotonic modifier is specified,
the effect will be as if the monotonic modifier was specified.
Therefore, if OMP_SCHEDULE is set to static the return value of omp_get_schedule() is 0x80000001, but your code is not handling properly the monotonic modifier.

How to use multiple IR signals for doing the same thing?

I want to use different signals from different IR remotes to control a wheeled robot.
The robot is the Smart robot car kit v1.0 from Elegoo.
I used the infrared_remote_control_car.ino file from the disc with it.
I just added the #define JVC and the operators at the end.
The code looks like this:
#include <IRremote.h>
int receiverpin = 12;
int in1=9;
int in2=8;
int in3=7;
int in4=6;
int ENA=10;
int ENB=5;
int ABS=130;
unsigned long RED;
#define A 16736925
#define B 16754775
#define X 16712445
#define C 16720605
#define D 16761405
#define JVCfront 49816
#define JVCback 49688
#define JVCright 49704
#define JVCleft 49832
#define JVCmenu 49900
#define JVC3ok 49724
#define JVCstop 49856
IRrecv irrecv(receiverpin);
decode_results results;
void _mForward()
{
digitalWrite(ENA,HIGH);
digitalWrite(ENB,HIGH);
digitalWrite(in1,LOW);
digitalWrite(in2,HIGH);
digitalWrite(in3,LOW);
digitalWrite(in4,HIGH);
Serial.println("go forward!");
}
void _mBack()
{
digitalWrite(ENA,HIGH);
digitalWrite(ENB,HIGH);
digitalWrite(in1,HIGH);
digitalWrite(in2,LOW);
digitalWrite(in3,HIGH);
digitalWrite(in4,LOW);
Serial.println("go back!");
}
void _mleft()
{
analogWrite(ENA,ABS);
analogWrite(ENB,ABS);
digitalWrite(in1,LOW);
digitalWrite(in2,HIGH);
digitalWrite(in3,HIGH);
digitalWrite(in4,LOW);
Serial.println("go left!");
}
void _mright()
{
analogWrite(ENA,ABS);
analogWrite(ENB,ABS);
digitalWrite(in1,HIGH);
digitalWrite(in2,LOW);
digitalWrite(in3,LOW);
digitalWrite(in4,HIGH);
Serial.println("go right!");
}
void _mStop()
{
digitalWrite(ENA,LOW);
digitalWrite(ENB,LOW);
Serial.println("STOP!");
}
void setup() {
pinMode(in1,OUTPUT);
pinMode(in2,OUTPUT);
pinMode(in3,OUTPUT);
pinMode(in4,OUTPUT);
pinMode(ENA,OUTPUT);
pinMode(ENB,OUTPUT);
pinMode(receiverpin,INPUT);
Serial.begin(9600);
_mStop();
irrecv.enableIRIn();
}
void loop() {
if (irrecv.decode(&results))
{
RED=results.value;
Serial.println(RED);
irrecv.resume();
delay(150);
if(RED==(A || JVCfront))
{
_mForward();
}
else if(RED==(B or JVCback))
{
_mBack();
}
else if(RED==(C or JVCleft))
{
_mleft();
}
else if(RED==(D or JVCright))
{
_mright();
}
else if(RED==(X or JVCstop or JVCmenu or JVC3ok))
{
_mStop();
}
}
}
I tried different ways I saw on the internet for the OR operator as you can see.
Actually, the robot is always going forward.
Does the Serial.println(RED) always print out the expected value?
Your if-elseblock itself does not seem to be problematic at first glance. It doesn't matter if you use || or or. They are equivalent.
The problem is the way you are checking the value:
Therefore that you have parenthesis around your OR statement, you create a bool-value. if(RED==(A || JVCfront) translates to:
is A set or is JVCfront set; meaning, are they != 0 (yes they both are, so this expression is true
is RED == true (no it is not, because true represents 1 in integer)
so the code in that block is not being executed
If you want to solve it with an if-else, you need to:
if(RED == A or RED == JVCfront)
{
_mForward();
}
Anyway, I would suggest a switch-case statement:
switch(RED):
{
case A:
{
//intentional fallthrough
}
case JVCfront:
{
_mForward();
break;
}
case B:
{
//intentional fallthrough
}
case JVCback:
{
_mBack();
break;
}
case C:
{
//intentional fallthrough
}
case JVCleft:
{
_mleft();
break;
}
case D:
{
//intentional fallthrough
}
case JVCright:
{
_mright();
break;
}
case X:
{
//intentional fallthrough
}
case JVCstop:
{
//intentional fallthrough
}
case JVCmenu:
{
//intentional fallthrough
}
case JVC3ok:
{
_mStop();
break;
}
default:
{
_mStop();
}
}
I personally find this kind of code much easier to read, and more understandable.
Please note: If you dont put a break into a case, it automatically executes the next case as well. This is why I wrote //intentional fallthrough in this part of the code. P.e. when case A is executed, nothing happens. It just falls through into case JVCFront and executes everything there.

Capping the value

I have a small script that defines the casting time for all classes in this minor project im working on however i have a few issues.
I want to place a cap on the max value however i'm getting errors!
this is the function i was referring to.
void Player::ApplyRatingMod(CombatRating combatRating, int32 value, bool apply)
{
float oldRating = m_baseRatingValue[combatRating];
m_baseRatingValue[combatRating] += (apply ? value : -value);
// explicit affected values
float const multiplier = GetRatingMultiplier(combatRating);
float const oldVal = oldRating * multiplier;
float const newVal = m_baseRatingValue[combatRating] * multiplier;
switch (combatRating)
{
case CR_HASTE_MELEE:
ApplyAttackTimePercentMod(BASE_ATTACK, oldVal, false);
ApplyAttackTimePercentMod(OFF_ATTACK, oldVal, false);
ApplyAttackTimePercentMod(BASE_ATTACK, newVal, true);
ApplyAttackTimePercentMod(OFF_ATTACK, newVal, true);
break;
case CR_HASTE_RANGED:
ApplyAttackTimePercentMod(RANGED_ATTACK, oldVal, false);
ApplyAttackTimePercentMod(RANGED_ATTACK, newVal, true);
break;
case CR_HASTE_SPELL:
//ApplyCastTimePercentMod(oldVal, false);
//ApplyCastTimePercentMod(newVal, true);
break;
default:
break;
}
UpdateRating(combatRating);
}
void Player::UpdateRating(CombatRating cr)
{
int32 amount = m_baseRatingValue[cr];
// Apply bonus from SPELL_AURA_MOD_RATING_FROM_STAT
// stat used stored in miscValueB for this aura
AuraEffectList const& modRatingFromStat = GetAuraEffectsByType(SPELL_AURA_MOD_RATING_FROM_STAT);
for (AuraEffect const* aurEff : modRatingFromStat)
if (aurEff->GetMiscValue() & (1 << cr))
amount += int32(CalculatePct(GetStat(Stats(aurEff->GetMiscValueB())), aurEff->GetAmount()));
if (amount < 0)
amount = 0;
SetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr, uint32(amount));
bool affectStats = CanModifyStats();
switch (cr)
{
case CR_WEAPON_SKILL: // Implemented in Unit::RollMeleeOutcomeAgainst
case CR_DEFENSE_SKILL:
UpdateDefenseBonusesMod();
break;
case CR_DODGE:
UpdateDodgePercentage();
break;
case CR_PARRY:
UpdateParryPercentage();
break;
case CR_BLOCK:
UpdateBlockPercentage();
break;
case CR_HIT_MELEE:
UpdateMeleeHitChances();
break;
case CR_HIT_RANGED:
UpdateRangedHitChances();
break;
case CR_HIT_SPELL:
UpdateSpellHitChances();
break;
case CR_CRIT_MELEE:
if (affectStats)
{
UpdateCritPercentage(BASE_ATTACK);
UpdateCritPercentage(OFF_ATTACK);
}
break;
case CR_CRIT_RANGED:
if (affectStats)
UpdateCritPercentage(RANGED_ATTACK);
break;
case CR_CRIT_SPELL:
if (affectStats)
UpdateAllSpellCritChances();
break;
case CR_HIT_TAKEN_MELEE: // Implemented in Unit::MeleeMissChanceCalc
case CR_HIT_TAKEN_RANGED:
break;
case CR_HIT_TAKEN_SPELL: // Implemented in Unit::MagicSpellHitResult
break;
case CR_CRIT_TAKEN_MELEE: // Implemented in Unit::RollMeleeOutcomeAgainst (only for chance to crit)
case CR_CRIT_TAKEN_RANGED:
break;
case CR_CRIT_TAKEN_SPELL: // Implemented in Unit::SpellCriticalBonus (only for chance to crit)
break;
case CR_HASTE_MELEE: // Implemented in Player::ApplyRatingMod
case CR_HASTE_RANGED:
case CR_HASTE_SPELL:
break;
case CR_WEAPON_SKILL_MAINHAND: // Implemented in Unit::RollMeleeOutcomeAgainst
case CR_WEAPON_SKILL_OFFHAND:
case CR_WEAPON_SKILL_RANGED:
break;
case CR_EXPERTISE:
if (affectStats)
{
UpdateExpertise(BASE_ATTACK);
UpdateExpertise(OFF_ATTACK);
}
break;
case CR_ARMOR_PENETRATION:
if (affectStats)
UpdateArmorPenetration(amount);
break;
}
}
void Player::UpdateAllRatings()
{
for (uint8 cr = 0; cr < MAX_COMBAT_RATING; ++cr)
UpdateRating(CombatRating(cr));
}
You can notice how i want to cap the new value outcome to 32000.
Before it gets calculated to percentages!
I tried using
if(newVal > 32000)
newVal = 32000;
Which would normally do the job i guess, but i'm stuck with an error
E0137 expression must be a modifiable lvalue
On the line newVal = 32000;
Remove const qualifier from newVal
float newVal = m_baseRatingValue[combatRating] * multiplier;
You declare newVal as a constant (float const newVal = ...), so you're not allowed to assign a new value.
Removing const should work for you, e.g.
float newVal = m_baseRatingValue[combatRating] * multiplier;
if (newVal > 32000)
newVal = 32000;
...

Cast const int pointer to int, in a switch case node

In my STM32 code i have an
#define USART1 ((USART_TypeDef *) USART1_BASE)
and i would like to have
switch((uint32_t)ptr)
{
case USART1: return 1;
(...)
But gcc-arm (6.3.1) give me an error
error: reinterpret_cast from integer to pointer
I found an information that i can use
case __builtin_constant_p(USART1): return 0;
but this is only gcc solution? Is there something more generic?
There is UART1_BASE which is just the sum of a couple of unsigned integer constants. See the machine header:
#define PERIPH_BASE 0x40000000U
#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000U)
#define USART1_BASE (APB2PERIPH_BASE + 0x1000U)
So should be able to use
switch((unsigned int)ptr) {
case USART1_BASE: return 1;
}
You forgot to cast pointer to integer in the case statement as well.
Example from my working code:
switch ((uint32_t)gpio) {
case (uint32_t)GPIOA:
EXTI_cfgr = 0b0000;
break;
case (uint32_t)GPIOB:
EXTI_cfgr = 0b0001;
break;
case (uint32_t)GPIOC:
EXTI_cfgr = 0b0010;
break;
default:
break;
}
USART1_BASE is a number in the header files of the STM32 development environment. You can compile your code when you decided what type shall be used in the switch. I recommend uint32_t:
switch((uint32_t)ptr)
{
case USART1_BASE: return 1;
(...)
If you like more readability you can try to remove the cast from the switch:
uint32_t ptr_value = (uint32_t)ptr;
switch(ptr_value)
{
case USART1_BASE: return 1;
(...)

C++ Enum to String Switch Not Working

I am instantiating an object with a few enum types and trying to set some string members based on those enum types. However, when I am debugging and step though, the switch used to set the strings hits every case, and each string gets set to the last case for each enum type.
enum Number {
one,
two,
three
};
enum Color {
purple,
red,
green
};
enum Shading {
solid,
striped,
outlined
};
enum Shape {
oval,
squiggle,
diamond
};
Card::Card(Number num, Color colour, Shading shade, Shape shaper) {
number_ = num;
color_ = colour;
shading_ = shade;
shape_ = shaper;
setStrings();
}
void Card::setStrings() {
switch (number_) {
case one:
number_string = "one";
case two:
number_string = "two";
case three:
number_string = "three";
}
switch(color_) {
case purple:
color_string = "purple";
case red:
color_string = "red";
case green:
color_string = "green";
}
switch (shading_) {
case solid:
shading_string = "solid";
case striped:
shading_string = "striped";
case outlined:
shading_string = "outlined";
}
switch (shape_) {
case oval:
shape_string = "oval";
case squiggle:
shape_string = "squiggle";
case diamond:
shape_string = "diamond";
}
}
Every card I instantiate using the overloaded constructor has number_string = "three", color_string = "green", shading_string = "outlined", and shape_string = "diamond".
You need to use break for switch statements' case clause else it is a fall through. Here is an example and details for you. https://10hash.com/c/cf/#idm45440468325552
#include <stdio.h>
int main()
{
int i = 65;
switch(i)
{
case 'A':
printf("Value of i is 'A'.\n");
break;
case 'B':
printf("Value of i is 'B'.\n");
break;
default:
break;
}
return 0;
}
Your switch-case is not correct. You need to put a break after every case for your solution otherwise it will go into every case until it is finished and not break when it hits the case you want.