C decorator design pattern (using the pizza example) - c

I are taking a low level course in embedded systems and have been assigned the task of replicating some design patterns in C. I have gotten observer and delegator working I am really struggling with the decorator pattern. I do realize that many people think that design patterns do not belong in a "low-level" language like C but I do not have an option - it needs to be done to pass this course. All the examples I have found are for OO programming languages. I'm using this Java pizza example as a basis (just returning the cost to make it easy) but for the life of me cannot get it to work: http://www.newthinktank.com/2012/09/decorator-design-pattern-tutorial/
This is the UML for the example (as I said I am only doing the getCost part):
I have spent about 2 days trying to get this to work but am just stuck. I have added the code that I have but am stumped how to add the tomato to the pizza so that the cost is added up correctly
#include <stdio.h>
typedef struct _pizza {
double (* getCost) ();
} pizza_t;
typedef struct _toppingDecorator {
double (* getCost) ();
pizza_t tempPizza;
} toppingDecorator_t;
// these are the pizzas
double plainPizzaCost () {
return 5;
}
double thickCrustPizzaCost () {
return 7;
}
// these are the toppings
double mozzarellaCost (toppingDecorator_t * self) {
return self->tempPizza.getCost () + 3.0;
}
double tomatoCost (toppingDecorator_t * self) {
return self->tempPizza.getCost () + 1;
}
int main(int argc, const char * argv[]) {
pizza_t plainPizza;
plainPizza.getCost = &plainPizzaCost;
pizza_t thickCrustPizza;
thickCrustPizza.getCost = &thickCrustPizzaCost;
toppingDecorator_t mozzarella;
mozzarella.tempPizza = plainPizza;
mozzarella.getCost = &mozzarellaCost;
toppingDecorator_t tomato;
tomato.tempPizza = mozzarella.tempPizza;
tomato.getCost = &tomatoCost;
// now print the cost
printf ("A plain pizza costs %f\n", plainPizza.getCost ());
printf ("A mozzarella pizza costs %f\n", mozzarella.getCost (&mozzarella));
printf ("A tomato and mozzarella pizza costs %f\n", tomato.getCost (&mozzarella));
}

not sure why the post was down voted but anyway... A friend solved the problem for me and I thought I'd post the answer here - thank you Marcel :o)
#include <stdio.h>
#include <stdlib.h>
typedef struct _pizza pizza_t;
typedef double (* getCost)(struct _pizza * self);
typedef struct _pizza {
getCost getCostFunc;
} pizza_t;
typedef struct _plainPizza {
pizza_t base;
} plainPizza_t;
typedef struct _toppingDecorator {
pizza_t base;
pizza_t * decorate;
} toppingDecorator_t;
// these are the pizzas
double plainPizzaCost (plainPizza_t self) {
return 5;
}
// these are the toppings
double mozzarellaCost (toppingDecorator_t * self) {
return self->decorate->getCostFunc(self->decorate) + 3;
}
double tomatoCost (toppingDecorator_t * self) {
return self->decorate->getCostFunc(self->decorate) + 2;
}
double salamiCost (toppingDecorator_t * self) {
return self->decorate->getCostFunc(self->decorate) + 1;
}
int main(int argc, const char * argv[]) {
plainPizza_t plainPizza;
plainPizza.base.getCostFunc = (getCost) plainPizzaCost;
toppingDecorator_t mozzarella;
mozzarella.base.getCostFunc = (getCost) mozzarellaCost;
mozzarella.decorate = (pizza_t *) &plainPizza;
toppingDecorator_t tomato;
tomato.base.getCostFunc = (getCost) tomatoCost;
tomato.decorate = (pizza_t *) &mozzarella;
toppingDecorator_t salami;
salami.base.getCostFunc = (getCost) salamiCost;
salami.decorate = (pizza_t *) &tomato;
printf ("A tomato pizza costs %f\n", tomato.base.getCostFunc((pizza_t *) &tomato));
printf ("A salami pizza costs %f\n", salami.base.getCostFunc((pizza_t *) &salami));
}

Related

C mutating struct properties by reference

I'm learning pointers in C and i came across a confusion between pointers X struts X functions
The goal: creating two structs and mutate properties inside them.
The path I'm going: I am creating these two structs and then passing its memory addresses to the mutate function, the function then prints and mutates some properties of these structs.
Result I get:
1: The name of the struct created is nod being entirely printed and its of the wrong struct passed, and the life property is not properly changed and printed to the screen.
2: On the terminal I get "Segmentation Fault", not sure why but I'm pretty sure its something wrong I did.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int power;
int life;
char name[];
} Hero;
void attackHero(Hero *hero, int *power) {
(*hero).life = (*hero).life - *power;
printf("Damage: %d\n", *power);
printf("Attacked hero: %s\n", (*hero).name);
printf("Hero's remaining life: %d\n", (*hero).life);
};
int main () {
Hero flash;
flash.power = 250;
flash.life = 500;
strcpy(flash.name, "The Flash");
Hero batman;
batman.power = 380;
batman.life = 700;
strcpy(batman.name, "Batman arkham knight");
attackHero(&flash, &batman.power);
return 0;
}
Result printed to the terminal (Vscode + gcc):
Here is the warning that I get when I compile your original code:
1.c:25:2: warning: ‘__builtin_memcpy’ writing 10 bytes into a region of size 0 overflows the destination [-Wstringop-overflow=]
25 | strcpy(flash.name, "The Flash");
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1.c:30:2: warning: ‘__builtin_memcpy’ writing 21 bytes into a region of size 0 overflows the destination [-Wstringop-overflow=]
30 | strcpy(batman.name, "Batman arkham knight");
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you want to use the flexible array then you have to allocate space for it like this:
int main () {
Hero *flash = malloc(sizeof(*flash) + sizeof("The Flash"));
flash->power = 250;
flash->life = 500;
strcpy(flash->name, "The Flash");
Hero *batman = malloc(sizeof(*flash) + sizeof("Batman arkham knight"));
batman->power = 380;
batman->life = 700;
strcpy(batman->name, "Batman arkham knight");
attackHero(flash, &batman->power);
free(flash);
free(batman);
}
Here there the resulting code refactored a bit, and I added a error check for malloc:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int power;
int life;
char name[];
} Hero;
Hero *createHero(int power, int life, const char *name) {
Hero *h = malloc(sizeof(*h) + strlen(name) + 1);
if(!h) {
printf("malloc failed\n");
exit(1);
}
h->power = power;
h->life = life;
strcpy(h->name, name);
return h;
}
void attackHero(Hero *hero, int power) {
hero->life -= power;
printf(
"Damage: %d\n"
"Attacked hero: %s\n"
"Hero's remaining life: %d\n",
power,
hero->name,
hero->life
);
};
int main(void) {
Hero *flash = createHero(250, 500, "The Flash");
Hero *batman = createHero(380, 700, "Batman arkham knight");
attackHero(flash, batman->power);
free(flash);
free(batman);
}
Alternatively use a fixed array (char [64] as suggested by #Diego) or a char * and allocate space to it. The former only needs 2 lines of code change from the original:
// largest name in use
#define NAME_LEN sizeof("Batman arkham knight")
typedef struct {
int power;
int life;
char name[NAME_LEN];
} Hero;
Whole lotta malloc() going on. Since the hero’s names are string literals (and assuming they don’t change), just change name[]; to const char *name in the structure and initialize via simple assignment:
flash.name = "The Flash";
batman.name = "Batman arkham knight";
No worries about malloc() failures, name sizes or free() requirements.

Getting a segmentation error in my C program while running tests

/* Created Library File */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <string.h>
#include "tournament.h"
Team * initializeTeam(char * name, Player * players){
Team *team = malloc(sizeof(Team));
(*team).name = name;
(*team).players = players;
return team;
}
Team * game(Team * team1, Team * team2){
int turns = 10;
int team_A_total = 0;
int team_B_total = 0;
int team_A_shooting = 0;
int team_B_shooting = 0;
int team_A_blocking = 0;
int team_B_blocking = 0;
int team_A_def = 0;
int team_B_def = 0;
int team_B_off = 0;
int team_A_off = 0;
for(int i=0;i<turns;i++){
team_A_off = team_A_off + (*team1).players[i].offensive;
team_A_def = team_A_def + (*team1).players[i].defensive;
team_B_off = team_B_off + (*team2).players[i].offensive;
team_B_def = team_B_def + (*team2).players[i].defensive;
};
for(int j=0;j<turns;j++){
team_A_shooting = rand() % team_A_off;
team_A_blocking = rand() % team_A_def;
team_B_shooting = rand() % team_B_off;
team_B_blocking = rand() % team_B_def;
if(team_A_shooting>team_B_blocking){
team_A_total = (team_A_total + 1);
};
if(team_B_shooting>team_A_blocking){
team_B_total = (team_B_total + 1);
};
};
if(team_A_total > team_B_total){
return team1;
}
else
if(team_B_total > team_A_total){
return team2;
}
else
if(team_A_total == team_B_total){
int number = rand();
if(number % 2 == 0){
return team1;}
else{
return team2;}
}
return 0;
}
/*header file*/
#ifndef JG_TOURNEY_H
#define JG_TOURNEY_H
typedef struct Player{
int offensive;
int defensive;
int number;
int team;
char first[255];
char last[255];
} Player;
typedef struct Team{
char * name;
Player * players;
} Team;
Team * initializeTeam(char * name,Player * players);
Team * game(Team * team1, Team * team2);
Team * tournament(Team **, int);
void deleteTeam(Team *);
#endif
/*Driver code*/
#include"tournament.h"
#include"tournament.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <string.h>
#define DEBUG 0
#define NUM_TEAMS 32
#define NUM_PLAYERS 10
Player * draftPlayers(char * filename, int team, int num_players);
int inLeague(Team *, Team **);
int main(){
/***** Change the team names to names of your choosing ******/
char * team_names[] = {
"team1",
"team2",
"team3",
"team4",
"team5",
"team6",
"team7",
"team8",
"team9",
"team10",
"team11",
"team12",
"team13",
"team14",
"team15",
"team16",
"team17",
"team18",
"team19",
"team20",
"team21",
"team22",
"team23",
"team24",
"team25",
"team25",
"team27",
"team28",
"team29",
"team30",
"team31",
"team32",
};
/********************************************************************/
/* DO NOT ALTER ANY OF THE THE DRIVER CODE BELOW */
/********************************************************************/
#if !DEBUG
fclose(stderr);
#endif
printf("\t-----------------------------------\n");
printf("\t- Creating Your League -\n");
printf("\t-----------------------------------\n");
srand(time(NULL));
printf("\n\t=========Test #1: Creating your Teams and Players===========\n\n");
Team ** league = malloc(sizeof(Team*) * NUM_TEAMS);
//create teams i.e. league of N teams.
for(int counter = 0; counter < NUM_TEAMS; counter++){
Player * draft = draftPlayers("players.dat", counter, NUM_PLAYERS);
assert(draft[0].team == counter%NUM_TEAMS);
league[counter] = initializeTeam(team_names[counter], draft);
assert(sizeof((league[counter]->players[rand() % NUM_PLAYERS])) == sizeof(Player));
assert((league[counter]->players[rand() % NUM_PLAYERS]).offensive > 0);
assert((league[counter]->players[rand() % NUM_PLAYERS]).defensive > 0);
assert(sizeof(*(league[counter])) == sizeof(Team));
}
printf("\n\t\t....League Initialized\n");
printf("\t-----------------------------------\n");
printf("\t- Part 1: Exhibition Games -\n");
printf("\t-----------------------------------\n");
printf("\n\t=========Test #1: Sanity check for the game===========\n\n");
Team * winner = game(NULL, NULL);
assert(winner == NULL);
printf("\n\t\t....Test Passed\n");
printf("\n\t=========Test #2: Playing a Game between two random teams===========\n\n");
Team * team1 = league[rand() % NUM_TEAMS];
Team * team2 = league[rand() % NUM_TEAMS];
printf("Up next, an exhibition game between %s and %s\n", team1->name, team2->name);
winner = game(team1, team2);
assert(winner == team1 || winner == team2);
printf("The winning team is %s\n\n", winner->name);
printf("\n\t\t....Test Passed\n");
printf("\n\t=========Test #3: Playing a Game between the same team===========\n\n");
int team_num = rand() % NUM_TEAMS;
printf("Up next, a a scrimmage for %s\n", league[team_num]->name);
winner = game(league[team_num], league[team_num]);
assert(winner == league[team_num]);
printf("The winning team is %s\n\n", winner->name);
printf("\n\t\t....Test Passed\n");
When running the created library file and running it with the driver code I fail the first test because of a segmentation fault. I know it has to do with something with my memory however I am unable to figure out where my code is causing this. I know it is a lot if code to deal with however I only included the parts of the code that is needed to run this test. Any help is very much appreiated.
(*team).name = name;
(*team).players = players;
It looks like you're trying to dereference team using *, then dereference it again using .name, so try removing the * and dereference with .name or ->name only.

Initializing a struct in C

Im having trouble initialising structures (well doing everything actually, but structures first). The struct is first made in a header as follows
typedef enum cell
{
BLANK, RED, CYAN
} Cell;
#define NAMELEN 20
typedef struct player
{
char name[NAMELEN + NULL_SPACE];
Cell token;
unsigned score;
} Player;
void initFirstPlayer(Player * player);
void initSecondPlayer(Player * player, Cell token);
#endif
=======================================================================
and I tried to initialise it here
void initFirstPlayer(Player * player)
{
int randNo = rand() % 2;
if (randNo == 0) {
token = RED;
}
else() {
token = CYAN;
}
player ; p1 = {
"placeholder",
token,
0,
}
}
void initSecondPlayer(Player * player, Cell token)
{ }
What is the correct way to initialise this player struct?
I suspect this should work for you. Use a generic initPlayer function. Use that to allocate memory for the player and set the initial values. Be sure to also include a freePlayer function where you free() the player when you're done.
#include <stdlib.h>
#include <string.h>
Player* initPlayer()
{
Player* player = malloc(sizeof(Player));
int randNo = rand() % 2;
if (randNo == 0) {
player->token = RED;
}
else {
player->token = CYAN;
}
const char* initName = "placeholder";
strcpy(player->name, initName);
player->score = 0;
return player;
}
void freePlayer(Player* p)
{
free(p);
}
The way you'd use this would be like so:
int main()
{
Player* p1 = initPlayer();
Player* p2 = initPlayer();
play(p1, p2);
freePlayer(p1);
freePlayer(p2);
}
Assuming you have at least C99 support, so that compound literals and designated initializers are available to you, then you can use:
void initFirstPlayer(Player *player)
{
*player = (Player){ .token = rand() % 2 ? CYAN : RED,
.score = 0,
.name = "placeholder"
};
}
This does a structure assignment to the variable whose address is passed to the function. It compresses it all into one statement; you can split it out into several if you wish. This is an occasion where the ternary ? : operator is useful. You might prefer (rand() % 2) with the extra parentheses; I'd probably add them as often as I'd omit them.
The compound literal comes from (typename){ ...initializer for typename... }.
The designated initializers are the .member = value notations.
If you're stuck with C90 support, you have to work harder, perhaps creating a local variable with the correct information and then doing the structure assignment.
void initFirstPlayer(Player *player)
{
Player p1 = { "placeholder", rand() % 2 ? CYAN : RED, 0 };
*player = p1;
}
Now the onus is on you to list the initializers in the correct sequence.
Another way is to receive the player you want to inicialize as parameter:
void initPlayer(Player* player)
{
int randNo = rand() % 2;
if (randNo == 0) {
player->token = RED;
}
else {
player->token = CYAN;
}
const char* initName = "placeholder";
strcpy(player->name, initName);
player->score = 0;
}
int main() {
Player p1;
initPlayer(&p1);
}
You can have an array of players or allocate dinamically with malloc.

How can I do it smarter?

I must read and extract some values from string.
These values are coded like this:
k="11,3,1" v="140.3"
I have defined the codes and created struct with all field as well as a temp one where I store k and v. In fillFields proc I transfer values from temp struct to the right one (with the valid types).
It works but I have many fields and fillFields would need to have many if-conditions. Maybe someone could give me any hint how to write it smarter.
The simplified code now:
#define ASK "11,3,1"
#define BID "11,2,1"
#define CLOSE "3,1,1"
typedef struct tic {
float ask;
float bid;
float close;
}tic, *ticP;
typedef struct pElem {
char * k;
char * v;
}pElem, *pElemP;
void fillFields(ticP t, pElemP p)
{
if (strcmp( ASK, p->k)==0)
{
printf ("ASK %s\n", p->v);
t->ask = atof(p->v);
}
if (strcmp( BID, p->k)==0)
{
printf ("BID %s\n", p->v);
t->bid = atof(p->v);
}
if (strcmp( CLOSE, p->k)==0)
{
printf("CLOSE >>>%s<<<\n", p->v) ;
t->close = atof (p->v);
}
}
Rather than save the text value in pElem, save the converted values.
This creates an extra step in parsing k="11,3,1" v="140.3", to convert text to an enumerated type, but it's paid once. The fillFields() calls then run simpler. Assuming you have more ticP variables, it's a win.
typedef enum pElem_type {
pElem_None, pElem_ASK, pElem_BID, pElem_CLOSE, pElem_N
} pElem_type;
typedef struct pElem {
pElem_type type;
float value;
} pElem;
void fillFields(ticP t, const pElem *p) {
switch (p->type) {
case pElem_ASK:
printf("ASK %f\n", p->value);
t->ask = p->value;
break;
case pElem_BID:
printf("BID %f\n", p->value);
t->bid = p->value;
break;
case pElem_CLOSE:
printf("Close %f\n", p->value);
t->close = p->value;
break;
default:
printf("Error\n");
}
}
// Further simplifications possible
typedef struct tic {
float field[pElem_N];
}tic, *ticP;
static const char *FieldName[pElem_N] = {
"None", "ASK", "BID", "Close"
};
void fillFields(ticP t, const pElem *p) {
if (p->type < pElem_N) {
printf("%s %f\n", FieldName[p->type], p->value);
t->field[p->type] = p->value;
}
}

printf with reference arguments

Imagine having a label that after created updates x amount of times / sec. The text of the label is given as a format-specifier text (ala printf), and any arguments for the format-specifier is updated on redraw, because the arguments for the format specifier is pointers to their respective values.
Does any variant of sprintf work like this?
The code would work something like this:
/* client */
createLabel("Value is %f", &myFloatValue);
I haven't quite figured out a way to do this yet, does anyone have any ideas? I guess one could parse the format text, retrieve the pointers (and types), and store them as some object in a list, where you later could reprint the text and maybe delegate the formatting to the objects themselves, passing them only a textbuffer.. hmmm
Btw, the interface is C, but the host is C++.
Okay i got a "working" prototype, but it's written mainly in assembler. Anyway it demonstrates the supposed use of the api. Can anyone see a portable way to do this / have a better idea for the implementation?
It's pretty large so i'm posting it on pastebin:
http://pastebin.com/H8ZpWb4u
So your createLabel interface would store the format string, along with the addresses of the variables you're wanting to display within the string. Then just use standard old sprintf to reformat the text. Just be careful with those pointers to the data, and make sure you invalidate them when necessary.
I'm not really sure what the problem is. What else are you looking for? sprintf is capable of doing what you want, but you're going to have to track the format string and variable addresses yourself.
Okay i suddenly got an idea .. stringstream + templated polymorphism. I ended up writing the thing in C++ in 5 mins, and at the very least it's a huge improvement.
#include <string>
#include <iostream>
#include <vector>
#include <sstream>
class CBaseValue
{
public:
virtual void toString(std::stringstream & buf) = 0;
};
template< typename T >
class CValue : public CBaseValue
{
typedef T type;
typedef T * ptr_type;
type * val;
public:
CValue(void * val)
{
this->val = reinterpret_cast<ptr_type>(val);
}
CValue(type * val) : val(val) {}
virtual void toString(std::stringstream & buf) {
buf << *val;
}
};
class CLabel
{
std::stringstream ss;
std::vector<CBaseValue *> valueList;
std::string format;
public:
CLabel() {};
void reset() {
format.clear();
ss.str("");
for(unsigned i = 0; i < valueList.size(); i++) {
delete valueList[i];
}
valueList.clear();
}
void setFormat(const char * fmt, ...) {
reset();
format = fmt;
va_list args;
va_start(args, fmt);
for(unsigned i = 0; i < format.size(); ++i) {
if(format[i] == '%') {
++i;
switch(fmt[i])
{
case 'd':
valueList.push_back(new CValue<unsigned int>( va_arg(args, void *) ));
break;
case 'f':
valueList.push_back(new CValue<float>( va_arg(args, void *) ));
break;
}
}
}
va_end(args);
}
std::string get() {
ss.str("");
unsigned count(0);
for(unsigned i = 0; i < format.size(); i++) {
if(format[i] == '%') {
i++; // ignore type specifiers, already polymorphically solved
valueList[count++]->toString(ss);
} else {
ss << format[i];
}
}
return ss.str();
}
~CLabel() {
reset();
}
};
int main() {
int test = 2;
float val = 3.14f;
CLabel myLabel;
myLabel.setFormat("Stringstream test, float: %f, and an int: %d \n", &val, &test);
std::cout << myLabel.get();
test = 3;
std::cout << myLabel.get();
system("pause");
}
You could do something relatively simple with std::bind or boost::bind. I'll leave it as an exercise on how to massage a C interface on top of this.
#include <functional>
int main() {
int test = 2;
float val = 3.14f;
std::function<int()> label = std::bind(
printf,
"Stringstream test, float: %f, and an int: %d \n",
std::ref(val),
std::ref(test));
label();
test = 3;
label();
}

Resources