Control execution flow for better code design - c

I'm not sure how exactly to address this problem, I hope you guys can help me.
I'm creating a card game in C (a text-only game that runs on the terminal window) called truco. It is a best-of-3 game that goes until one team reaches 12 or more points, so we have three tricks (let's call it round) each worth 2 points and the game continues with up to three rounds played until one team reaches 12 points.
When playing truco one can "ask for truco" to raise the stake of the match (I'm calling the best of three tricks a match), and the other player can accept, refuse or raise the stake again (essentially accept and then ask for truco).
I'm currently trying to implement this functionality, but my code is probably not the best design as I am suffering to add the "refuse" option, when a player refuses the truco, the other should be given as the winner (of that match) immediately.
And here comes my question, suppose the user asks for truco on the first trick, and the CPU refuses (the game is just you against the CPU for now) how do I "skip" all other code related to other tricks and set the user as the winner for that match?
I don't know how to design the code to allow this kind of feature, in normal cases two or three tricks should be played, but if some player asks for truco and the other refuses the game should ignore the remaining tricks and all other functionalities relating to it, going to the end of the match, updating the score and start another match.
Below I created a small reproducible code to clarify things (just note that I removed and altered a lot of code to keep it simple):
#include <stdio.h>
#include <stdbool.h>
// variable to store the result of the trick and also the final result of the match
int current_result = 0;
void ask_truco()
{
printf("asking truco...\ntruco refused\n");
// game should verify current_result and skip to reset_deck
current_result = 1;
}
void play_trick()
{
printf("playing trick\n");
// simulating that match should be interrupted and finished
ask_truco();
// this should be skipped, but not in normal situations
printf("do something...\n");
}
int check_winner()
{
printf("checking winner\n");
// hard-coded CPU wins
return 2;
}
void reset_deck()
{
printf("resetting deck\n");
}
int play_match(void)
{
// asking for truco here, second and third tricks should not be played
play_trick();
while (true)
{
play_trick(); // while loop helps play second and third trick
current_result = check_winner();
// from ask_truco, I should go back here
if (current_result == 1)
{
printf("increasing user score\n");
break;
}
else if (current_result == 2)
{
printf("increasing cpu score\n");
break;
}
}
// resetting deck of cards
reset_deck();
return 0;
}
int main(void)
{
play_match();
}
In the actual project, I have a few files and functions, if I just use ifs and flags I will end up with a mess, is there a better way to do this? I was wondering if the event-driven design would help me...

Okay, after reading the comments some of you provided me, especially #Fe2O3 and after strungling with myself a little bit I implemented the approach presented to me and manage to solve the problem. I would like to take the opportunity to explain what I did.
First of all, let me explain what my code was before, in my question above I committed the error (as some of you pointed) to remove too much of my code, which prevented you to fully understand what my code was doing.
I will start showing you three files of my project, again some of the things were removed or altered, but this time I think it's pretty concise and still understandable.
My types definition
// types.h
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define TOTAL_CARDS_NUMBER 40
#define TOTAL_HAND_CARDS_NUMBER 3
enum suits
{
spades = 1, // (♠)
hearts, // (♥)
diamonds, // (♦)
clubs // (♣)
};
enum rank
{
four = 1,
five,
six,
seven,
queen,
jack,
king,
ace,
two,
three
};
enum trumpcards
{
facedown = 0,
fourclubs = 14,
sevenhearts = 13,
acespades = 12,
sevendiamonds = 11
};
typedef struct card
{
enum suits suit;
enum rank rank;
bool available;
int value;
} card;
typedef struct player
{
card cards[TOTAL_HAND_CARDS_NUMBER];
int *player_tentos;
} player;
typedef struct player_action
{
int choice;
bool ask_truco;
bool hide_card;
} player_action;
enum round_result
{
TIE,
WIN,
LOSE
};
typedef struct trick
{
enum round_result result;
bool is_tied_by_user;
} trick;
/*
prototypes
*/
void play_hand(card *cards, player *user, player *cpu);
void reset_deck(card *cards);
card ask_cpu_for_card(card *cpu_cards);
card ask_user_for_card(card *user_cards);
My main file
// truco.c
#include "./types.h"
int main(void)
{
printf("Truco\n\n");
card cards[TOTAL_CARDS_NUMBER];
// prepare deck, generating the cards
/* set_deck(cards); */
player user, cpu;
int user_tentos = 0;
int cpu_tentos = 0;
user.player_tentos = &user_tentos;
cpu.player_tentos = &cpu_tentos;
while (user_tentos < 12 && cpu_tentos < 12)
{
play_hand(cards, &user, &cpu);
}
/* show_final_victor(user_tentos, cpu_tentos); */
return 0;
}
Match related file
truco is a best-of-three game for each match, and has a lot of matchs played before the game finishes
// match.c
#include "./types.h"
void play_hand(card *cards, player *user_ptr, player *cpu_ptr)
{
int stake = 2;
int *user_tentos = (*user_ptr).player_tentos;
int *cpu_tentos = (*cpu_ptr).player_tentos;
// distributing cards
/* draw_cards(cards, user_ptr, cpu_ptr); */
trick tricks[3];
int trick = 0;
enum round_result current_result = TIE;
while (true)
{
tricks[trick] = play_trick(user_ptr, cpu_ptr);
current_result = check_winner(tricks);
if (current_result == WIN)
{
// user wins
(*user_tentos) += stake;
break;
}
else if (current_result == LOSE)
{
// cpu wins
(*cpu_tentos) += stake;
break;
}
else if (trick == 2)
{
// third trick in case of tie-tie-tie
break;
}
trick++;
}
// cards should be made available again here
reset_deck(cards);
}
trick play_trick(player *user_ptr, player *cpu_ptr)
{
card *user_cards = (*user_ptr).cards;
card *cpu_cards = (*cpu_ptr).cards;
card user_card, cpu_card;
trick trick;
// ask players for card, possibily asking truco
ask_cards_from_players(user_cards, cpu_cards,
&user_card, &cpu_card);
// populate trick structure with result of current round
/* set_trick_result(user_card, cpu_card, &trick); */
// visual only - show user played cards and round result
/* show_played_cards(user_card, cpu_card); */
return trick;
}
void ask_cards_from_players(
card *user_cards, card *cpu_cards,
card *user_card, card *cpu_card)
{
// ask each player for a card in correct order
// I removed this part to keep it concise and simple
// user can possibily ask truco
*user_card = ask_user_for_card(user_cards);
// cpu could possibily ask truco
// but let's focus on the user for now
*cpu_card = ask_cpu_for_card(cpu_cards);
}
card ask_user_for_card(card *user_cards)
{
// show user cards
/* show_player_cards(user_cards); */
player_action action = {
.choice = 0,
.ask_truco = false};
card card;
// get user choice, including they called truco or not
/* get_choice(&action); */
// get card using choice
/* card = get_card_from_hand(action.choice); */
if (action.ask_truco)
{
// ask cpu if it accepts truco
// if so, maybe the cpu wants to call truco (retruco)
// if retruco, we should ask the user, if they accept truco
// again the user may call retruco now, and so on
// otherwise, the player who called truco should be considered the winner
// if there is a winner in this way, we should set `current_result` accordingly
// the tentos should be updated and the game should skip to line `43` on `play_hand` function
// that is, the `reset_deck` function call
// if truco is just accepted, but retruco is not called
// the game should continue
// and stake for this match should be increased
}
return card;
}
card ask_cpu_for_card(card *cpu_cards)
{
// show cpu cards
/* show_player_cards(cpu_cards); */
card card;
// get a random card for cpu
/* card = get_random_card(cpu_cards); */
return card;
}
That's it, here we have most of the code related to the question, still, some extra things here and there that I kept to maintain everything in context.
As you can see above, my is in case truco is refused. Suppose cpu refuses truco, how do I come back from ask_user_for_card to update user_tentos in the while loop inside play_hand function and immediately go to line 43 and reset_deck(), finishing that match?
Of course, I could use a lot of if statements, maybe change the return type of some functions, or even create some new structures*, but I think that you make the code a little messy, remember this is still a reduced and simplified sample.
* To tangent a little, I was wondering if it's considered a bad practice to create structures with the sole purpose to return more than one thing in a function, even though the properties may not be related...
To solve the problem, the idea #Fe2O3 gave me was a key factor, why not use enums to separate each state of the game and use a loop with a switch to change from one stage to another?
To organize things better I decided to create another file called state-manager.c together with its .h couple. This file is responsible for managing the state of the match, it would store and update the state of the game.
// state-manager.h
enum states
{
END_OF_MATCH = -1,
IDLE,
CHECK_USER_TURN,
SET_ASK_PLAYER_CARD,
ASK_USER_CARD,
ASK_CPU_CARD,
SET_TRICK_RESULT,
SHOW_PLAYED_CARDS,
CHECK_WINNER,
UPDATE_WINNER_TENTOS
};
enum calltruco
{
NO_PLAYER_ASKING_TRUCO,
USER_ASKING_TRUCO,
CPU_ASKING_TRUCO
};
typedef struct state
{
enum states current_state;
enum states previous_state;
enum states next_state;
// which player is asking truco
enum calltruco current_asking_player;
// which player has asked truco
enum calltruco previous_asking_player;
} state;
state get_state();
state update_state(enum states new_state);
state reset_state();
state set_asking_player(enum calltruco new_asking_player);
// state-manager.c
#include "./types.h"
#include "./state-manager.h"
/*
THIS FILE MANAGES THE STATES FOR THE MATCH
Its purpose is to control the flow of the program
when playing three tricks of the game (each match worthing 2-base points)
*/
static state match_state = {
.current_state = IDLE,
.previous_state = IDLE,
.next_state = IDLE,
.current_asking_player = NO_PLAYER_ASKING_TRUCO,
.previous_asking_player = NO_PLAYER_ASKING_TRUCO};
state get_state()
{
return match_state;
}
state update_state(enum states new_state)
{
match_state.previous_state = match_state.current_state;
match_state.current_state = new_state;
return match_state;
}
state reset_state()
{
match_state.current_state = IDLE;
match_state.previous_state = IDLE;
match_state.current_asking_player = NO_PLAYER_ASKING_TRUCO;
match_state.previous_asking_player = NO_PLAYER_ASKING_TRUCO;
return match_state;
}
state set_asking_player(enum calltruco new_asking_player)
{
match_state.previous_asking_player = match_state.current_asking_player;
match_state.current_asking_player = new_asking_player;
return match_state;
}
And in my match.c almost everything was changed
// match.c new version
void play_hand(card *cards, player *user_ptr, player *cpu_ptr)
{
int stake = 2;
state match_state = get_state();
trick tricks[3];
int trick = 0;
enum round_result current_result = TIE;
card user_card, cpu_card;
while (match_state.current_state != END_OF_MATCH)
{
switch (match_state.current_state)
{
case IDLE:
printf("IDLE\n");
// checks and populate the next state
match_state = idle(match_state, trick);
update_state(match_state.next_state);
break;
case CHECK_USER_TURN:
printf("CHECK_USER_TURN\n");
is_user_turn = check_user_turn(tricks[trick - 1]);
update_state(SET_ASK_PLAYER_CARD);
break;
case SET_ASK_PLAYER_CARD:
printf("SET_ASK_PLAYER_CARD\n");
update_state((is_user_turn) ? ASK_USER_CARD : ASK_CPU_CARD);
break;
case ASK_USER_CARD:
printf("ASK_USER_CARD\n");
// now I can just return out of the function it truco is refused
match_state = ask_user_card(match_state,
user_cards,
&user_card,
&current_result,
&stake);
// and update the state accordingly
update_state(match_state.next_state);
break;
case ASK_CPU_CARD:
printf("ASK_CPU_CARD\n");
// do more stuff...
break;
case SET_TRICK_RESULT:
printf("SET_TRICK_RESULT\n");
// do more stuff...
break;
case SHOW_PLAYED_CARDS:
printf("SHOW_PLAYED_CARDS\n");
// do more stuff...
break;
case CHECK_WINNER:
printf("CHECK_WINNER\n");
// do more stuff...
break;
case UPDATE_WINNER_TENTOS:
printf("UPDATE_WINNER_TENTOS\n");
// whatever it does, I can go here anytime I want and break out of the loop
break;
default:
printf("default\n");
update_state(END_OF_MATCH);
break;
}
match_state = get_state();
}
reset_state();
// cards should be made available again here
reset_deck(cards);
}
Again, I naturally just showed related stuff, but I think it is still possible to see the changes, now I have a loop with a switch statement to change from each state of the game to another, I control from where I am to where I will go.
My only concern is, this approach although works great is arguably more complex to read understand and maintain, honestly I'm glad I managed to do this; any other suggestion or comment is appreciated.
Thank you!

Related

How do I fix this code that minuses one life from the snake in the snake game?

Hi I am trying to solve this code, but I need help. I want the snake to loose one life every time it hits itself or the wall. It has 3 lives. Here is my code so far:
#include <stdio.h>
int main(void) {
printf("You will have life functions. You will get 3 lifes.\n");
char life [3];
int aa;
printf("You have 3 lifes");
printf("Press 'S' to start");
scanf("%i",&aa);
bool PlayerDied( PlayerData * pd )
{
bool alive = false;
--pd->Lives; // player died - one less life
return pd->Lives <= 0;
alive = true; // player still has a life left
return alive;
}
return 0;
}
So I seem to be not believing in no side-effects here. I would write this:
bool PlayerDied( PlayerData * pd )
{
return (--pd->Lives) > 0;
}
Decrement pd->lives then return whether or not any lives remain.
Thre's kind of this habit in C of doing something and returning a status as the function's return value. You'll find it all over the standard APIs for various OSes.
Your mistake was having a return with more code after it. If the return is reached (and since it's unconditional it will be reached), nothing past the ; of the return statement ever runs.

Can I turn this requirement into a macro?

I have C programs with decrementing software counters. If for instance I want to blink an led every 2 seconds I can do:
if(!ledT) {
ledT = 200;
// code
// code
// code
}
Because I always do the exact same combination with every counter, I tend to type it one line.
if(!ledT) { ledT = 200;
// code
// code
// code
}
For the entire if-line I'd like to use a macro instead. So the code would look something like:
expired(ledT, 200) {
// code
// code
// code
}
I use something similar in my state machine code for the entry state.
if(runOnce) { runOnce = false;
// code
// code
// code
Desired syntax:
entryState {
// code
// code
// code
.
#define entryState if(runOnce) { runOnce = false; // this ofcourse cannot work But something like this is what I want.
I've made several attempts but I got nowhere. The problem is that the { is somewhere in the middle of the macro and I want to type a { behind the macro because as we all know, no code editor can live with an unequal number of { and }.
expired(ledT, 200); // expired is macro, not function
// code
// code
// code
}
So this is out of the question.
Whilst reading about macros, I've read something interesting about using: do ... while(0). This 'trick' abuses the compiler's optimization feature to create a certain macro, which would otherwise be impossible.
This site
sheds some light about this manner.
Is there a way to use some kind of 'macro trick' to achieve what I want?
So again, that is transforming:
// this
if(runOnce) {
runOnce = false;
// code
// code
// code
// into this
entryState {
// code
// code
// code
// and this:
if(!someTimer) {
someTimer = someInterval;
// code
// code
// code
// must be transformed into:
timeExpired(someTimer, someInterval) {
// code
// code
// code
And an answer like "No, it simply cannot be done" will also be accepted (providing you know what you are talking about)
EDIT:
I need to add an addition because not everybody seems to know what I want, the last given answer is not even aimed at the specific problem at hand. Somehow toggling IO suddenly became important? Therfor I altered my code examples to better illustrate what the problem is.
EDIT2:
I agree that the the timeExpired macro does not improve readability at all
To show that some macros can improve readabilty I'll give a snippet of a state and a state machine. This is how a generated state looks like in my code:
State(stateName) {
entryState {
// one time only stuff
}
onState {
// continous stuff
exitFlag = true; // setting this, exits the state
}
exitState {
// one time only stuff upon exit
return true;
}
}
Currently in place with these macros:
#define State(x) static bool x##F(void)
#define entryState if(runOnce)
#define onState runOnce = false;
#define exitState if(!exitFlag) return false; else
I think I should I should exchange return true; in the states by EXIT or something prittier.
And the state machine which calls these States looks like:
#undef State
#define State(x) break; case x: if(x##F())
extern bit weatherStates(void) {
if(enabled) switch(state){
default: case weatherStatesIDLE: return true;
State(morning) {
if(random(0,1)) nextState(afternoon, 0);
else nextState(rain, 0); }
State(afternoon) {
nextState(evening, 0); }
State(evening) {
if(random(0,1)) nextState(night, 0);
else nextState(thunder, 0); }
State(night) {
nextState(morning, 0); }
State(rain) {
nextState(evening, 0); }
State(thunder) {
nextState(morning, 0); }
break; }
else if(!weatherStatesT) enabled = true;
return false; }
#undef State
The only thing which is not generated are the 'if' and 'else' before the 'nextState()' functions. These 'flow conditions' need filling in.
If a user is provided with a small example or an explanation, he should have no difficulty at all with filling in the states. He should also be able to add states manually.
I'd even like to exchange this by macros:
extern bit weatherStates(void) {
if(enabled) switch(state){
default: case weatherStatesIDLE: return true;
and
break;} }
else if(!weatherStatesT) enabled = true;
return false;}
Why would I do this? To hide irrelevant information out of your display. To remove alot of tabs in the state machine. To increase overal readability by using a simple syntax. Like with 3rd library functions you need to know how to use the code rather to know how the function does the trick.
You don't need to know, how a state signals that it is ready. It is more important to know that the function in question is used as a state function than to know that it returns a bit variable.
Also I test macros before using. So I don't provide somebody with state machines that may show strange behavior.
There’s no need to employ macros here, and doing so leads to highly un-idiomatic C code that doesn’t really have any advantages over proper C code.
Use a function instead:
int toggle_if_unset(int time, int pin, int interval) {
if (time == 0) {
time = 200;
TOG(pin);
}
return time;
}
ledT = toggle_if_unset(ledT, ledPin, 200);
(I’m guessing appropriate parameter names based on your example; adjust as appropriate.)
What’s more, it looks as if ledT and ledPin are always paired and belong together, in which case you should consider putting them into a struct:
struct led {
pin_t pin;
int interval;
};
void toggle_if_unset(struct led *led, int new_interval);
Or something along these lines.
Given that this is for some old 8051 legacy project, it is extremely unlikely that you need to create abstraction layer macros for pin I/O handling. You'll only have just so many pins. Your original code is most likely the best and clearest one.
If you for some reason worry about code repetition, because you have multiple combinations of the product/support multiple PCB with different routing etc, and you are stuck with your current code base... then as a last resort you could use macros to avoid code repetition. This also assuming that you are a seasoned C programmer - otherwise stop reading here.
What you will be looking at in that rare scenario is probably something that's known as "X macros", which is about declaring a whole list of pre-processor constants. Then whenever you need to do something repetitive, you call upon that list and use the constants inside it that you are interested for that specific call. Each call is done by specifying what the macro "X" should do in that particular call, then undefined the macro afterwards.
For example if you have ports A, B, C, you have LEDs on port A:0, B:1 and C:2 respectively and wish to use different delays per pin, you can declare a list like this:
#define LED_LIST \
/* port pin delay */ \
X(A, 0, 100) \
X(B, 1, 200) \
X(C, 2, 300) \
Then you can call upon this list when you need to do repetitive tasks. For example if these ports have data direction registers you need to set accordingly and those registers are called DDRA, DDRB, DDRC (using Motorola/AVR naming as example):
/* set data direction registers */
#define X(port, pin, delay) DDR##port |= 1u<<pin;
LED_LIST
#undef X
This will expand to:
DDRA |= 1u<<0;
DDRB |= 1u<<1;
DDRC |= 1u<<2;
Similarly, you can initialize the counters as:
/* declare counters */
#define X(port, delay) static uint16_t count##port = delay;
LED_LIST
#undef X
...
/* check if counters elapsed */
#define X(port, delay) if(count##port == 0) { count##port = delay; PORT##port ^= 1u << pin; }
LED_LIST
#undef X
(I replaced the toggle macro with a simple bitwise XOR)
Which will expand to:
static uint16_t countA = 100;
static uint16_t countB = 200;
static uint16_t countC = 300;
...
if(countA == 0)
{
countA = 100;
PORTA ^= 1u << 0;
}
if(countB == 0)
{
countB = 200;
PORTB ^= 1u << 1;
}
if(countC == 0)
{
countC = 300;
PORTC ^= 1u << 2;
}
And of course avoid using 16 bit counters like done here unless you must, since you are working with a crappy 8-bitter.
#define LL(ledT) do {if(!ledT) { ledT = 200; TOG(ledPin); }}while(0)
Whilst reading about macros, I've read something interesting about
using: do ... while(0). This 'trick' abuses the compiler's
optimization feature to create a certain macro, which would otherwise
be impossible.
Most of the opinions there are actually wrong. There is nothing about optimizations.
The main reason is to make macros using curled braces to compile at all.
This one will not compile
#define A(x) {foo(x);bar(x);}
void foo1(int x)
{
if (x) A(1);
else B(0);
}
but this one will compile
#define A(x) do{foo(x);bar(x);}while(0)
void foo1(int x)
{
if (x) A(1);
else B(0);
}
https://godbolt.org/z/4jH2jP
DISCLAIMER: I don't recommend using this solution.
I had a go at trying to make this into macro's. It is indeed possible but if it's faster, that's another question. As you make a new variable each time you call the macro.
#include <stdio.h>
#define entryState(runOnce) int temp_state = runOnce; if (runOnce) runOnce = 0; if (temp_state)
#define timeExpired(someTimer, someInterval) int temp_expired = someTimer; if (!someTimer) someTimer = someInterval; if (!temp_expired)
int main(int argc, const char* argv[]) {
int runOnce = 1;
int someTimer = 0;
int someInterval = 200;
timeExpired(someTimer, someInterval) {
printf("someTimer is Expired\n");
}
printf("someTimer: %i\n\n", someTimer);
entryState(runOnce) {
printf("this is running once\n");
}
printf("runOnce: %i\n", runOnce);
}
Compiling and running:
c:/repo $ gcc test.c -o test
c:/repo $ ./test.exe
someTimer is Expired
someTimer: 200
this is running once
runOnce: 0
I don't have a C51 compiler at hand now, so I let the testing on the 8051 over to you.

How to create derived structure properties in C

In Python, its possible to create a derived property from a class using the #property decorator for example
class State():
def __init__(self, fav_num_monday, fav_num_not_monday, is_monday):
self.fav_num_monday = fav_num_monday
self.fav_num_not_monday = fav_num_not_monday
self.is_monday = is_monday
#property
def fav_num(self):
return self.is_monday * self.fav_num_monday + \
(1 - self.is_monday) * self.fav_num_not_monday
state = State(12, 5, 0)
print("Current favourite number: %d" % state.fav_num)
My question is then what is the best way to achieve this in C (where speed is of the utmost importance). I've have added below some ways I have tried but am not sure if they could have repercussions in a larger codebase. They are as follows:
Simply writing out the whole expression each time.
Pros: No unexpected repercussions, no code/speed penalty.
Cons: Ugly code, takes a long time to write.
Using a get function.
Pros: Code easier to read.
Cons: Inefficient code (slower than 1).
Defining a macro.
Pros: No code/speed penalty. Code quick to write.
Cons: Potential repercussions later, code not so easy to follow.
The example program is below
#include <stdio.h>
#include <string.h>
#define state_fav_num state.is_monday * state.fav_num_monday + (1 - state.is_monday) * state.fav_num_not_monday
struct State {
int fav_num_monday;
int fav_num_not_monday;
int is_monday;
};
int get_state(struct State *state, char *property) {
// Returns value of the property in state.
// Allows us to create derived properties also.
if (!strncmp(property, "fav_num_monday", 14)) {
return state->fav_num_monday;
} else if (!strncmp(property, "fav_num_not_monday", 18)) {
return state->fav_num_not_monday;
} else if (!strncmp(property, "is_monday", 9)) {
return state->is_monday;
} else if (!strncmp(property, "fav_num", 7)) {
return state->is_monday * state->fav_num_monday +
(1 - state->is_monday) * state->fav_num_not_monday;
}
}
int main() {
// Set the state.
struct State state;
state.fav_num_monday = 12;
state.fav_num_not_monday = 5;
state.is_monday = 1;
// Print favourite number in different ways.
printf("\n1) Current favourite number is %d.",
state.is_monday * state.fav_num_monday +
(1 - state.is_monday) * state.fav_num_not_monday);
printf("\n2) Current favourite number is %d.",
get_state(&state, "fav_num"));
printf("\n3) Current favourite number is %d.",
state_fav_num);
printf("\n");
return 0;
}
You can get the best of both worlds (function and macro) for readability and performance, with a static inline function.
You usually wouldn't use that, but if you know the compiler is going to optimize its code away, then it's OK to use it. The usual rule I use is 3 or less lines of code, and the function should require extra performance.
That said, your get_state doesn't meet the (my) requirements for a static inline function, but if you only want a function to get only the fav_num, it would make sense:
struct State {
int fav_num_monday;
int fav_num_not_monday;
bool is_monday;
};
static inline int get_fav_num(const struct State *state)
{
if (state->is_monday)
return state->fav_num_monday;
else
return state->fav_num_not_monday;
}
int main(void)
{
struct State state;
int fav_num;
state = (struct State){
.fav_num_monday = 12;
.fav_num_not_monday = 5;
.is_monday = 1;
};
// Print favourite number in different ways.
printf("\n");
if (state.is_monday)
fav_num = state->fav_num_monday;
else
fav_num = state->fav_num_not_monday;
printf("1) Current favourite number is %d.\n", fav_num);
fav_num = get_fav_num(&state);
printf("4) Current favourite number is %d.\n", fav_num);
return 0;
}
Disclaimer: This code needs C99 or later.
Although here the code is all together, the struct State {...}; and the static inline function would usually go in a header .h file.
Also, I would improve your get_state function in this way:
enum Properties {
FAV_NUM_MONDAY,
FAV_NUM_NOT_MONDAY,
IS_MONDAY,
FAV_NUM
};
int get_state(const struct State *state, int property)
{
switch (property) {
case FAV_NUM_MONDAY:
return state->fav_num_monday;
case FAV_NUM_NOT_MONDAY:
return state->fav_num_not_monday;
case IS_MONDAY:
return state->is_monday;
case FAV_NUM:
return get_fav_num(state);
default:
return -1; /* Error */
}
}
This function would be a usual extern function and would go in a .c file, although the enum Properties should go in a header file so that it can be used by the user of the function.
Edit: Add high performance version using array
state.h
#include <stdint.h>
enum State_Properties {
FAV_NUM_MONDAY,
FAV_NUM_NOT_MONDAY,
IS_MONDAY,
STATE_PROPERTIES
};
static inline
uint_fast8_t get_fav_num(const uint_fast8_t *restrict (state[STATE_PROPERTIES]))
{
if ((*state)[IS_MONDAY])
return (*state)[FAV_NUM_MONDAY];
else
return (*state)[FAV_NUM_NOT_MONDAY];
}
main.c
#include <inttypes.h>
#include "state.h"
int main(void)
{
uint_fast8_t state[STATE_PROPERTIES];
uint_fast8_t fav_num;
uint_fast8_t fav_num_monday;
state = (uint_fast8_t [STATE_PROPERTIES]){
[FAV_NUM_MONDAY] = 12;
[FAV_NUM_NOT_MONDAY] = 5;
[IS_MONDAY] = true;
};
// Print favourite number in different ways.
fav_num = get_fav_num(&state);
printf("5) Current favourite number is %"PRIuFAST8".\n", fav_num);
// Example of how to retrieve any property:
fav_num_monday = state[FAV_NUM_MONDAY];
}
Of course you can change the type to anyone you want. I used uint_fast8_t, because your data can fit in there, and it is the fastest type on any system.

How do I pass a variable used in a function to a variable in another function in C?

I'm making a small and simple game in C as a project for college.
In the game, there's a function in which the player will buy troops of different types for his army. Then, during the execution of the other function, the player will position the troops bought in the game scenario, but the function "needs to know" how many troops and of which type the player bought.
So basically, what I'm asking is how do I pass the value of a variable used in a function to be used in another one.
example:
typedef enum
{
PLAYER_COMMAND_BUY,
PLAYER_COMMAND_GET,
PALYER_COMMAND_SET,
}PLAYER_COMMAND_t;
int manage_player(PLAYER_COMMAND_t command, unsigned *data)
{
static unsigned nplayers;
int result = 0; //OK
switch(command)
{
case PLAYER_COMMAND_BUY:
/* do something to buy players */
/* set nplayers */
break;
case PLAYER_COMMAND_GET:
*data = nplayers;
/* do something to buy players */
break;
case PALYER_COMMAND_SET:
/* do something to buy players */
nplayers = data;
break;
}
return result;
}
If your code needs to work a lot with common data in different functions, you could put this data in a embedded database (sqlite for example) that will be part of you executable.

Is there a typical state machine implementation pattern?

We need to implement a simple state machine in C.
Is a standard switch statement the best way to go?
We have a current state (state) and a trigger for the transition.
switch(state)
{
case STATE_1:
state = DoState1(transition);
break;
case STATE_2:
state = DoState2(transition);
break;
}
...
DoState2(int transition)
{
// Do State Work
...
if(transition == FROM_STATE_2) {
// New state when doing STATE 2 -> STATE 2
}
if(transition == FROM_STATE_1) {
// New State when moving STATE 1 -> STATE 2
}
return new_state;
}
Is there a better way for simple state machines
EDIT:
For C++, I think the Boost Statechart library might be the way to go. However, it does not help with C. Lets concentrate on the C use case.
I prefer to use a table driven approach for most state machines:
typedef enum { STATE_INITIAL, STATE_FOO, STATE_BAR, NUM_STATES } state_t;
typedef struct instance_data instance_data_t;
typedef state_t state_func_t( instance_data_t *data );
state_t do_state_initial( instance_data_t *data );
state_t do_state_foo( instance_data_t *data );
state_t do_state_bar( instance_data_t *data );
state_func_t* const state_table[ NUM_STATES ] = {
do_state_initial, do_state_foo, do_state_bar
};
state_t run_state( state_t cur_state, instance_data_t *data ) {
return state_table[ cur_state ]( data );
};
int main( void ) {
state_t cur_state = STATE_INITIAL;
instance_data_t data;
while ( 1 ) {
cur_state = run_state( cur_state, &data );
// do other program logic, run other state machines, etc
}
}
This can of course be extended to support multiple state machines, etc. Transition actions can be accommodated as well:
typedef void transition_func_t( instance_data_t *data );
void do_initial_to_foo( instance_data_t *data );
void do_foo_to_bar( instance_data_t *data );
void do_bar_to_initial( instance_data_t *data );
void do_bar_to_foo( instance_data_t *data );
void do_bar_to_bar( instance_data_t *data );
transition_func_t * const transition_table[ NUM_STATES ][ NUM_STATES ] = {
{ NULL, do_initial_to_foo, NULL },
{ NULL, NULL, do_foo_to_bar },
{ do_bar_to_initial, do_bar_to_foo, do_bar_to_bar }
};
state_t run_state( state_t cur_state, instance_data_t *data ) {
state_t new_state = state_table[ cur_state ]( data );
transition_func_t *transition =
transition_table[ cur_state ][ new_state ];
if ( transition ) {
transition( data );
}
return new_state;
};
The table driven approach is easier to maintain and extend and simpler to map to state diagrams.
You might have seen my answer to another C question where I mentioned FSM! Here is how I do it:
FSM {
STATE(x) {
...
NEXTSTATE(y);
}
STATE(y) {
...
if (x == 0)
NEXTSTATE(y);
else
NEXTSTATE(x);
}
}
With the following macros defined
#define FSM
#define STATE(x) s_##x :
#define NEXTSTATE(x) goto s_##x
This can be modified to suit the specific case. For example, you may have a file FSMFILE that you want to drive your FSM, so you could incorporate the action of reading next char into the the macro itself:
#define FSM
#define STATE(x) s_##x : FSMCHR = fgetc(FSMFILE); sn_##x :
#define NEXTSTATE(x) goto s_##x
#define NEXTSTATE_NR(x) goto sn_##x
now you have two types of transitions: one goes to a state and read a new character, the other goes to a state without consuming any input.
You can also automate the handling of EOF with something like:
#define STATE(x) s_##x : if ((FSMCHR = fgetc(FSMFILE) == EOF)\
goto sx_endfsm;\
sn_##x :
#define ENDFSM sx_endfsm:
The good thing of this approach is that you can directly translate a state diagram you draw into working code and, conversely, you can easily draw a state diagram from the code.
In other techniques for implementing FSM the structure of the transitions is buried in control structures (while, if, switch ...) and controlled by variables value (tipically a state variable) and it may be a complex task to relate the nice diagram to a convoluted code.
I learned this technique from an article appeared on the great "Computer Language" magazine that, unfortunately, is no longer published.
In Martin Fowler's UML Distilled, he states (no pun intended) in Chapter 10 State Machine Diagrams (emphasis mine):
A state diagram can be implemented in three main ways: nested switch, the State pattern, and
state tables.
Let's use a simplified example of the states of a mobile phone's display:
Nested switch
Fowler gave an example of C# code, but I've adapted it to my example.
public void HandleEvent(PhoneEvent anEvent) {
switch (CurrentState) {
case PhoneState.ScreenOff:
switch (anEvent) {
case PhoneEvent.PressButton:
if (powerLow) { // guard condition
DisplayLowPowerMessage(); // action
// CurrentState = PhoneState.ScreenOff;
} else {
CurrentState = PhoneState.ScreenOn;
}
break;
case PhoneEvent.PlugPower:
CurrentState = PhoneState.ScreenCharging;
break;
}
break;
case PhoneState.ScreenOn:
switch (anEvent) {
case PhoneEvent.PressButton:
CurrentState = PhoneState.ScreenOff;
break;
case PhoneEvent.PlugPower:
CurrentState = PhoneState.ScreenCharging;
break;
}
break;
case PhoneState.ScreenCharging:
switch (anEvent) {
case PhoneEvent.UnplugPower:
CurrentState = PhoneState.ScreenOff;
break;
}
break;
}
}
State pattern
Here's an implementation of my example with the GoF State pattern:
State Tables
Taking inspiration from Fowler, here's a table for my example:
Source State Target State Event Guard Action
--------------------------------------------------------------------------------------
ScreenOff ScreenOff pressButton powerLow displayLowPowerMessage
ScreenOff ScreenOn pressButton !powerLow
ScreenOn ScreenOff pressButton
ScreenOff ScreenCharging plugPower
ScreenOn ScreenCharging plugPower
ScreenCharging ScreenOff unplugPower
Comparison
Nested switch keeps all the logic in one spot, but the code can be hard to read when there are a lot of states and transitions. It's possibly more secure and easier to validate than the other approaches (no polymorphism or interpreting).
The State pattern implementation potentially spreads the logic over several separate classes, which may make understanding it as a whole a problem. On the other hand, the small classes are easy to understand separately. The design is particularly fragile if you change the behavior by adding or removing transitions, as they're methods in the hierarchy and there could be lots of changes to the code. If you live by the design principle of small interfaces, you'll see this pattern doesn't really do so well. However, if the state machine is stable, then such changes won't be needed.
The state tables approach requires writing some kind of interpreter for the content (this might be easier if you have reflection in the language you're using), which could be a lot of work to do up front. As Fowler points out, if your table is separate from your code, you could modify the behavior of your software without recompiling. This has some security implications, however; the software is behaving based on the contents of an external file.
Edit (not really for C language)
There is a fluent interface (aka internal Domain Specific Language) approach, too, which is probably facilitated by languages that have first-class functions. The Stateless library exists and that blog shows a simple example with code. A Java implementation (pre Java8) is discussed. I was shown a Python example on GitHub as well.
I also have used the table approach. However, there is overhead. Why store a second list of pointers? A function in C without the () is a const pointer. So you can do:
struct state;
typedef void (*state_func_t)( struct state* );
typedef struct state
{
state_func_t function;
// other stateful data
} state_t;
void do_state_initial( state_t* );
void do_state_foo( state_t* );
void do_state_bar( state_t* );
void run_state( state_t* i ) {
i->function(i);
};
int main( void ) {
state_t state = { do_state_initial };
while ( 1 ) {
run_state( state );
// do other program logic, run other state machines, etc
}
}
Of course depending on your fear factor (i.e. safety vs speed) you may want to check for valid pointers. For state machines larger than three or so states, the approach above should be less instructions than an equivalent switch or table approach. You could even macro-ize as:
#define RUN_STATE(state_ptr_) ((state_ptr_)->function(state_ptr_))
Also, I feel from the OP's example, that there is a simplification that should be done when thinking about / designing a state machine. I don't thing the transitioning state should be used for logic. Each state function should be able to perform its given role without explicit knowledge of past state(s). Basically you design for how to transition from the state you are in to another state.
Finally, don't start the design of a state machine based on "functional" boundaries, use sub-functions for that. Instead divide the states based on when you will have to wait for something to happen before you can continue. This will help minimize the number of times you have to run the state machine before you get a result. This can be important when writing I/O functions, or interrupt handlers.
Also, a few pros and cons of the classic switch statement:
Pros:
it is in the language, so it is documented and clear
states are defined where they are called
can execute multiple states in one function call
code common to all states can be executed before and after the switch statement
Cons:
can execute multiple states in one function call
code common to all states can be executed before and after the switch statement
switch implementation can be slow
Note the two attributes that are both pro and con. I think the switch allows the opportunity for too much sharing between states, and the interdependency between states can become unmanageable. However for a small number of states, it may be the most readable and maintainable.
there is also the logic grid which is more maintainable as the state machine gets bigger
For a simple state machine just use a switch statement and an enum type for your state. Do your transitions inside the switch statement based on your input. In a real program you would obviously change the "if(input)" to check for your transition points. Hope this helps.
typedef enum
{
STATE_1 = 0,
STATE_2,
STATE_3
} my_state_t;
my_state_t state = STATE_1;
void foo(char input)
{
...
switch(state)
{
case STATE_1:
if(input)
state = STATE_2;
break;
case STATE_2:
if(input)
state = STATE_3;
else
state = STATE_1;
break;
case STATE_3:
...
break;
}
...
}
switch() is a powerful and standard way of implementing state machines in C, but it can decrease maintainability down if you have a large number of states. Another common method is to use function pointers to store the next state. This simple example implements a set/reset flip-flop:
/* Implement each state as a function with the same prototype */
void state_one(int set, int reset);
void state_two(int set, int reset);
/* Store a pointer to the next state */
void (*next_state)(int set, int reset) = state_one;
/* Users should call next_state(set, reset). This could
also be wrapped by a real function that validated input
and dealt with output rather than calling the function
pointer directly. */
/* State one transitions to state one if set is true */
void state_one(int set, int reset) {
if(set)
next_state = state_two;
}
/* State two transitions to state one if reset is true */
void state_two(int set, int reset) {
if(reset)
next_state = state_one;
}
I found a really slick C implementation of Moore FSM on the edx.org course Embedded Systems - Shape the World UTAustinX - UT.6.02x, chapter 10, by Jonathan Valvano and Ramesh Yerraballi....
struct State {
unsigned long Out; // 6-bit pattern to output
unsigned long Time; // delay in 10ms units
unsigned long Next[4]; // next state for inputs 0,1,2,3
};
typedef const struct State STyp;
//this example has 4 states, defining constants/symbols using #define
#define goN 0
#define waitN 1
#define goE 2
#define waitE 3
//this is the full FSM logic coded into one large array of output values, delays,
//and next states (indexed by values of the inputs)
STyp FSM[4]={
{0x21,3000,{goN,waitN,goN,waitN}},
{0x22, 500,{goE,goE,goE,goE}},
{0x0C,3000,{goE,goE,waitE,waitE}},
{0x14, 500,{goN,goN,goN,goN}}};
unsigned long currentState; // index to the current state
//super simple controller follows
int main(void){ volatile unsigned long delay;
//embedded micro-controller configuration omitteed [...]
currentState = goN;
while(1){
LIGHTS = FSM[currentState].Out; // set outputs lines (from FSM table)
SysTick_Wait10ms(FSM[currentState].Time);
currentState = FSM[currentState].Next[INPUT_SENSORS];
}
}
For simple cases, you can use your switch style method. What I have found that works well in the past is to deal with transitions too:
static int current_state; // should always hold current state -- and probably be an enum or something
void state_leave(int new_state) {
// do processing on what it means to enter the new state
// which might be dependent on the current state
}
void state_enter(int new_state) {
// do processing on what is means to leave the current state
// might be dependent on the new state
current_state = new_state;
}
void state_process() {
// switch statement to handle current state
}
I don't know anything about the boost library, but this type of approach is dead simple, doesn't require any external dependencies, and is easy to implement.
You might want to look into the libero FSM generator software. From a state description language and/or a (windows) state diagram editor you may generate code for C, C++, java and many others ... plus nice documentation and diagrams.
Source and binaries from iMatix
This article is a good one for the state pattern (though it is C++, not specifically C).
If you can put your hands on the book "Head First Design Patterns", the explanation and example are very clear.
One of my favourite patterns is the state design pattern. Respond or behave differently to the same given set of inputs.
One of the problems with using switch/case statements for state machines is that as you create more states, the switch/cases becomes harder/unwieldy to read/maintain, promotes unorganized spaghetti code, and increasingly difficult to change without breaking something. I find using design patterns helps me to organize my data better, which is the whole point of abstraction.
Instead of designing your state code around what state you came from, instead structure your code so that it records the state when you enter a new state. That way, you effectively get a record of your previous state. I like #JoshPetit's answer, and have taken his solution one step further, taken straight from the GoF book:
stateCtxt.h:
#define STATE (void *)
typedef enum fsmSignal
{
eEnter =0,
eNormal,
eExit
}FsmSignalT;
typedef struct fsm
{
FsmSignalT signal;
// StateT is an enum that you can define any which way you want
StateT currentState;
}FsmT;
extern int STATECTXT_Init(void);
/* optionally allow client context to set the target state */
extern STATECTXT_Set(StateT stateID);
extern void STATECTXT_Handle(void *pvEvent);
stateCtxt.c:
#include "stateCtxt.h"
#include "statehandlers.h"
typedef STATE (*pfnStateT)(FsmSignalT signal, void *pvEvent);
static FsmT fsm;
static pfnStateT UsbState ;
int STATECTXT_Init(void)
{
UsbState = State1;
fsm.signal = eEnter;
// use an enum for better maintainability
fsm.currentState = '1';
(*UsbState)( &fsm, pvEvent);
return 0;
}
static void ChangeState( FsmT *pFsm, pfnStateT targetState )
{
// Check to see if the state has changed
if (targetState != NULL)
{
// Call current state's exit event
pFsm->signal = eExit;
STATE dummyState = (*UsbState)( pFsm, pvEvent);
// Update the State Machine structure
UsbState = targetState ;
// Call the new state's enter event
pFsm->signal = eEnter;
dummyState = (*UsbState)( pFsm, pvEvent);
}
}
void STATECTXT_Handle(void *pvEvent)
{
pfnStateT newState;
if (UsbState != NULL)
{
fsm.signal = eNormal;
newState = (*UsbState)( &fsm, pvEvent );
ChangeState( &fsm, newState );
}
}
void STATECTXT_Set(StateT stateID)
{
prevState = UsbState;
switch (stateID)
{
case '1':
ChangeState( State1 );
break;
case '2':
ChangeState( State2);
break;
case '3':
ChangeState( State3);
break;
}
}
statehandlers.h:
/* define state handlers */
extern STATE State1(void);
extern STATE State2(void);
extern STATE State3(void);
statehandlers.c:
#include "stateCtxt.h:"
/* Define behaviour to given set of inputs */
STATE State1(FsmT *fsm, void *pvEvent)
{
STATE nextState;
/* do some state specific behaviours
* here
*/
/* fsm->currentState currently contains the previous state
* just before it gets updated, so you can implement behaviours
* which depend on previous state here
*/
fsm->currentState = '1';
/* Now, specify the next state
* to transition to, or return null if you're still waiting for
* more stuff to process.
*/
switch (fsm->signal)
{
case eEnter:
nextState = State2;
break;
case eNormal:
nextState = null;
break;
case eExit:
nextState = State2;
break;
}
return nextState;
}
STATE State3(FsmT *fsm, void *pvEvent)
{
/* do some state specific behaviours
* here
*/
fsm->currentState = '2';
/* Now, specify the next state
* to transition to
*/
return State1;
}
STATE State2(FsmT *fsm, void *pvEvent)
{
/* do some state specific behaviours
* here
*/
fsm->currentState = '3';
/* Now, specify the next state
* to transition to
*/
return State3;
}
For most State Machines, esp. Finite state machines, each state will know what its next state should be, and the criteria for transitioning to its next state. For loose state designs, this may not be the case, hence the option to expose the API for transitioning states. If you desire more abstraction, each state handler can be separated out into its own file, which are equivalent to the concrete state handlers in the GoF book. If your design is simple with only a few states, then both stateCtxt.c and statehandlers.c can be combined into a single file for simplicity.
In my experience using the 'switch' statement is the standard way to handle multiple possible states. Although I am surpirsed that you are passing in a transition value to the per-state processing. I thought the whole point of a state machine was that each state performed a single action. Then the next action/input determines which new state to transition into. So I would have expected each state processing function to immediately perform whatever is fixed for entering state and then afterwards decide if transition is needed to another state.
There is a book titled Practical Statecharts in C/C++.
However, it is way too heavyweight for what we need.
For compiler which support __COUNTER__ , you can use them for simple (but large) state mashines.
#define START 0
#define END 1000
int run = 1;
state = START;
while(run)
{
switch (state)
{
case __COUNTER__:
//do something
state++;
break;
case __COUNTER__:
//do something
if (input)
state = END;
else
state++;
break;
.
.
.
case __COUNTER__:
//do something
if (input)
state = START;
else
state++;
break;
case __COUNTER__:
//do something
state++;
break;
case END:
//do something
run = 0;
state = START;
break;
default:
state++;
break;
}
}
The advantage of using __COUNTER__ instead of hard coded numbers is that you
can add states in the middle of other states, without renumbering everytime everything.
If the compiler doesnt support __COUNTER__, in a limited way its posible to use with precaution __LINE__
You can use minimalist UML state machine framework in c. https://github.com/kiishor/UML-State-Machine-in-C
It supports both finite and hierarchical state machine. It has only 3 API's, 2 structures and 1 enumeration.
The State machine is represented by state_machine_t structure. It is an abstract structure that can be inherited to create a state machine.
//! Abstract state machine structure
struct state_machine_t
{
uint32_t Event; //!< Pending Event for state machine
const state_t* State; //!< State of state machine.
};
State is represented by pointer to state_t structure in the framework.
If framework is configured for finite state machine then state_t contains,
typedef struct finite_state_t state_t;
// finite state structure
typedef struct finite_state_t{
state_handler Handler; //!< State handler function (function pointer)
state_handler Entry; //!< Entry action for state (function pointer)
state_handler Exit; //!< Exit action for state (function pointer)
}finite_state_t;
The framework provides an API dispatch_event to dispatch the event to the state machine and two API's for the state traversal.
state_machine_result_t dispatch_event(state_machine_t* const pState_Machine[], uint32_t quantity);
state_machine_result_t switch_state(state_machine_t* const, const state_t*);
state_machine_result_t traverse_state(state_machine_t* const, const state_t*);
For further details on how to implement hierarchical state machine refer the GitHub repository.
code examples
https://github.com/kiishor/UML-State-Machine-in-C/blob/master/demo/simple_state_machine/readme.md
https://github.com/kiishor/UML-State-Machine-in-C/blob/master/demo/simple_state_machine_enhanced/readme.md
In C++, consider the State pattern.
Your question is similar to "is there a typical Data Base implementation pattern"?
The answer depends upon what do you want to achieve? If you want to implement a larger deterministic state machine you may use a model and a state machine generator.
Examples can be viewed at www.StateSoft.org - SM Gallery. Janusz Dobrowolski
I would also prefer a table driven approach. I have used switch statements in the past. The main problem I have encountered is debugging transitions and ensuring that the designed state machine has been implemented properly. This occurred in cases where there was a large number of states and events.
With the table driven approach are the states and transitions are summarized in one place.
Below is a demo of this approach.
/*Demo implementations of State Machines
*
* This demo leverages a table driven approach and function pointers
*
* Example state machine to be implemented
*
* +-----+ Event1 +-----+ Event2 +-----+
* O---->| A +------------------->| B +------------------->| C |
* +-----+ +-----+ +-----+
* ^ |
* | Event3 |
* +-----------------------------------------------------+
*
* States: A, B, C
* Events: NoEvent (not shown, holding current state), Event1, Event2, Event3
*
* Partly leveraged the example here: http://web.archive.org/web/20160808120758/http://www.gedan.net/2009/03/18/finite-state-machine-matrix-style-c-implementation-function-pointers-addon/
*
* This sample code can be compiled and run using GCC.
* >> gcc -o demo_state_machine demo_state_machine.c
* >> ./demo_state_machine
*/
#include <stdio.h>
#include <assert.h>
// Definitions of state id's, event id's, and function pointer
#define N_STATES 3
#define N_EVENTS 4
typedef enum {
STATE_A,
STATE_B,
STATE_C,
} StateId;
typedef enum {
NOEVENT,
EVENT1,
EVENT2,
EVENT3,
} Event;
typedef void (*StateRoutine)();
// Assert on number of states and events defined
static_assert(STATE_C==N_STATES-1,
"Number of states does not match defined number of states");
static_assert(EVENT3==N_EVENTS-1,
"Number of events does not match defined number of events");
// Defining State, holds both state id and state routine
typedef struct {
StateId id;
StateRoutine routine;
} State;
// General functions
void evaluate_state(Event e);
// State routines to be executed at each state
void state_routine_a(void);
void state_routine_b(void);
void state_routine_c(void);
// Defining each state with associated state routine
const State state_a = {STATE_A, state_routine_a};
const State state_b = {STATE_B, state_routine_b};
const State state_c = {STATE_C, state_routine_c};
// Defning state transition matrix as visualized in the header (events not
// defined, result in mainting the same state)
State state_transition_mat[N_STATES][N_EVENTS] = {
{ state_a, state_b, state_a, state_a},
{ state_b, state_b, state_c, state_b},
{ state_c, state_c, state_c, state_a}};
// Define current state and initialize
State current_state = state_a;
int main()
{
while(1) {
// Event to receive from user
int ev;
printf("----------------\n");
printf("Current state: %c\n", current_state.id + 65);
printf("Event to occur: ");
// Receive event from user
scanf("%u", &ev);
evaluate_state((Event) ev); // typecast to event enumeration type
printf("-----------------\n");
};
return (0);
}
/*
* Determine state based on event and perform state routine
*/
void evaluate_state(Event ev)
{
//Determine state based on event
current_state = state_transition_mat[current_state.id][ev];
printf("Transitioned to state: %c\n", current_state.id + 65);
// Run state routine
(*current_state.routine)();
}
/*
* State routines
*/
void state_routine_a() {
printf("State A routine ran. \n");
}
void state_routine_b() {
printf("State B routine ran. \n");
}
void state_routine_c() {
printf("State C routine ran. \n");
}
Boost has the statechart library. http://www.boost.org/doc/libs/1_36_0/libs/statechart/doc/index.html
I can't speak to the use of it, though. Not used it myself (yet)

Resources