Creating a bound on a value within the program - c++

I am currently writing a program that will take in a lot of user input and as a result will change certain variables.
What I am trying to accomplish is to set a bound for these values, such as the variable "age" of the object cannot exceed 50 and is greater than or equal to 0.
range: [0, 50]
What would be the best way to the best way to set a maximum for the value?
For example:
age = 46
age = age + 10 // new value of age would be 50 as that is the maximum.
I know I could implement this with if statements within the scope of the operations
if (age > 50) {age = 50;}
else if (age < 0) {age = 0;}
following the operation to change the value.
I am going to be dealing with many different variables within the structure such as age, hunger, happiness, etc. and would rather not have to repeat the if statements for each one.
Is there a way I can define bounds on the variables previously and if it ever leaves the bounds it throws an error or returns a variable?
If it helps my current implementation of the changing of values is:
with an enum 'Operation' defining the operations seen below.
int modifyHunger(Operation operation, int value)
{
switch(operation)
{
case INCREMENT:
myHunger = myHunger + value;
break;
case DECREMENT:
myHunger = myHunger - value;
break;
case REINIT:
myHunger = 0;
break;
case INIT:
myHunger = value;
break;
default:
break;
}
return myHunger;
}

There are several ways to tackle this question, but my personal choice is using min and max over direct conditionals. So for example we can implement a function to clamp values like this:
template <typename T>
T clamp(const T &value, const T &lower, const T &upper)
{
return max(lower, min(value, upper));
}
The advantage to this method is that it is generalized for any type which can be used with min and max.
Edit:
Just to expand on the idea further you can also make a class which overloads basic math operators and implicitly calls clamp. Which can be even more elegant, and in that case probably won't need a template.
It's up to you to expand this into something comfortable for your taste and use case.

Related

C++ How can I convert a string to enum to use it in a switch?

I have a list of commands that if a user inputs then it will call separate functions. Talking to a friend he said I should use switch, which is faster and easier to read over "if, else if, else" statements.
When checking how to implement this I realised that I wouldn't be able to because the input is a string and for a switch to work I would need to cast it to an enum and it seems like the most straightforward option I have is to map each of the options like below.
header
enum class input
{
min,
max,
avg,
count,
stdev,
sum,
var,
pow
};
map<string, input> inMap
{
{ "min", input::min },
{ "max", input::max },
{ "avg", input::avg },
{ "count", input::count },
{ "stdev", input::stdev },
{ "sum", input::sum },
{ "var", input::var },
{ "pow", input::pow }
};
Is there a more accessible option to use enum where I don't have to map each value? This is very time-consuming and I'm not seeing any benefits at the moment.
cpp file
void test::processInput(vector<string> input) {
switch (inMap[input[0]]) {
case inMap::min:
MIN(input);
break;
case inMap::max:
MAX(input);
break;
case inMap::avg:
AVG(input);
break;
case inMap::count:
COUNT(input);
break;
case inMap::stdev:
STDEV(input);
break;
case inMap::sum:
SUM(input);
break;
case inMap::var:
VAR(input);
break;
case inMap::pow:
POW(input);
break;
default:
std::cout << "Error, input not found" << std::endl;
}
}
I read some posts about hashing the value instead, is this a good option? At this point wouldn't be just better to continue using if, else if, else?
Thanks!
Why not have a map of string to function.
Then you don't need to convert to an enum.
using Action = void(std::vector<std::string>);
using ActionFunc = std::function<Action>;
using ActionMap = std::map<std::string, ActionFunc>;
void MIN(std::vector<std::string>){}
... etc
ActionMap inMap
{
{ "min", MIN },
{ "max", MAX },
{ "avg", AVG },
{ "count", COUNT },
{ "stdev", STDDEV },
{ "sum", SUM },
{ "var", VAR },
{ "pow", POW }
};
void test::processInput(std::vector<std::string> input) // May want a ref here.
{
auto find = inMap.find(input[0]);
if (find == inMap.end()) {
std::cout << "Error, input not found" << std::endl;
return;
}
find->second(input);
}
Either way you are doing a number of string compares, and string compares are slow.
When you do the if/else you are on average doing n/2 compares if you have n target strings. So 4 compares for the 8 keywords.
When you do a map, this reduces to log2(n) compares - so 3 compares for 8 entries. Oh and one extra backwards compare to check if the value equals the index. If it is both not less and not greater, then it must be equal.
Given the map code is more complex, you don't win, as you have seen. With (many) more keywords to check for, you will get a benefit.
If you use unordered_map, then the string is converted into an integer hash value, and that is effectively used to directly look up the answer. Calculating the hash can be a slow process, though, and a final compare will be done to check the found value exactly matches. There is also a higher set-up cost generating the hashes for all the keywords. In this particular case, you could write your own hash function which just takes the first 2 characters, and perhaps trim the range down, which would be somewhat faster than the default string hash function.
The final alternative is to do a character-by-character look-up. If the first character is 'm' then you immediately reduce the check to 2 options. 's' gives 2 other options, and so-on. For a small data set like this, just doing that first character filter will make a difference, doing a second character gives you unique checks. These are simple character compares, not whole string compares, so much faster!
There is no trivial stdlib data structure that can help you with this. You could write it out longhand as 2 levels of nested case statements:
switch (input[0][0])
{
case 'm':
switch (input[0][1])
{
case 'i':
if (input[0].compare("min")==0) return MIN;
return NO_MATCH;
case 'a':
if (input[0].compare("max")==0) return MAX;
return NO_MATCH;
}
return NO_MATCH;
case 's':
switch(input[0][1])
{
case 't':
case 'u':
}
... etc
(as an exercise for the reader, there is a version of string::compare() that will skip the characters you have already compared)
You can build your own tree structure to represent this word look-up. If you add the ability to skip through multiple letters in the tree you can produce a fairly efficient string dictionary look-up which costs little more than a single string compare.
Another option is that with a sorted vector of string/target pairs you can do a custom binary chop function that takes advantage of knowing that all the strings still in the search span have the same initial letters, and do not need to be compared any more. In this case, it won't make much difference, but with hundreds of keywords, this would be much more maintainable than the manual case statements.
But in the end, most keyword detecting code is fast enough using the simple hash table provided by unordered_map.

I want return type pointer but i want my function to return pointer of derive class

Dragon* Dragon::spawn() {
int x = rand() % 5;
int y;
if (!if_locked(x)) //is a function to see if that id is unlocked because i want some dragon to be generated only if you have certain xp so it will call func again until unlocked id is generated
spawn();
else
y = unlocking(m); // Y is generated form 1-5, I have assigned Id to each derive class whosoever id matches Y that pointer will be returned
if (y == 1) {
GroundDragon* pt;
return pt;
}
if (y == 2) {
WaterDragon* st;
return st;
}
if (y == 3) {
IceDragon*bt;
return bt;
}
if (y == 4) {
FireDragon* ct;
return ct;
}
if (y == 5) {
DarkDragon* dark;
return dark;
}
}
As you can see im making syntax mistakes i hope someone can guide me
The return type of function is base class and all the classes in if statement are derive class
so i can later use this function
template<class T>
void spawner(T*) {// I will spawn() fucntion as perimeter at time of call
T = new T;
}
Forgive me if im repaeting question the last time i post it didnt get attention i was expecting so i modifed my code a bit hopeful it is clear now`
int Dragon::unlocking(Mage m) {
if (m.getxp() <= 50 and m.getxp() <= 100) {
unlock[0] = 1;
cout << "Congratulation GroundDragon unlocked " << endl;
return 1;
}
if (m.getxp() > 100 and m.getxp() < 150) {
unlock[1] = 1;
cout << "Congratulation WaterDragon unlocked " << endl;
return 2;
}
if (m.getxp() > 150 and m.getxp() < 175) {
unlock[2] = 1;
cout << "Congratulation IceDragon unlocked " << endl;
return 3;
}
if (m.getxp() > 175 and m.getxp() < 500) {
unlock[3] = 1;
cout << "Congratulation FireDragon unlocked " << endl;
return 4;
}
if (m.getxp() > 500) {
unlock[4] = 1;
cout << "Congratulation DarkDragon unlocked " << endl;
return 5;
}
}
bool Dragon::if_locked(int x) {
if (unlock[x] == 1) {
return true;
}
else
return false;
}
*Im not comfortable with smartpointer(i have never used them before but i would love to use them if you show me how to call it main *
I used raw pointer but it is still showing me errors please help mw
The idea is sound, it's just the execution that failed.
If you want to have a factory function that will return different objects that will then behave polymorphically, this is perfectly fine, with one important thing - you need to return actual objects.
Your factory function has a return type of Dragon*. This means that whatever value you return, it will be a pointer pointing to (some sort of a) Dragon. However, the value of that pointer can point to an object that is actually an instace of FireDragon, IceDragon etc. When you create an instance of such an object, the pointer to such instance can then get converted to the appropriate return type and returned.
In your case though, while you're creating temporary objects of type pointer-to-some-sort-of-dragon, you're not actually filling them with instances. They all are created with an unspecified value, and that value is then converted to an unspecified value of type Dragon*, with no way to extract the information which type it was converted from.
So, in order to make it work in a usual fashion, we just need to create a new instance of appropriate type and return it. We don't ever want to return raw pointers from functions when transferring ownership, so std::unique_ptr is a much better alternative:
std::unique_ptr<Dragon> Dragon::spawn() {
int x = rand() % 5;
/* note - this bit of code doesn't make any sense whatsoever
int y;
if (!if_locked(x)) //is a different function
spawn();
else
y = unlocking(m); //is also a different function
*/
// note that `rand() % 5` will produce values 0 through 4.
switch(x) {
case 0: return std::make_unique<GroundDragon>();
case 1: return std::make_unique<WaterDragon>();
case 2: return std::make_unique<IceDragon>();
case 3: return std::make_unique<FireDragon>();
case 4: return std::make_unique<DarkDragon>();
}
}
Now you don't need the spawner function at all; you can directly use the returned value.
I think the first important lesson to give is about initializing pointers.
The line
GroundDragon* pt;
declares that there is a pointer to a GroundDragon object, so far so good. However, this does not create an object.
As an analogy: you created a direction sign that is able to point into the direction of a village, but you do not build an actual village for it to point towards. And right now, it just points into some random direction.
Being uninitialized, pt contains a random value, not the address of an existing object of type GroundDragon. Doing anything with it will most likely result in bad things (it is undefined behaviour in particular).
In order to initialize it, you would write it like
GroundDragon* pt = new GroundDragon;
This creates an objects of type GroundDragon on the heap and assigns it's address to pt.
Also note that every new needs a delete to keep the memory clean, just to mention this preemptively.
This is very essential knowledge - make sure to understand this.
I wanted to write this in order to show you how to work with raw pointers, as an addition to the answer of Bartek Banachewicz, who did not show the way to initialize raw pointers. What he then does, using smart pointers, is clearly a way better approach than using raw pointers, though. However, I'd say that it is quite important that you are also able to work with raw pointers. Make sure to be able to do both in the long run, and use smart pointers whenever you can.
Edit: Now for the other part of your code,
int x = rand() % 5;
int y;
if (!if_locked(x)) //is a function to see if that id is unlocked because i want some dragon to be generated only if you have certain xp so it will call func again until unlocked id is generated
spawn();
else
y = unlocking(m);
First of all, please be aware that calling spawn(); ignores the return value. Which means, it has no effect at all. What you probably wanted to write is return spawn();.
Second, if(!if_locked(x)) seems to me to be the contrary of what it should be. "if not locked" means "if unlocked", and in that case, it should not try it again but instead proceed, right?
And, is the Mage m that you give to unlocking a member of Dragon? Sounds like it rather should be a pointer, if you don't especially want a relationship like Dragon owns Mage.
In any case, I would keep unlocking out of spawn. A method like spawn says that it is good for spawning. Especially printing that something is unlocked is not something I would intuitively understand a part of the spawning process. Also, I would name it differently, as "unlocking" is a status rather than a command. Go like check_for_new_unlocks or something like that, which sounds like a command. And do it separately from spawn.
Also, note that you check for narrow experience intervals - are you sure that it can't happen that an interval is never triggered, as the character might advance over the interval with never calling the method in between?
Furthermore, I'd call the array that says if something is unlocked differently. "unlock" sounds like a command. How about "available"?
Also, I find the recursive call of spawn to be less readable as trying out other values for x, but that is opinion. I'd go like
int x = rand() % 5;
while(not available[x])
{
x = rand() % 5;
}
Maybe this can be done more clever, though, based on the actual mechanics. You could create the random variable like int x = rand() % total_available(); for instance.
Note that a lot of this is somewhat opinion based. In this regard, I want to point you towards CodeReview - as soon as your code works correctly, you might want to post it there for people to help you improve it in several different regards.

How to generate a boolean condition during runtime in C++?

I want to be able to generate a boolean condition during the runtime based on the states of some variables. My task looks simple at first. I have a large if () else if () statement what needs to determine if the number is in a certain range. It then does something depending on whether that number is inside that range.
Here's pseudocode to demonstrate what I want:
void fun(int num, int offset = 0) {
if (0...60) {
// do something
} else if (60...180) {
// do something else
} else if (180...240) {
} else if (240...360) {
}
}
The first if statement should work like this:
if (0 >= num && num <= 20) {
// do something
}
The caveat here is that in addition to int num, there is another parameter passed in, which I call the offset. The structure of the code here, including the do something inside the { } is the same. The only things that need to change are are ranges, based on the value of the offset. By the way, this is not a default parameter here, it is just pseudocode demonstrating what the value of int offset was passed in.
void fun(int num, int offset = 120) {
if (120...180) {
// do something
} else if (180...300) {
// do something else
} else if (300...360) {
} else if (360...120) {
}
}
That last else if () statement has been giving me some trouble.
} else if (360...120) {
}
What I'm actually trying to write here is:
} else if (num >= 360 || num <= 120) {
}
The reason for this is that my int num may have a value > 360. However, in that case for the purpose of my application it has to "wrap around" and be treated as a value 0...120.
This is for a mathematical application here. Whenever you have int num > 360, you go around the full circle and you end back at 0 where you started. So that is the effect which I want to achieve.
I don't want to write extra functions. I want my code to be generic because many different values for int num and int offset may be passed into my function. I want to generate the necessary conditions during the runtime based on the value of int offset.
The main problem here is that in the first situations, when int offset = 0 my condition is
} else if (240 >= num && num <= 360) {
}
However, for a different offset we wrap around and so I have to change the format of the entire condition! For example, when int offset = 120, as shown above:
} else if (num >= 360 || num <= 120) {
}
The problem is that in the first situation I had the && in the last else if (), but now I have the || to convey the same meaning. What I'm looking for is a way to be able to manipulate the operators inside the conditional statements as mere chars in a string, then "paste" the completed condition into the if () statements during the runtime!
What's even worse is that this "wrapping around" can occur inside any one of the if () statements, not just the last one. It is based on the value of the offset.
I can't use preprocessor tricks, because I want this to work during the runtime. Maybe it is possible to use function pointers or something for this, but I don't know how to do that. Please note that the ... above is not real C++ code, it is pseudocode! I'm aware that there is a "range-based" switch statement in C++, but I can't use that because of the "wrapping around" property mentioned above.

C++ indexed access to structure variables of different types

I have a number of bool and int variables, that I need to access by some sort of index. I found a way to do so, but it seems a bit too complicated. Is there a way to do this in more elegant way?
For now in header file I have structure
struct FDialogueFlags
{
bool tmpFlag1;
bool tmpFlag2;
// bool tmpFlagX;
int tmpState1;
int tmpState2;
// int tmpStateX;
};
and enumeration
enum class Eflags
{
// NAME = flag_ID,
TMP_FLAG_1 = 1,
TMP_FLAG_2 = 10,
// TMP_FLAG_X = XX,
TMP_STATE_1 = 101,
TMP_STATE_2 = 110,
// TMP_STATE_X = XXX,
};
And in source file I have function, that returns values for given index - flag_ID
int GetFlagValue(int flag_ID)
{
switch (Eflags(flag_ID))
{
case (Eflags::TMP_FLAG_1):
return flagsAndStates.tmpFlag1;
break;
case (Eflags::TMP_FLAG_2):
return flagsAndStates.tmpFlag2;
break;
/*case (Eflags::TMP_FLAG_X):
return flagsAndStates.tmpFlagX;
break;*/
case (Eflags::TMP_STATE_1):
return flagsAndStates.tmpState1;
break;
case (Eflags::TMP_STATE_2):
return flagsAndStates.tmpState2;
break;
/*case (Eflags::TMP_STATE_X):
return flagsAndStates.tmpStateX;
break;*/
default:
break;
}
}
That way everytime I need to add new "flag" or "state" I have to edit 3 places in my code.
Besides, if I need to access any "flag" or "state" by it's name written in enum, I can not do so, because Eflags (TMP_FLAG_1) returns TMP_FLAG_1 and not a number.
The other important thing, I'd like to keep variable namings, there might be up to hundred of this "flags" and "states" and it's crusial for them to have unique names and not just iterative numbers (Code above is just an example, in the end product I would name all of them according to their meaning)
If possible I'd like to avoid using std::map since it isn't supported natively by UE4.
So, the core idea is to access certain amount of variables of different numeric types by given number, possibly keeping variable naming.
Assuming you are asking for syntactic alternatives, Can you use tuples? Here - http://en.cppreference.com/w/cpp/utility/tuple
They are similar to structures and you can use std::get to retrieve values with index-based method. You can then use if statements for comparisons instead of switch statement.
Example -
#include <iostream>
#include <tuple>
int main()
{
auto t = std::make_tuple(1, true, 25);
std::cout << std::get<0>(t) << "\n"
<< std::get<1>(t) << "\n"
<< std::get<2>(t) << "\n";
}
IDEONE
I don't have any experience with UE4 and what native support means, but there are numerous drop-in alternatives to std::map like this one.

switch case on char*

It is a piece of code that gives me error:
const char* name = pAttr->Name(); // attribute name
const char* value = pAttr->Value(); // attribute value
switch(name) // here is where error happens: must have integral or enum type
{
case 'SRAD': // distance from focal point to iso center
double D = atof(value);
break;
case 'DRAD': // distance from iso center to detector
break;
default:
break;
}
The switch(name) is where error happens. It says it must be a integral or enum type. So how do I do switch case, or equivalent, on a char* type?
You cannot use switch here; as the error says, const char* is not supported. It's a good thing, too, because comparing two C-strings through pointers only compares the pointers, not the strings they point to (consider "hello" == "world").
Even if it were, you're trying to compare your C-string to multicharacter literals, which is certainly not what you intended, not least of all because they have type int and an implementation-defined value; I guess you meant to write "SRAD", not 'SRAD'.
Since you're using C++, you should do this:
const std::string name = pAttr->Name();
const std::string value = pAttr->Value();
if (name == "SRAD") {
double D = atof(value.c_str()); // use std::stod(value) in C++11
// ...
}
else if (name == "DRAD") {
// ...
}
else {
// ...
}
(I also fixed your use of name in the initialisation of D; Remy's right — you must have meant value here since "SRAD" cannot possibly be interpreted as a double.)
Another option is to use a local map to store integral values corresponding to the string values, get the integral value from the string, then, use switch on the integral value.
enum { SRAD = 1, DRAD, ... };
static std::map<std::string, int> localMap;
// Fill up the map.
if ( localMap.empty() )
{
localMap["SRAD"] = SRAD;
localMap["DRAD"] = DRAD;
}
const char* name = pAttr->Name(); // attribute name
const char* value = pAttr->Value(); // attribute value
int val = localMap[name];
switch (val)
{
case SRAD: // distance from focal point to iso center
{
double D = atof(value);
break;
}
case DRAD: // distance from iso center to detector
break;
default: // name is unknown
break;
}
Ok, this is totally, completely EVIL, but I have done it, and it does work:
// Must be a #define because an inline func won't give you a constant
#define MAKECODE(p) ((((p)[0])*0x01000000) \
+ (((p)[1])*0x00010000) \
+ (((p)[2])*0x00000100) \
+ ((p)[3]) )
// Note: I did not verify that the parenthesis matched.
switch(MAKECODE(name))
{
case MAKECODE("SRAD"): // distance from focal point to iso center
double D = atof(name);
break;
case MAKECODE("DRAD"): // distance from iso center to detector
break;
default:
break;
}
NOTE: BAD things will happen if the string name points to is less than 4 characters. Different bad things will happen is the string in the case statements are less than 4 characters (but probably just a compiler error).
this answer posted mostly for fun, but it will work if your name string is guaranteed to always be 4 bytes long.
#include <iostream>
using namespace std;
// precondition: name is exactly 4 chars in length
uint32_t convert(const char* name)
{
uint32_t val = uint32_t(name[3])
+ (uint32_t(name[2]) << 8)
+ (uint32_t(name[1]) << 16)
+ (uint32_t(name[0]) << 24);
return val;
}
int main()
{
const char* name = "SRAD"; // attribute name
const char* value = "10"; // attribute value
switch(convert(name)) // convert the string value to integral type uint32_t
{
case 'SRAD': // use arcane knowledge of C to construct an int32 representation of ascii digits
{
double D = atof(value);
cout << "SRAD " << D << endl;
break;
}
case 'DRAD': // distance from iso center to detector
cout << "some operation on value here " << endl;
break;
default:
break;
}
return 0;
}
A switch statement can only evaluate an expression of an integral or enumeration type (or convertible to such a type), and the expression in each case label must be a constant expression.
'SRAD' is not a string literal. It's a character literal with an implementation-defined value of type int. (This is a nearly useless language feature that I've seen used by mistake more than I've seen it used correctly.)
If you want to use C-style language features, avoiding things like C++'s std::string, the equivalent would be an if/else chain:
if (strcmp(name, "SRAD") == 0) {
// ...
}
else if (strcmp(name, "DRAD") == 0) {
// ...
}
else {
// ...
}
If you use std::string (which is advisable), the code would be similar, except that you can use == rather than strcmp.
You could set up a data structure that lets compute a discrete value that you can then use in a switch/case statement, as R Sahu's answer suggests. This would save the overhead of potentially doing N string comparisons. In my opinion, that would be overkill for a simple case like this. If your actual code is larger and more complex, it's worth considering.
Or you might consider redesigning your data structure so that you store and test an enumeration value directly, and then get a string value from that enumeration value via a lookup table.