Does CAPL support something like typedef? My goal is to create a boolean:
typedef char bool;
I am able to do this:
enum bool {
false = 0,
true = 1
};
but it isn't what I was going for because I have to do:
enum bool isValid()
instead of:
bool isValid()
Unfortunately there is no typedef in CAPL.
enum is the closest you can get regarding boolean values.
The following code shows the usage of such enum:
variables
{
enum Bool {
true = 1,
false = 0
};
}
on Start {
enum Bool state;
// setting the value
state = true;
// accessing the integer value
write("state (integer value): %d", state); // prints "1"
// accessing the value identifier
write("state (value identifier ): %s", state.name()); // prints "true"
// usage in if-statement
if (state == true) {
write("if-statement: true");
} else {
write("if-statement: false");
}
// usage in switch-statement
switch (state) {
case true:
write("switch-statement: true");
break;
case false:
write("switch-statement: false");
break;
default:
write("switch-statement: undefined");
break;
}
}
Related
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
bool valid(string password);
int main(void)
{
string password = get_string("Enter your password: ");
if (valid(password))
{
printf("Your password is valid!\n");
}
else
{
printf("Your password needs at least one uppercase letter, lowercase letter, number and symbol\n");
}
}
// TODO: Complete the Boolean function below
bool valid(string password)
{
bool CheckUpper = false;
bool CheckLower = false;
bool CheckNumber = false;
bool CheckSymbol = false;
for ( int i=0; i < strlen(password); i++)
{
if (islower (password[i]))
{
CheckLower = true;
}
if (isupper (password[i]))
{
CheckUpper = true;
}
if (isdigit (password[i]))
{
CheckNumber = true;
}
if (!isalnum(password[i]))
{
CheckSymbol = true;
}
}
if (CheckLower == true && CheckUpper == true && CheckNumber == true && CheckSymbol == true)
{
return true;
}
return false;
}
So this code will ask you for a password, and the "valid" Boolean type function will determine whether it is a valid password or not. As you can see it is using an if conditional for every condition required, for each letter of the password in a for loop.
Imagine the first letter is lower case. Is there a way to "skip the if" conditional that checks for a lower case for the next letters/digits of the password? And this way being faster.
I've tried using the continue statement but soon realized it made no sense as it was going back to that if conditional when tenter code herehe for loop advanced one position.
I have a function that is working if I compile with O0 flag but crashes on a function called on a nullptr if compiled with O2.
If I add some macros to disable optimizations around that function it will work properly.
https://i.imgur.com/ObYiiEl.png
if (LPPARTY pkParty = GetParty())
{
struct FPartyBuff
{
const CSkillProto* pkSk;
DWORD casterPID;
int iAmount1, iDur1;
int iAmount2, iDur2;
FPartyBuff(const CSkillProto* pkSkill, DWORD caster, int amount1, int dur1, int amount2, int dur2)
: pkSk(pkSkill), casterPID(caster), iAmount1(amount1), iDur1(dur1), iAmount2(amount2), iDur2(dur2) {}
void operator() (LPCHARACTER ch)
{
bool bOverride = true;
if (ch && ch->GetPlayerID() != casterPID)
{
if (pkSk->bPointOn != POINT_NONE)
{
ch->AddAffect(pkSk->dwVnum, pkSk->bPointOn, iAmount1, pkSk->dwAffectFlag, iDur1, 0, bOverride, false, casterPID);
bOverride = false;
}
if (pkSk->bPointOn2 != POINT_NONE)
{
ch->AddAffect(pkSk->dwVnum, pkSk->bPointOn2, iAmount2, pkSk->dwAffectFlag, iDur2, 0, bOverride, false, casterPID);
bOverride = false;
}
}
}
};
if (pkVictim && pkParty->IsMember(pkVictim->GetPlayerID()))
{
FPartyBuff f(pkSk, GetPlayerID(), iAmount, iDur, iAmount2, iDur2);
pkParty->ForEachNearMember(f);
}
}
But without them this part of the code calls IsMember on pkParty even when it is a nullpointer.
LPPARTY is defined as CParty*
Why is it happening?
For example, if I have a bool value v, I want a reference to !v that can change when v changes. An example use will be:
class A {
bool& isOpen;
A(bool& value): isOpen(value) {}
void f() {
if (isOpen) {
doSomething();
}
}
};
class B {
bool& isClosed;
B(bool& value): isClosed(value) {}
void g() {
if (isClosed) {
doSomething();
}
}
};
int main() {
bool isOpen = true;
A a(isOpen);
B b(negattive_reference_of(isOpen));
a.f(); // doSomething()
b.g(); // do nothing
isOpen = false;
a.f(); // do nothing
b.g(); // doSomething()
}
Is there anyway in C++ to acheive a similar effect?
Under the hood reference is equivalent to a constant pointer to some variable (compiler just gives you a syntax sugar of how to work with such pointers so that they are always initialized).
So you wan't to have the same variable and two different pointers to it, one of which will dereference to true and the other to false. That is obviously impossible.
The OOP -way to do it would be to pass not reference to boolean but some interface to your classes and use implementation that uses same boolean variable:
class IIsOpenProvider
{
public:
virtual ~IIsOpenProvider() = 0;
virtual bool GetOpenValue() = 0;
};
class IIsClosedProvider
{
public:
virtual ~IIsClosedProvider() = 0;
virtual bool GetClosedValue() = 0;
};
class ValueProvider : public IIsOpenProvider, public IIsClosedProvider
{
public:
bool GetOpenValue() override { return isOpen; }
bool GetClosedValue() override { return !isOpen; }
private:
bool isOpen;
};
class A {
IIsOpenProvider& isOpen;
A(IIsOpenProvider& value): isOpen(value) {}
void f() {
if (isOpen.GetOpenValue()) {
doSomething();
}
}
};
class B {
IIsClosedProvider& isClosed;
B(IIsClosedProvider& value): isClosed(value) {}
void g() {
if (IIsClosedProvider.GetClosedValue()) {
doSomething();
}
}
};
// usage
ValueProvider val;
A a(val);
B b(val);
I have the following code
typedef struct{
uint8_t carOpening:2;
uint8_t fCarElement:4;
}lockState_t;
enum Doors
{
DRIVER_DOOR = 0,
PASSENGER_DOOR,
...
NUMBER_OF_ELEMENTS
};
class DoorState
{
public:
DoorState(Doors door, uint8_t initialState)
{
fState.fCarElement = static_cast<uint8_t>(door);
if(initialState == SIG_VAL_DOOR_CLOSED)
{
fState.carOpening = static_cast<uint8_t>(DOOR_CLOSED);
}
else if(initialState == SIG_VAL_DOOR_OPENED)
{
fState.carOpening = static_cast<uint8_t>(DOOR_OPENED);
}
else
{
fState.carOpening = static_cast<uint8_t>(DOOR_UNKNOWN);
}
};
void checkSignal(uint8_t signal);
enum tState { DOOR_UNKNOWN = 0, DOOR_CLOSED, DOOR_OPENED };
private:
static const uint8_t SIG_VAL_DOOR_CLOSED = 0x00;
static const uint8_t SIG_VAL_DOOR_OPENED = 0x01;
lockState_t fState;
};
Then I have a few instances of this class, like:
DoorState fDriverDoorState;
DoorState fPassengerDoorState;
This is how I initialize the instances:
, fDriverDoorState(DRIVER_DOOR
, DS::instance().get<uint8_t>(DS::ComStatZvKlappen_StDswDrd_ID))
, fPassengerDoorState(PASSENGER_DOOR, DS::instance().get<uint8_t>(DS::ComStatZvKlappen_StDswPsd_ID))
Then I am checking if the state of the door has changed and publising a message if it has:
tState doorState = DOOR_UNKNOWN;
if (SIG_VAL_DOOR_CLOSED == signal)
{
doorState = DOOR_CLOSED;
}
else if (SIG_VAL_DOOR_OPENED == signal)
{
doorState = DOOR_OPENED;
}
if(doorState != static_cast<tState>(fState.carOpening))
{
fState.carOpening = static_cast<uint8_t>(doorState);
if(DOOR_UNKNOWN != doorState)
{
LooperEventBroker::publish(::csm::events::CsmEvents::VEHICLE_LOCK_STATE_EVENT(), &fState);
Logger::info(VEHICLE, "Door %s event published for %s",
doorState == DOOR_OPENED ? "openend" : "closed", opening2string(fState.fCarElement));
}
}
For the most part it is working perfectly. The strange part is that sometimes I see this log being posted:
"Door closed event published for INVALID DOOR", which should not happen as no instance is initialized with INVALID DOOR, and fCarElement, which stores the door type, is never modified. Which means that somehow fCarElement gets corrupted. Question is where or why?
As requested here is the implementation of opening2string function:
static const char* opening2string(uint8_t opening)
{
switch (opening)
{
case DRIVER_DOOR:
return "DRIVER DOOR";
case PASSENGER_DOOR:
return "PASSENGER DOOR";
...
default:
return "INVALID DOOR";
}
}
Regards,
Gabriel
I have the warnings from the gcc compiler showing the const char issue.
How to get rid of the warnings?
Thanks,
Michael
char * str_convert(int op) {
/*returns the string corresponding to an operation opcode. Used for screen output.*/
if(op == PLUS) {
return "plus";
}
else if (op == MULT) {
return "mult";
}
else if (op == SUBS) {
return "subs";
}
else if (op == MOD) {
return "mod";
}
else if (op == ABS) {
return "abs";
}
else if (op == MAX) {
return "max";
}
else if (op == MIN) {
return "min";
}
else {
return NULL;
}
}
I think the fix is adding const to the return type (to prevent modification of the contents).
I'd also change the if cascade to switch / case, but that's unrelated to the problem.
const char * str_convert(int op) {
/*returns the string corresponding to an operation opcode. Used for screen output.*/
switch (op) {
case ABS: return "abs";
case MAX: return "max";
case MIN: return "min";
case MOD: return "mod";
case MULT: return "mult";
case PLUS: return "plus";
case SUBS: return "subs";
default: return NULL;
}
}
You may also wish to consider using templated 'op' value as the compiler will replace the jump table it will use for the the switch statement implementation, evaluated at runtime, with a compile time evaluated version that calls on of N functions, depending on the template value.
template <int op>
const char * str_convert(void)
{
/*returns the string corresponding to an operation opcode. Used for screen output.*/
switch (op)
{
case ABS: return "abs";
case MAX: return "max";
case MIN: return "min";
case MOD: return "mod";
case MULT: return "mult";
case PLUS: return "plus";
case SUBS: return "subs";
default: return NULL;
}
}