State machine: Use transition matrix instead of nested switch cases C++ - c++

I am having difficulties with my state machine. I use a function that returns the new state based on input parameters oldState and two input parameters.
In this function I have a lot of nested switch cases. I'd rather use a 2x2 transition matrix but have no idea how to use it. I did make a transition table from the state diagram with sates and inputs.
But how exaclty do I use the 2 dim. array transition_table[3][4]?

You stated you currently have something like this:
StateType transition (StateType old, InputType one, InputType two) {
//... nested switch statements
return new_state;
}
So, it seems what you need is a 3-dimensional array:
#define MAX_STATES 12
#define MAX_INPUT_VAL 2
StateType transitionTable[MAX_STATES][MAX_INPUT_VAL][MAX_INPUT_VAL] = {
{ { StateA, StateB },
{ StateC, StateD } },
{ { StateE, StateF },
{ StateG, StateH } },
{ { StateI, StateJ },
{ StateK, StateL } },
//...
};
Then you would transition like this:
new_state = transitionTable[StateIndex(old)][one][two];
So, assuming that StateIndex(StateC) returns 2, then:
old = StateC;
new_state = transitionTable[StateIndex(old)][1][0];
assert(new_state == StateK);
would result in new_state holding StateK.

Given a matrix like this:
state1_input1 state1_input2 state1_input3
state2_input1 state2_input2 state2_input3
state3_input1 state3_input2 state3_input3
When you are in state n and receive input m, you look at row n, column m to find out the new state. Assuming you have 3 possible states and 4 possible inputs, all you need to do is:
state = transition_table[state][input]

Based on your description, you don't need a 2-dimentional array, 1 dimension is fine. It should be made this way:
void foo()
{
int States[2] = {1,2};
int currentState = 1;///initial state, let's say
int oldState;///prev. state
while(true)
{
if(currentState == 1 && *add any other condition that you need*)
{
<...>do something<...>
oldState = currentState;//saving the old state, in case you need it.
currentState = states[currentState]; //changing the state
}
else if( currentState == 2 && *add any other condition that you need*)
{
<...>some other code<...>
}
}
So you have an array of states. You then calculate the index of that array based on your input parameters (you said you use the old state and something else for it). After that you simply get the new state from the array by that index.
My explanation is a bit messy, so leave a comment if you need a clarification of some part.

Related

how to check if personID is in my_customers (see my example)

In C++, the interface for this file says
*If no soup left returns OUT_OF_SOUP
* If personID not found in my_customers AND numbBowlsSoupLeft>0 then give this person a bowl of soup (return BOWL_OF_SOUP)
* and record it by creating new customer struct using personID, numbBowlsSoup=1 and adding this struct to my_customers, be sure to decrement numbBowlsSoupLeft.
for my implementation, I'm trying to put
int Soupline::getSoup(int personID) {
if (numBowlsSoupLeft == 0) {
return OUT_OF_SOUP;
}
if (!(personID : my_customers) && numbBowlsSoupLeft > 0) {
}
But that second if statement is giving me syntax errros, I just want to know how to check to see if the personID is IN my_customers?
my_customers was created in the soupline interface using:
std::vector<customer> my_customers; // keeps track of customers
First you want to use find() to search a vector.
Second, please handle the case if numbBowlsSoupLeft < 0, because that can be a huge source of problem.
Third, your syntax error is the (personID : my_customers), the : is for iteration.
int Soupline::getSoup(int personID) {
if (numBowlsSoupLeft <= 0) { // handles negative numBowlsSoupLeft
return OUT_OF_SOUP;
}
bool found_customer = false;
for (auto c : my_customers) {
if (personID == c.person_id()) { // This is my guess on how the id is stored in customer class
// Logic to process soup for customer
found_customer = true;
break;
}
}
if (!found_customer) {
// Logic to process non-customer asking for soup?
}
}
Sorry i dunno what is the return integer is supposed to be, so it is not defined in my code example.

Exception Handling with Multiple Variables

I'm trying to learn more about exception handling while working on my program. I have multiple test variables I want to test and make sure it is within range with:
public bool IsWithinRange(TextBox textbox, string name, int min, int max)
{
double number = double.Parse(textbox.Text);
if (number < min || number > max)
{
MessageBox.Show(name + " must be between " + min.ToString() + " and " + max.ToString() + ".", "Entry Error");
textbox.Focus();
return false;
}
else { return true; }
}
And calling the method using:
bool condition;
condition = CheckAll();
if (condition == true) { condition = IsWithinRange(txtVar1, "Var1", 1, 50); }
if (condition == true) { condition = IsWithinRange(txtVar2, "Var2", -100, 100); }
if (condition == true) { condition = IsWithinRange(txtVar3, "Var3", 100, 200); }
This logic works, but I was curious to see if there was a more concise, better looking way of writing some form of systematic checking of variables one by one?
You can take advantage of a few things:
Are you able to assign meaningful names to the TextBox.Name properties? If so, you can omit the second parameter in "IsWithinRange" and simply call "Textbox.Name".
As of C# 6.0, there is now a syntax to interpolate strings. So the string passed into your your MessageBox.Show syntax can be made shorter and prettier.
You can immediately assign to "condition", and you can convert your "if" statements to combined "and" statements.
All together, your code can look like this:
bool condition =
CheckAll()
&& IsWithinRange(txtVar1, 1, 50)
&& IsWithinRange(txtVar2, -100, 100)
&& IsWithinRange(txtVar3, 100, 200);
// Some other code here
With your method looking like this:
public bool IsWithinRange(TextBox textbox, int min, int max) {
double number = double.Parse(textbox.Text);
if (number < min || number > max) {
MessageBox.Show($"{textbox.Name} must be between {min} and {max}.", "Entry Error");
textbox.Focus();
return false;
}
else
return true;
}
This is assuming you actually use "condition". If not, you can omit "bool condition = " and the code runs just the same.
But there are a few things to note. Your code will continue to run even if "CheckAll" is false or any "IsWithinRange" is false. This is true in my version above or in your own version. Yes, your user will get a message, but after he clicks "okay", the remaining code will run even if the checks fail.
Also, "IsWithinRange" might be misinterpreted by a teammate or even by yourself in the future. This is because it does more than just return true/false: it sends a message if false. This violates the principle of command-query separation.
An approach to these issues ignores brevity, as that is desired but never the highest goal. What you can do is create a class that validates, whose methods separate the tasks:
class Validator {
public bool isValid = true;
public List<string> messages = new List<string>();
public Validator CheckAll() {
// Whatever your logic is for this.
return this; // Return the instance of "Validator" that called this method
}
public Validator CheckRange (TextBox textbox, int min, int max) {
double number = double.Parse(textbox.Text);
if (number < min || number > max) {
messages.Add($"{textbox.Name} must be between {min} and {max}.");
isValid = false;
}
return this;
}
public void ShowErrorsToUser () =>
MessageBox.Show(string.Join(Environment.NewLine, messages));
}
Which you would use like this:
var validator =
new Validator()
.CheckAll()
.CheckRange(txtVar1, 1, 50)
.CheckRange(txtVar2, -100, 100)
.CheckRange(txtVar3, 100, 200);
if (!validator.isValid) {
validator.ShowErrorsToUser();
txtVar1.Focus();
return; // Stop code execution!
}
// Continue with your normal logic that utilizes your textbox values.
I'll leave it to you to decide whether the class-based approach is worth your time. But I present it to you as a different way to think.

Why is the boolean value within a structure within a vector not being updated?

This might sound like a very basic question, but I have trying to fix a simple bug for over an hour now and I can't seem to understand what's happening.
I have the following structure declaration in my header file:
struct StudentBody
{
string name;
Vec2 position;
bool disabled;
StudentBody(string name, Vec2 position) : name(name), position(position) {}
};
This structure is being filled into a vector of type:
std::vector<StudentBody> students_real;
Like this:
students_real =
{
StudentBody("student1",Vec2(DISPLAY_WIDTH - 50, LOWER_MARGIN + 100)),
StudentBody("student2",Vec2(DISPLAY_WIDTH - 100, LOWER_MARGIN + 100)),
StudentBody("student3",Vec2(DISPLAY_WIDTH - 150, LOWER_MARGIN + 100)),
StudentBody("student4",Vec2(DISPLAY_WIDTH - 200, LOWER_MARGIN + 100))
};
By default all of the students have their "disabled" set to false.
Then I have an "update" method that gets triggered with the screen refresh rate, and within that method I have the following code:
for (auto it = students_real.begin(); it != students_real.end(); it++)
{
auto student_to_check = *it;
CCLOG("student %s disabled -> %i",student_to_check.name.c_str(),student_to_check.disabled);
if (student_to_check.name == "student1" || student_to_check.disabled) {
continue;
}
bool disableStudent = true;
//... A custom condition here checks if "disabledStudent" should become false or stay as true...
if (disableStudent)
{
CCLOG("Disabling %s",student_to_check.name.c_str());
student_to_check.disabled = true;
CCLOG("student %s disabled -> %i",student_to_check.name.c_str(),student_to_check.disabled);
}
}
The problem here is that the "disabled" flag is not staying as true. When I check the condition at first it's false. Then I check my second condition too and if it's satisfied I set it to true. However the next time this for loop is started the condition is back to false.
This makes me believe that my "auto student_to_check = *it;" gives me a copy of the structure to handle it but not the structure itself? Or what is going on? Why can't I modify the value of the structure within the vector?
This:
auto student_to_check = *it;
declares a local variable that is a copy of the structure in the vector. The iterator points to the structure in the vector, so you can use:
auto student_to_check = it;
and:
student_to_check->disabled = true;
or more simply the following to access anything in the vector's structure. Then you don't need the local variable:
it->disabled = true;
Even better would be to use C++11's range-based for loop, as #sp2danny commented:
for(auto& student_to_check : students_real)
student_to_check will reference the structure in the vector instead of a local copy, and the rest of your code remains as is.

How to store the state of a deeply-nested loop?

I am trying to refactor the following code, as I don't think it is structured well.
Can you think of a more elegant way to do this?
Bar::Bar()
{
m_iter1 = 0;
m_iter2 = 0;
}
bool Bar::foo()
{
_reinitialize();
for (; m_iter1 < 2; m_iter1++, m_iter2 = 0) {
_log("TRYING METHOD: [%d]", m_iter1);
if (_something_wrong(m_iter1)) {
return false;
}
for (; m_iter2 < 6; m_iter2++) {
if (_try_with_these_params(m_iter1, m_iter2, ...)) {
m_status = success;
// store next iteration in case we need to retry.
m_iter2++;
return true;
}
}
}
return false;
}
bool try_foo(Bar& bar)
{
if (bar.foo()) {
if (meet_some_criteria) {
return true;
} else {
bar.invalidate();
// retry. the Bar object stores the state.
try_foo(bar);
}
} else {
return false;
}
}
int main()
{
Bar bar;
if (try_foo(bar)) {
_log("SUCCESS");
} else {
_log("FAILURE");
}
}
The code loops over different parameter sets and tries to perform some action with these parameters. If the action is successful, then external code may invalidate the action and attempt to retry. The object which performs the action stores the state, so that external code may retry and re-enter the parameter loop at the place it left off.
The output using one parameters affect others, so the calculations need to be accomplished locally within the Bar class.
I would like to extend this idea to more dimensions, but doing so with the current design is clumsy.
A lot here depends on how expensive the various actions are.
If initially generating a candidate parameter set is cheap (and the set isn't too large), then you might want to just generate all the candidate sets, then give that result to the external code and try each in turn until you find one that the external code will accept.

How to refactor this while loop to get rid of "continue"?

I have a while (!Queue.empty()) loop that processes a queue of elements. There are a series of pattern matchers going from highest-priority to lowest-priority order. When a pattern is matched, the corresponding element is removed from the queue, and matching is restarted from the top (so that the highest-priority matchers get a chance to act first).
So right now it looks something like this (a simplified version):
while (!Queue.empty())
{
auto & Element = *Queue.begin();
if (MatchesPatternA(Element)) { // Highest priority, since it's first
// Act on it
// Remove Element from queue
continue;
}
if (MatchesPatternB(Element)) {
// Act on it
// Remove Element from queue
continue;
}
if (MatchesPatternC(Element)) { // Lowest priority, since it's last
// Act on it
// Remove Element from queue
continue;
}
// If we got this far, that means no pattern was matched, so
// Remove Element from queue
}
This works, but I want to refactor this loop in some way to remove the use of the keyword continue.
Why? Because if I want to outsource a pattern matching to an external function, it obviously breaks. E.g.
void ExternalMatching(...)
{
if (MatchesPatternB(Element)) {
// Act on it
// Remove Element from queue
continue; // This won't work here
}
}
while (!Queue.empty())
{
auto & Element = *Queue.begin();
if (MatchesPatternA(Element)) {
// Act on it
// Remove Element from queue
continue;
}
ExternalMatching(...);
if (MatchesPatternC(Element)) {
// Act on it
// Remove Element from queue
continue;
}
// If we got this far, that means no pattern was matched, so
// Remove Element from queue
}
I don't want to have to write repetitive if statements like if (ExternalMatching(...)) { ... continue; }, I'd rather find a cleaner way to express this logic.
This simplified example might make it seem like a good idea to make pattern matching more general rather than having distinct MatchesPatternA, MatchesPatternB, MatchesPatternC, etc. functions. But in my situation the patterns are quite complicated, and I'm not quite ready to generalize them yet. So I want to keep that part as is, separate functions.
Any elegant ideas? Thank you!
If you have access to C++11 I would like to suggest another solution. Basicaly I created a container of handlers and actions that can be adjusted in runtime. It may be a pro or con for your design depending on your requirements. Here it is:
#include <functional>
typedef std::pair<std::function<bool(const ElementType &)>,
std::function<void(ElementType &)> > HandlerData;
typedef std::vector<HandlerData> HandlerList;
HandlerList get_handlers()
{
HandlerList handlers;
handlers.emplace_back([](const ElementType &el){ return MatchesPatternA(el); },
[](ElementType &el){ /* Action */ });
handlers.emplace_back([](const ElementType &el){ return MatchesPatternB(el); },
[](ElementType &el){ /* Action */ });
handlers.emplace_back([](const ElementType &el){ return MatchesPatternC(el); },
[](ElementType &el){ /* Action */ });
return handlers;
}
int main()
{
auto handlers = get_handlers();
while(!Queue.empty()) {
auto &Element = *Queue.begin();
for(auto &h : handlers) {
// check if handler matches the element
if(h.first(Element)) {
// act on element
h.second(Element);
break;
}
}
// remove element
Queue.pop_front();
}
}
I would recommend using a function that does the pattern matching (but does not act on the result) and then a set of functions that act on the different options:
enum EventType {
A, B, C //, D, ...
};
while (!queue.empty()) {
auto & event = queue.front();
EventType e = eventType(event); // Internally does MatchesPattern*
// and returns the match
switch (e) {
case A:
processA(event);
break;
case B:
processB(event);
This way you clearly separate the matching from the processing, the loop is just a simple dispatcher
Consider an interface:
class IMatchPattern
{
public:
virtual bool MatchesPattern(const Element& e) = 0;
};
Then you can organize a container of objects implementing IMatchPattern, to allow for iterative access to each pattern match method.
You can change your ExternalMatching to return bool, indicating that the processing has been done. This way the caller would be able to continue evaluating if necessary:
bool ExternalMatching(...)
{
if (MatchesPatternB(Element) {
// Act on it
// Remove Element from queue
return true;
}
return false;
}
Now you can call it like this:
if (ExternalMatchin1(...)) continue;
if (ExternalMatchin2(...)) continue;
...
if (ExternalMatchingN(...)) continue;
Ok, I ended up rewriting the loop more akin to this.
Huge thanks and credit goes to Yuushi, dasblinkenlight, David Rodríguez for their help; this answer is based on a combination of their answers.
bool ExternalMatching(...)
{
bool Match;
if ((Match = MatchesPatternX(Element))) {
// Act on it
} else if ((Match = MatchesPatternY(Element))) {
// Act on it
}
return Match;
}
while (!Queue.empty())
{
auto & Element = Queue.front();
if (MatchesPatternA(Element)) { // Highest priority, since it's first
// Act on it
} else if (MatchesPatternB(Element)) {
// Act on it
} else if (ExternalMatching(...)) {
} else if (MatchesPatternC(Element)) { // Lowest priority, since it's last
// Act on it
}
// Remove Element from queue
}
Now, I know there's further room for improvement, see answers of Mateusz Pusz and Michael Sh. However, this is good enough to answer my original question, and it'll do for now. I'll consider improving it in the future.
If you're curious to see the real code (non-simplified version), see here:
https://github.com/shurcooL/Conception/blob/38f731ccc199d5391f46d8fce3cf9a9092f38c65/src/App.cpp#L592
Thanks everyone again!
I would like to suggest a Factory function that would take the Element and create an appropriate handler and return the interface pointer to the handler.
while (!Queue.empty())
{
auto & Element = *Queue.begin();
// get the appropriate handler object pointer e.g.
IPatternHandler *handler = Factory.GetHandler(Element);
handler->handle();
// clean up handler appropriately
}