Capping the value - c++

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

Related

TradeRequest fields improperly set when backtesting in MT5

I'm generating a trade request that's causing a 10013 error when I do backtesting in MT5. I decided to log the trade request and it printed this:
2022.11.16 14:28:17.245 Core 01 2022.01.04 11:00:00 Action REMOVE, Symbol EURUSD, Volume 0.100000, Price 1.128980, Deviation 5, Type SELL STOP LIMIT, Position 9443944
My code is:
bool Strategy::DoEntryRules() {
// Iterate over all the entry rules we have registered...
for (int i = 0; i < m_entry_rules.Count(); i++) {
IEntryRule *rule;
m_entry_rules.TryGetValue(i, rule);
EntryResult result = rule.Enter();
if (result.Result == ENTRY_RESULT_CONTINUE) {
continue;
} else if (result.Result == ENTRY_RESULT_ERROR) {
PrintFormat("Entry rule %s failed with error code %d\n", rule.Name(), result.ErrorCode);
}
m_money_manager.AssignLot(result.Order);
uint errCode = SendOrder(result.Order, rule.Name());
if (errCode != 0) {
result.Result = ENTRY_RESULT_ERROR;
result.ErrorCode = errCode;
}
return true;
}
return false;
}
uint Strategy::SendOrder(const MqlTradeRequest &request, const string name) {
string action;
switch (request.action) {
case TRADE_ACTION_DEAL:
action = "DEAL";
case TRADE_ACTION_SLTP:
action = "SLTP";
case TRADE_ACTION_CLOSE_BY:
action = "CLOSE BY";
case TRADE_ACTION_MODIFY:
action = "MODIFY";
case TRADE_ACTION_PENDING:
action = "PENDING";
case TRADE_ACTION_REMOVE:
action = "REMOVE";
}
string type;
switch (request.type) {
case ORDER_TYPE_BUY:
type = "BUY";
case ORDER_TYPE_BUY_LIMIT:
type = "BUY LIMIT";
case ORDER_TYPE_BUY_STOP:
type = "BUY STOP";
case ORDER_TYPE_BUY_STOP_LIMIT:
type = "BUY STOP LIMIT";
case ORDER_TYPE_CLOSE_BY:
type = "CLOSE BY";
case ORDER_TYPE_SELL:
type = "SELL";
case ORDER_TYPE_SELL_LIMIT:
type = "SELL LIMIT";
case ORDER_TYPE_SELL_STOP:
type = "SELL STOP";
case ORDER_TYPE_SELL_STOP_LIMIT:
type = "SELL STOP LIMIT";
}
PrintFormat("Action %s, Symbol %s, Volume %f, Price %f, Deviation %d, Type %s, Position %d",
action, request.symbol, request.volume, request.price, request.deviation, type, request.position);
MqlTradeCheckResult checkResult;
if (!OrderCheck(request, checkResult)) {
PrintFormat("%s generated a bad order with error code %d: %s", name, checkResult.retcode, checkResult.comment);
return checkResult.retcode;
}
MqlTradeResult result;
if (!OrderSend(request, result) && result.retcode != TRADE_RETCODE_DONE) {
PrintFormat("%s generated an order that was not accepted with error code %d: %s", name, result.retcode, result.comment);
return result.retcode;
}
return 0;
}
where m_entry_rules contains one IEntryRule, which is an interface that has the following implementation:
EntryResult SentimentEntry::Enter() {
EntryResult result;
if (m_handle == 0) {
int errCode = InitATR();
if (errCode != 0) {
result.Result = ENTRY_RESULT_ENTER;
result.ErrorCode = errCode;
return result;
}
}
double values[];
if (CopyBuffer(m_handle, 0, 0, 1, values) < 0) {
result.Result = ENTRY_RESULT_ERROR;
result.ErrorCode = GetLastError();
ResetLastError();
return result;
}
ENUM_SENTIMENT sentiment = SentimentIndicator();
bool decision = GetRange() > 0.66 * values[0];
if (decision && sentiment != SENTIMENT_NEUTRAL) {
PrintFormat("%f > 0.66 * %f, %s", GetRange(), values[0], SentimentToString(sentiment));
result.Result = ENTRY_RESULT_ENTER;
result.Order = CreateOrder(m_magic);
if (sentiment == SENTIMENT_BULLISH) {
result.Order.price = SymbolInfoDouble(Symbol(), SYMBOL_ASK); // ENTERED HERE
result.Order.type = ORDER_TYPE_BUY;
} else if (sentiment == SENTIMENT_BEARISH) {
result.Order.price = SymbolInfoDouble(Symbol(), SYMBOL_BID);
result.Order.type = ORDER_TYPE_SELL;
}
} else {
result.Result = ENTRY_RESULT_CONTINUE;
}
return result;
}
and m_money_manager.AssignLot is defined as:
void ConstantLotManager::AssignLot(MqlTradeRequest &request) {
request.volume = 0.1;
return;
}
Finally, the CreateOrder function is defined as:
MqlTradeRequest CreateOrder(ulong magic) {
MqlTradeRequest request;
request.symbol = Symbol();
request.deviation = 5;
request.action = TRADE_ACTION_DEAL;
request.type_filling = ORDER_FILLING_FOK;
request.type_time = ORDER_TIME_GTC;
request.magic = magic;
return request;
}
From logging, I'm able to determine that the commented line was reached, so the trade request should have an action of TRADE_ACTION_DEAL and a type of ORDER_TYPE_BUY so I'm not sure why it's showing up as me attempting to remove a sell-short order. Does anyone know what's going on here?
I have determined the problem and fixed it. The core issue was that I wasn't converting the ENUM_TRADE_REQUEST_ACTIONS and ENUM_ORDER_TYPE enums to strings properly, giving me the impression of a malformed trade request. The logging statement should look like this:
string action;
switch (request.action) {
case TRADE_ACTION_DEAL:
action = "DEAL";
break;
case TRADE_ACTION_SLTP:
action = "SLTP";
break;
case TRADE_ACTION_CLOSE_BY:
action = "CLOSE BY";
break;
case TRADE_ACTION_MODIFY:
action = "MODIFY";
break;
case TRADE_ACTION_PENDING:
action = "PENDING";
break;
case TRADE_ACTION_REMOVE:
action = "REMOVE";
break;
}
string type;
switch (request.type) {
case ORDER_TYPE_BUY:
type = "BUY";
break;
case ORDER_TYPE_BUY_LIMIT:
type = "BUY LIMIT";
break;
case ORDER_TYPE_BUY_STOP:
type = "BUY STOP";
break;
case ORDER_TYPE_BUY_STOP_LIMIT:
type = "BUY STOP LIMIT";
break;
case ORDER_TYPE_CLOSE_BY:
type = "CLOSE BY";
break;
case ORDER_TYPE_SELL:
type = "SELL";
break;
case ORDER_TYPE_SELL_LIMIT:
type = "SELL LIMIT";
break;
case ORDER_TYPE_SELL_STOP:
type = "SELL STOP";
break;
case ORDER_TYPE_SELL_STOP_LIMIT:
type = "SELL STOP LIMIT";
break;
}
PrintFormat("Action %s, Symbol %s, Volume %f, Price %f, Deviation %d, Type %s, Position %d",
action, request.symbol, request.volume, request.price, request.deviation, type, request.position);
This was my punishment for not remembering that I have to break switch statements in C++. :(

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.

Defining variables esp32

i am trying to figure out a way in esp32 to have (a list) for lack of better terms, that i could call upon as a variable input. I have a void playwav(); function. I want to use a global variable to define the file that should be played. ie playwav('alarm'). I had a case switch setup but was using the a b c method. As my code is growing (next step is going to add 71 new wav files), i am quickly realizing that method will no longer work. I have been told to do an array but for the life of me no matter what ive read i just cant grasp how to do it nor call upon the files by name. Does anyone have advice on what i should do? Any help is much appreciated.
This is what i currently have.
void playWAV (char effect, int bg1248_general_volume)
{
Serial.println("Entered playWAV");
switch (effect)
{
case 'a':
file = new AudioFileSourceSD("/wav/alarm.wav");
break;
case 'b':
file = new AudioFileSourceSD("/wav/alarmhigh.wav");
break;
case 'c':
file = new AudioFileSourceSD("/wav/alarmlow.wav");
break;
case 'd':
file = new AudioFileSourceSD("/wav/error.wav");
break;
case 'e':
file = new AudioFileSourceSD("/wav/error1.wav");
break;
case 'f':
file = new AudioFileSourceSD("/wav/noread.wav");
break;
case 'g':
file = new AudioFileSourceSD("/wav/noreadings.wav");
break;
case 'h':
file = new AudioFileSourceSD("/wav/normalrange.wav");
break;
case 'i':
file = new AudioFileSourceSD("/wav/warning.wav");
break;
case 'j':
file = new AudioFileSourceSD("/wav/warninghigh.wav");
break;
case 'k':
file = new AudioFileSourceSD("/wav/warninglow.wav");
break;
case 'l':
file = new AudioFileSourceSD("/wav/startup.wav");
break;
case 'm':
file = new AudioFileSourceSD("/wav/startup.wav");
break;
case 'n':
file = new AudioFileSourceSD("/wav/update.wav");
break;
case 'o':
file = new AudioFileSourceSD("/wav/startup_dev.wav");
}
float volumeGain = ((float)bg1248_general_volume / 100.0) * 39.0;
Serial.print("volumeGain:");
Serial.println(volumeGain);
id3 = new AudioFileSourceID3(file);
out = new AudioOutputI2S(0, 0); // Output to builtInDAC
out->SetPinout(12, 0, 2);
out->SetOutputModeMono(true);
out->SetGain(volumeGain);
wav = new AudioGeneratorWAV();
wav->begin(id3, out);
However because I used the alphabet im going to run out of cases very very soon. I want to be able to call for a specific wav file anywhere in the project preferably like playWAV(filename) or something similar.
I call the function(file) like this (example condition)
if((ns->sensSgv<=cfg.snd_alarm) && (ns->sensSgv>=0.1)) {
// red alarm state
// M5.Lcd.fillRect(110, 220, 100, 20, TFT_RED);
Serial.println("ALARM LOW");
M5.Lcd.fillRect(0, 220, 320, 20, TFT_RED);
M5.Lcd.setTextColor(TFT_BLACK, TFT_RED);
int stw=M5.Lcd.textWidth(tmpStr);
M5.Lcd.drawString(tmpStr, 159-stw/2, 220, GFXFF);
if( (alarmDifSec>cfg.alarm_repeat*60) && (snoozeRemaining<=0) ) {
playWAV('a', 100);
'a'=case 100 = volume.
Alan, this is what I currently had in my enum, i was following a tutorial but doubt i did it right. even if i did i was getting errors saying i had duplicate cases when i don't.
EDIT:
The condition is set using this:
if((ns->sensSgv<=cfg.snd_alarm) && (ns->sensSgv>=0.1))
and if you notice at the bottom there is:
if( (alarmDifSec>cfg.alarm_repeat*60) && (snoozeRemaining<=0) ) {
playWAV('a', 100);
The a corelates to the case A in the switch case. shown above. currently all the places that use the playWAV function are manually specified.
My understanding was using the alphabets in switch case will ran out soon because of large no. of files (>26). So, I implemented the logic using enum first and below is the complete code.
#include<stdio.h>
enum soundEffects {
alarm,
alarm_high,
alarm_low,
Dev_startup,
error,
error1,
noread,
noreadings,
normalrange,
startup,
startup_dev,
update,
warning,
warning_high,
warning_low,
};
void playWav (enum soundEffects effect, int paci_volume)
{
//Serial.println("Entered paciplay_day");
//printf("Entered paciplay_day\n");
switch (effect)
{
case alarm:
//file = new AudioFileSourceSD("/wav/alarm.wav");
printf("/wav/alarm.wav\n");
break;
case alarm_high:
//file = new AudioFileSourceSD("/wav/alarmhigh.wav");
printf("/wav/alarmhigh.wav\n");
break;
case alarm_low:
//file = new AudioFileSourceSD("/wav/alarmlow.wav");
printf("/wav/alarmlow.wav\n");
break;
case error:
//file = new AudioFileSourceSD("/wav/error.wav");
printf("/wav/error.wav\n");
break;
case error1:
//file = new AudioFileSourceSD("/wav/error1.wav");
printf("/wav/error1.wav\n");
break;
case noread:
//file = new AudioFileSourceSD("/wav/noread.wav");
printf("/wav/noread.wav\n");
break;
case noreadings:
//file = new AudioFileSourceSD("/wav/noreadings.wav");
printf("/wav/noreadings.wav\n");
break;
case normalrange:
//file = new AudioFileSourceSD("/wav/normalrange.wav");
printf("/wav/normalrange.wav\n");
break;
case warning:
//file = new AudioFileSourceSD("/wav/warning.wav");
printf("/wav/warning.wav\n");
break;
case warning_high:
//file = new AudioFileSourceSD("/wav/warninghigh.wav");
printf("/wav/warninghigh.wav\n");
break;
case warning_low:
//file = new AudioFileSourceSD("/wav/warninglow.wav");
printf("/wav/warninglow.wav\n");
break;
case startup:
//file = new AudioFileSourceSD("/wav/startup.wav");
printf("/wav/startup.wav\n");
break;
case update:
//file = new AudioFileSourceSD("/wav/update.wav");
printf("/wav/update.wav\n");
break;
}
}
int main()
{
//below are the 3 ways of calling your playWav() function
//1 - using direct numbers
//this will throw compilation error when compiled using cpp compilers
for (int i = 0; i<14; i++)
{
printf("enum value: %d\n", i);
playWav(i, 50);
}
//2 - directly calling using the enum
playWav(startup, 100);
//3 - Just another way of calling
enum soundEffects sound;
sound = error;
playWav(sound, 100);
return 0;
}
Also, I implemented this same logic using double array's. Please do find it below. This uses the name of the file as a parameter so altogether we can eliminate the use of switch statement.
#include<stdio.h>
void playWav (const char *filename, int paci_volume)
{
//Serial.println("Entered paciplay_day");
printf("Entered paciplay_day\n");
//file = new AudioFileSourceSD("/wav/update.wav");
printf("/wav/%s\n", filename);
}
int main()
{
const char list_of_files[][25] = { "startup.wav", "update.wav", "warning.wav", "alarm.wav" };
for (int i = 0; i<4; i++)
{
printf("name: %s\n", list_of_files[i]);
playWav(list_of_files[i], 50);
}
return 0;
}
Please omit my printf statements which I used for debugging. I hope this is useful.

How to use C++ Builder OPENARRAY in a custom function

I would like to use OPENARRAY (or an alternative, if you have one) to pass multiple placeholder variables into my function. I know that it can be used for String::Format in this way:
UnicodeString Text1 = "abc";
int Num2 = 1;
String::Format("Some %s and %d", OPENARRAY(TVarRec, (Text1, Num2));
What I would like is to use Text1 and Text2 variables in something like this:
MyFunction("Some %Txt1 and %Num2", OPENARRAY(TVarRec, ("%Txt1", Text1, "%Num2", Num2));
Or perhaps:
MyFunction(OPENARRAY(TVarRec, ("Some %Txt1 and %Num2", "%Txt1", Text1, "%Num2", Num2));
So it would accept the text and replace the placeholder variables with appropriate variable content.
What I don't know is how do I read OPENARRAY parameter content from MyFunction.
So the function would look like:
UnicodeString MyFunction(UnicodeString Txt, ?WHAT-HERE?)
{
// read openarray here and replace vars
return StringReplace(Txt, ?WHAT-HERE?);
}
So I don't know how do I accept the OPENARRAY variables. Also, if you have an alternative solution to passing placeholder, variable in similar manner (without the use of C++11), that would also be welcome.
When passing a Delphi-style Open Array to a function, two things are actually passed:
a pointer to the first element of the array
the index of the last element of the array (NOT the length of the array, as you might expect!).
So, in your example, you can declare your function like this:
UnicodeString MyFunction(UnicodeString Txt, const TVarRec *Values, const int Values_High)
And then loop through the array using normal pointer arithmetic.
TVarRec can hold many different data types, so you have to look at its VType field to know what kind of data it is actually referencing, and then access the appropriate data field. Some values (integers and single characters) are stored directly in the TVarRec itself, while others (strings and other class types) are referenced by pointer instead.
For example:
UnicodeString MyFunction(UnicodeString Txt, const TVarRec *Values, const int Values_High)
{
if (((Values_High + 1) % 2) != 0)
throw Exception("uneven number of values!");
for (int index = 0; index <= Values_High; index += 2)
{
String OldValue, NewValue;
switch (Values[index].VType)
{
case vtString:
OldValue = * static_cast<const ShortString*>(Values[index].VString);
break;
case vtPChar:
OldValue = Values[index].VPChar;
break;
case vtPWideChar:
OldValue = Values[index].VPWideChar;
break;
case vtAnsiString:
OldValue = * static_cast<const AnsiString*>(Values[index].VAnsiString);
break;
case vtWideString:
OldValue = * static_cast<const WideString*>(Values[index].VWideString);
break;
case vtUnicodeString:
OldValue = * static_cast<const UnicodeString*>(Values[index].VUnicodeString);
break;
default:
throw Exception("illegal value type at index %d!", ARRAYOFCONST(( index )) );
}
switch (Values[index+1].VType)
{
case vtInteger:
NewValue = Values[index+1].VInteger;
break;
case vtBoolean:
NewValue = Values[index+1].VBoolean;
break;
case vtChar:
NewValue = Values[index+1].VChar;
break;
case vtExtended:
NewValue = * static_cast<const Extended*>(Values[index+1].VExtended);
break;
case vtString:
NewValue = * static_cast<const ShortString*>(Values[index+1].VString);
break;
case vtPChar:
NewValue = Values[index+1].VPChar;
break;
case vtWideChar:
NewValue = Values[index+1].VWideChar;
break;
case vtPWideChar:
NewValue = Values[index+1].VPWideChar;
break;
case vtAnsiString:
NewValue = * static_cast<const AnsiString*>(Values[index+1].VAnsiString);
break;
case vtCurrency:
NewValue = * static_cast<const Currency*>(Values[index+1].VCurrency);
break;
case vtVariant:
NewValue = * static_cast<const Variant*>(Values[index+1].VVariant);
break;
case vtWideString:
NewValue = * static_cast<const WideString*>(Values[index+1].VWideString);
break;
case vtInt64:
NewValue = * static_cast<const __int64*>(Values[index+1].VInt64);
break;
case vtUnicodeString:
NewValue = * static_cast<const UnicodeString*>(Values[index+1].VUnicodeString);
break;
default:
throw Exception("illegal value type at index %d!", ARRAYOFCONST(( index )) );
}
Txt = StringReplace(Txt, OldValue, NewValue, TReplaceFlags() << rfReplaceAll);
}
return Txt;
}
MyFunction("Some %Txt1 and %Num2", OPENARRAY(TVarRec, ("%Txt1", Text1, "%Num2", Num2)) );
On a side note, when a function takes an open array of TVarRec values, you should use the ARRAYOFCONST() macro instead of the OPENARRAY() macro directly, eg:
String::Format("Some %s and %d", ARRAYOFCONST(( Text1, Num2 )) );
MyFunction("Some %Txt1 and %Num2", ARRAYOFCONST(( "%Txt1", Text1, "%Num2", Num2 )) );

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.