Skip List (Linked List with levels) Destructor -> getting segmentation fault - linked-list

So this is my destructor for SkipList and I am getting segmentation fault for some reason, here is my code.
for (int i = 1; i <= levels; i++) {
SNode *curr = head;
while (curr != nullptr) {
SNode *Next = curr->next[i];
delete curr;
curr = Next;
}
}
head = 0;
}
Getting an error when I try to make a new SkipList in main.cpp

Related

CS50 pset5 Speller [2022] - " :( program is free of memory errors"

I get error ":( program is free of memory errors valgrind tests failed; see log for more information."
Here is my code:
// Implements a dictionary's functionality
#include <ctype.h>
#include <stdbool.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#include "dictionary.h"
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// TODO: Choose number of buckets in hash table
const unsigned int N = 26;
// Hash table
node *table[N];
//Declare variables
unsigned int word_count;
unsigned int hash_value;
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
// TODO
hash_value = hash(word);
node *cursor = table[hash_value];
// Go in link list
while (cursor != 0)
{
if (strcasecmp(word, cursor->word) == 0)
{
return true;
}
cursor = cursor->next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
// TODO: Improve this hash function
unsigned long total = 0;
for (int i = 0; i < strlen(word); i++)
{
total += tolower(word[i]);
}
return total % N;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
// Open dictionary
FILE *file = fopen(dictionary, "r");
// it would be null if cant be open
if (file == NULL)
{
printf("Unable to open %s\n", dictionary);
return false;
}
// Declare variable words
char word[LENGTH + 1];
//Scan dictionary for strings up until EOF
while (fscanf(file, "%s", word) != EOF)
{
node *n = malloc(sizeof(node));
if (n == NULL)
{
return false;
}
//copy wordds into node
strcpy(n->word, word);
hash_value = hash(word);
n->next = table[hash_value];
table[hash_value] = n;
word_count++;
}
fclose(file);
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
if (word_count > 0)
{
return word_count;
}
return 0;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
for (int i = 0; i < N; i++)
{
node *cursor = table[i];
while (cursor)
{
node *tmp = cursor;
cursor = cursor->next;
free(tmp);
}
if (cursor == NULL)
{
return true;
}
}
return false;
}
Here are the errors in valgrind check50:
program is free of memory errors valgrind tests failed; see log for more information.
Here is ERR log:
56 bytes in 1 blocks are still reachable in loss record 1 of 1: (file: dictionary.c, line: 80)
And 80th line code is:
while (fscanf(file, "%s", word) != EOF)
{
node *n = malloc(sizeof(node));
if (n == NULL)
{
return false;
}
unload will free one index and return to speller because of this if (cursor == NULL) block. The last node in an index should set cursor to NULL, so function is done. That conditional should be eliminated. There is really no condition in unload that should return false.

How to code a MACD in an expert advisor that uses EMA instead of SMA for the signal line

#include <MovingAverages.mqh>
input int fast = 7;
input int slow = 26;
input int signallength =9;
input int closeoropen = 1; //close=0, open=1
input int movingavglength =114;
double ema, macd, signal;
double ind_buffer1[26], ind_buffer2[26];
bool sellsignaldone = false;
bool buysignaldone = false;
void OnTick()
{
ema = iMA(NULL,0,movingavglength,0,MODE_EMA,PRICE_CLOSE,1);
//---- macd counted in the 1-st buffer
for(int i=0; i<slow-1; i++)
ind_buffer1[i]=iMA(NULL,0,fast,0,MODE_EMA,closeoropen,i)-iMA(NULL,0,slow,0,MODE_EMA,closeoropen,i);
//---- signal line counted in the 2-nd buffer
for(int i=0; i<slow-1; i++)
ind_buffer2[i]=iMAOnArray(ind_buffer1,0,signallength,0,MODE_EMA,i);
macd = ind_buffer1[1];
signal = ind_buffer2[1];
if (macd > signal && macd<0 && Close[1]>ema && !buysignaldone && OrdersTotal()==0) {
buysignaldone = true;
OrderSend(NULL, OP_BUY,1/Ask, Ask, 3, Ask-(Ask*0.004), Ask+(Ask*0.008), "Buy Order",0,0,clrGreen);
}
if (macd < signal) {
buysignaldone = false;
}
if (macd < signal && macd>0 && Close[1]<ema && !sellsignaldone && OrdersTotal()==0) {
sellsignaldone = true;
OrderSend(NULL, OP_SELL,1/Bid, Bid, 3, Bid+(Bid*0.004), Bid-(Bid*0.008), "Sell Order",0,0,clrRed);
}
if (macd > signal) {
sellsignaldone = false;
}
}
You can't use iMACD for this. I'm not sure what I've done wrong but the signals are in the wrong place
Crossover is here
I got a much better result using iOsMA, but it's still not identical to the indicator.
#property strict
#include <MovingAverages.mqh>
input int fast = 7;
input int slow = 26;
input int signallength =9;
input int closeoropen = 1; //close=0, open=1
input int movingavglength =114;
double sma1, sma2, ema, macd, fastema, slowema, signal;
double ind_buffer1[26], ind_buffer2[26];
bool sellsignaldone = false;
bool buysignaldone = false;
void OnTick()
{
signal = iOsMA(NULL,0,fast,slow,signallength,closeoropen,1);
fastema = iMA(NULL,0,fast,0,MODE_EMA,closeoropen,1);
slowema = iMA(NULL,0,slow,0,MODE_EMA,closeoropen,1);
macd = fastema-slowema;
ema = iMA(NULL,0,movingavglength,0,MODE_EMA,PRICE_CLOSE,1);
if (signal>0 && macd<0 && Close[1]>ema && !buysignaldone && OrdersTotal()==0) {
buysignaldone = true;
OrderSend(NULL, OP_BUY,1/Ask, Ask, 3, Ask-(Ask*0.004), Ask+(Ask*0.008), "Buy Order",0,0,clrGreen);
}
if (macd < signal) {
buysignaldone = false;
}
if (signal<0 && macd>0 && Close[1]<ema && !sellsignaldone && OrdersTotal()==0) {
sellsignaldone = true;
OrderSend(NULL, OP_SELL,1/Bid, Bid, 3, Bid+(Bid*0.004), Bid-(Bid*0.008), "Sell Order",0,0,clrRed);
}
if (macd > signal) {
sellsignaldone = false;
}
}
You can also modify the MACD indicator in the indicator folder, simply adding on the bottom the "ExponentialMAOnBuffer(...);" and "call" the second indicator in the expert using the iCustom function linked to the number of the index of the indicator. (es. for MACD (0,ExtMacdBuffer);(1,ExtSignalBuffer);)
the ea code now is more clear!

MQL4 code limiting number of open symbols

I am trying to create an expert advisor ( EA ) that would limit the number of open symbol to 3
For example, if I load the EA on 15 different symbols, it would not open a trade on more than 3 at any particular time. Below is the code I inserted in the EA but not working as I want:
int SYMBOL_NUMBER_LIMIT = 3;
string COUNTED_SYMBOLS[];
ArrayResize(COUNTED_SYMBOLS, SYMBOL_NUMBER_LIMIT, 0);
for(int s=0; s<SYMBOL_NUMBER_LIMIT; s++) COUNTED_SYMBOLS[s]="";
int SYMBOLS_IN_TRADE_SO_FAR = 0;
bool NEW_TRADE_PERMISSION = true;
int ALL_POSITIONS = OrdersTotal(); // PositionsTotal();
if(ALL_POSITIONS > 0)
{
for(int index=0; index<ALL_POSITIONS; index++)
{
string THIS_SYMBOL = OrderSymbol(); // PositionGetSymbol(index);
bool Symbol_already_counted = false;
for(int i=0; i<SYMBOL_NUMBER_LIMIT; i++)
{
if(COUNTED_SYMBOLS[i]==THIS_SYMBOL)
{
Symbol_already_counted = true;
break;
}
if(Symbol_already_counted) continue;
else
{
SYMBOLS_IN_TRADE_SO_FAR++;
if(SYMBOLS_IN_TRADE_SO_FAR >= SYMBOL_NUMBER_LIMIT)
{
NEW_TRADE_PERMISSION = false;
break;
}
for(int j=0; j<SYMBOL_NUMBER_LIMIT; j++)
if(COUNTED_SYMBOLS[j]=="")
{
COUNTED_SYMBOLS[j] = THIS_SYMBOL;
break;
}
}
}
}
}
I would appreciate any help to make it work as I described. Thanks in advance

wxWidgets serial Commuication

I have absolutely no experience in programming serial communication and since I'm stuck with my code I'd really appreciate your help! Thank you already!
So now to my problem:
I got a generator on which are several different sensors who communicate over CAN with a microcontroller. This mc itself communicates with a device from USBTin again over CAN. On the USBTin, a little board, is mainly a CAN controller and a microcontroller which are precoded from its developer.
So my task now is to open my COM Port, send the right messages to the USBTin (those are "S5" for the baudrate and 'O' for Open CAN) and then receive the data.
First of all the functions and my problem:
The problem is that in my output textfield stands something like "PPPPPPPPPP,Râö". There are always these 10 P's and some random characters. I have no idea where the P's or these additional "Râö" comes from. The actual output string shoud be something like "T1E18001F8". I tested that with hTerm, which is a terminal programm for serial communication.
OPEN:
long Serial::Open()
{
if (IsOpened()) return 0;
#ifdef UNICODE
wstring wtext(port.begin(),port.end());
#else
string wtext = port;
#endif
hComm = CreateFile(wtext.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE) {return 1;}
if (PurgeComm(hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR |
PURGE_RXCLEAR) == 0) {return 2;}//purge
//get initial state
DCB dcbOri;
bool fSuccess;
fSuccess = GetCommState(hComm, &dcbOri);
if (!fSuccess) {return 3;}
DCB dcb1 = dcbOri;
dcb1.BaudRate = baud;
if (parity == 'E') dcb1.Parity = EVENPARITY;
else if (parity == 'O') dcb1.Parity = ODDPARITY;
else if (parity == 'M') dcb1.Parity = MARKPARITY;
else if (parity == 'S') dcb1.Parity = SPACEPARITY;
else if (parity == 'N') dcb1.Parity = NOPARITY;
dcb1.ByteSize = (BYTE)dsize;
if(stopbits==2) dcb1.StopBits = TWOSTOPBITS;
else if (stopbits == 1.5) dcb1.StopBits = ONE5STOPBITS;
else if (stopbits == 1) dcb1.StopBits = ONE5STOPBITS;
dcb1.fOutxCtsFlow = false;
dcb1.fOutxDsrFlow = false;
dcb1.fOutX = false;
dcb1.fDtrControl = DTR_CONTROL_DISABLE;
dcb1.fRtsControl = RTS_CONTROL_DISABLE;
fSuccess = SetCommState(hComm, &dcb1);
delay(60);
if (!fSuccess) {return 4;}
fSuccess = GetCommState(hComm, &dcb1);
if (!fSuccess) {return 5;}
osReader = { 0 };// Create the overlapped event. Must be closed before
exiting to avoid a handle leak.
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osReader.hEvent == NULL) {return 6;}// Error creating overlapped event;
abort.
fWaitingOnRead = FALSE;
osWrite = { 0 };
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osWrite.hEvent == NULL) {return 7;}
if (!GetCommTimeouts(hComm, &timeouts_ori)) { return 8; } // Error getting
time-outs.
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout = 20;
timeouts.ReadTotalTimeoutMultiplier = 15;
timeouts.ReadTotalTimeoutConstant = 100;
timeouts.WriteTotalTimeoutMultiplier = 15;
timeouts.WriteTotalTimeoutConstant = 100;
if (!SetCommTimeouts(hComm, &timeouts)) { return 9;} // Error setting time-
outs.
return 0;
}
WRITE:
bool Serial::Write(char *data)
{
if (!IsOpened()) {
return false;
}
BOOL fRes;
DWORD dwWritten;
long n = strlen(data);
if (n < 0) n = 0;
else if(n > 1024) n = 1024;
// Issue write.
if (!WriteFile(hComm, data, n, &dwWritten, &osWrite)) {
if (GetLastError() != ERROR_IO_PENDING) {fRes = FALSE;}// WriteFile
failed, but it isn't delayed. Report error and abort.
else {// Write is pending.
if (!GetOverlappedResult(hComm, &osWrite, &dwWritten, TRUE))
fRes = FALSE;
else fRes = TRUE;// Write operation completed successfully.
}
}
else fRes = TRUE;// WriteFile completed immediately.
return fRes;
}
READCHAR:
char Serial::ReadChar(bool& success)
{
success = false;
if (!IsOpened()) {return 0;}
DWORD dwRead;
DWORD length=1;
BYTE* data = (BYTE*)(&rxchar);
//the creation of the overlapped read operation
if (!fWaitingOnRead) {
// Issue read operation.
if (!ReadFile(hComm, data, length, &dwRead, &osReader)) {
if (GetLastError() != ERROR_IO_PENDING) { /*Error*/}
else { fWaitingOnRead = TRUE; /*Waiting*/}
}
else {if(dwRead==length) success = true;}//success
}
//detection of the completion of an overlapped read operation
DWORD dwRes;
if (fWaitingOnRead) {
dwRes = WaitForSingleObject(osReader.hEvent, READ_TIMEOUT);
switch (dwRes)
{
// Read completed.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hComm, &osReader, &dwRead, FALSE))
{/*Error*/ }
else {
if (dwRead == length) success = true;
fWaitingOnRead = FALSE;// Reset flag so that another
opertion
can be issued.
}// Read completed successfully.
break;
case WAIT_TIMEOUT:
// Operation isn't complete yet.
break;
default:
// Error in the WaitForSingleObject;
break;
}
}
return rxchar;
}
And Finally the excerpt of the main in wxWidgets to display the received data:
void GUI_1_2Frame::OnConnectButtonClick(wxCommandEvent& (event))
{
char tempString[10] = {0};
bool ReadChar_success = true;
char temp_Char;
/* Preset Serial Port setting */
Serial com(com_x, 115200, 8, NOPARITY, 1);
char* buffer;
if(connection_flag)
{
/* Port was connected, Disconnect Button unsed*/
com.Close();
wxMessageBox(_("Port closed"),_("Info!"),wxICON_INFORMATION);
connection_flag = 0;
ConnectButton->SetLabel("Connect");
TextCtrl1->SetValue("");
}
else
{
/* If open() == true -> INVALID HANDLE */
if(com.Open())
{
wxMessageBox(_("Port not available"),_("ERROR!"),wxICON_ERROR);
}
else /* Port Opened */
{
TextCtrl1->SetValue(com.GetPort());
ConnectButton->SetLabel("Disconnect");
connection_flag = 1;
}
if(com.Write("S5"))
{
TextCtrl1->SetValue("Baudrate sent!\n");
delay(100);
if(com.WriteChar('O'))
{
TextCtrl1->SetValue("Baudrate & Open Command sent!");
int i =0;
while(i<10)
{
temp_Char = com.ReadChar(ReadChar_success);
tempString[i] = temp_Char;
i++;
}
com.WriteChar('C');
com.Close();
//com.readSerialPort(data, MAX_DATA_LENGTH);
TextCtrl2->SetValue(tempString);
//wxMessageOutput::Get()->Printf("%s", tempString);
}
else
{
TextCtrl1->SetValue("Open Command Error!"); }
}
else
{
TextCtrl1->SetValue("Error!");
}
}
}
Since I am not native speaking englisch I say sorry for my language mistakes.
Thank everybody a lot and again I really appreciate every single hint!
Greetings,
MSol

Linked list exercise in C, what is wrong?

The code below does compile, but it doesn't run as it should.
I'm not sure what am I doing wrong, so would someone be willing to tell me what I did wrong and what I should have done better.
What do I need to change to make it run properly?
#include<stdio.h>
#include<stdlib.h>
typedef struct sub_Node
{
int value;
struct sub_Node *next;
}sub_Node;
typedef struct Node
{
char *name;
struct Node *next;
struct sub_Node *sub_start;
}Node;
Node *start;
void add_player(char *name)
{
Node *temp;
temp = (Node *)malloc(sizeof(Node));
temp->next = start;
temp->name = name;
temp->sub_start = (sub_Node *)malloc(sizeof(sub_Node));
temp->sub_start->next = NULL;
temp->sub_start->value = -1;
start = temp;
}
void initialize()
{
char *p;
p = "\0";
add_player(p);
}
void remove_player(char *name)
{
Node *p;
for(p = start; p!= NULL; p = p->next)
if(p->name == name)
{
p->name = p->next->name;
p->next = p->next->next;
}
}
sub_Node* add_descending(sub_Node* sub_start, int piece_value)
{
sub_Node *temp, *prev, *next;
temp = (sub_Node *)malloc(sizeof(sub_Node));
temp->value = piece_value;
temp->next = NULL;
prev = NULL;
next = sub_start;
while(next && next->value >= piece_value)
{
prev = next;
next = next->next;
}
if(!next)
{
prev->next = temp;
}
else
{
if(prev)
{
temp->next = prev->next;
prev->next = temp;
}
else
{
temp->next = sub_start;
sub_start = temp;
}
}
return sub_start;
}
void add_piece(char *name, int piece_value)
{
Node *p;
int c;
for(p = start; p!=NULL; p = p->next)
if(p->name == name)
p->sub_start = add_descending(p->sub_start, piece_value);
}
void print_pieces(char *name)
{
Node *p;
sub_Node *q;
for(p = start; p!=NULL; p = p->next)
if(p->name == name)
{
printf("The values of the owned pieces are:");
for(q = p->sub_start; q->value != -1; q = q->next)
printf(" %d", q->value);
}
}
int lose_piece(char *name)
{
Node *p;
sub_Node *q;
int aux;
for(p = start; p!=NULL; p = p->next)
if(p->name == name)
{
for(q = p->sub_start; q->next->value != -1; q = q->next) {}
aux = q->value;
q->value = q->next->value;
q->next = q->next->next;
return aux;
}
}
void print_players()
{
Node *p;
printf("The players are: ");
for(p = start; p->name != "\0"; p = p->next)
printf("%s ", p->name);
printf("\n");
}
int main()
{
initialize();
int y, value;
char name[20];
printf("Insert a digit to execute the desired task:\n"
"<0> end the program\n"
"<1> add a player, who doesn't own any piece yet\n"
"<2> remove a player and all his pieces\n"
"<3> print the name of all the players\n"
"<4> a player gets a piece\n"
"<5> a player loses the piece with the lowest value out of the ones that he has\n"
"<6> prints the pieces of a player in a descending order by value\n\n");
do
{
printf("digit: ");
scanf("%d", &y);
switch(y)
{
case 1:
printf("Insert the player's name: ");
scanf("%s", name);
add_player(name);
break;
case 2:
printf("Insert the player's name: ");
scanf("%s", name);
remove_player(name);
break;
case 3:
print_players();
break;
case 4:
printf("Insert the player's name: ");
scanf("%s", name);
printf("Insert the value of the piece: ");
scanf("%d", value);
add_piece(name, value);
break;
case 5:
printf("Insert the player's name: ");
scanf("%s", name);
printf("\nThe player loses the piece: %d\n", lose_piece(name));
break;
case 6:
printf("Insert the player's name: ");
scanf("%s", name);
print_pieces(name);
}
} while(y != 0);
return 0;
}
your two main problems where this scanf("%d", value); value should be passed by reference like this scanf("%d", &value); and the second is string comparison in c as in your code p->name != "\0" and if(p->name == name) this is wrong because actually you are making comparison between addresses of strings (where it resides in memory) not strings values. to compare strings in c you have to use strcmp and families.
Actually 3 main problems. for setting string values as you did in temp->name = name; is little bit more complicated than that. because you are assigning to temp->name a string from the stack that is volatile (the stack will be more likely invalid soon you return from the function) . in your case you have to alloc a new string by using malloc (and friends) or just by using strdup.
here is as a bonus a slightly rewrite of your program, you will find many advises and is a good starting point for how to structure your code for an easy maintenance.
still want to advise you to change members and variables to more declarative names as in sub_start and sub_Node can be PieceNode and pieces respectively.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct sub_Node
{
int value;
struct sub_Node *next;
}sub_Node;
typedef struct Node
{
char *name;
struct Node *next;
struct Node *prev; // this to make life easyer
struct sub_Node *sub_start;
}Node;
Node *start = NULL;
Node *find_player(char *name){
Node *tmp = start;
while( tmp ){
if(strcmp(tmp->name,name) == 0 )
break;
tmp = tmp->next;
}
return tmp;
}
// int to return Error Code
//
int add_player(char *name)
{
Node *temp;
if( find_player(name)) {
printf("player %s already exists\n", name);
return 1;
}
// do not cast malloc
temp = malloc(sizeof(Node));
if( !temp ){
printf ("not enough memory\n");
return 2;
}
temp->name = strdup ( name); // here was your error
temp->sub_start = NULL; // keep it simple
temp->prev = NULL;
temp->next = start;
if(start)
start->prev = temp;
start = temp;
return 0; // no error
}
void DestroyPieces(sub_Node* piece){
if( piece ) {
DestroyPieces( piece->next );
free( piece );
}
}
// as usual use int to return error code
int remove_player(char *name)
{
Node *player = find_player(name);
if ( !player ){
return 1; // player not found
}
if ( player->next ){
player->next->prev = player->prev;
}
if ( player->prev ){
player->prev->next = player->next;
}
DestroyPieces(player->sub_start);
free(player->name);
free(player);
return 0; // success
}
sub_Node* new_piece(int value){
sub_Node *temp = malloc( sizeof(sub_Node) );
if(temp){
temp->value = value;
temp->next = NULL;
}
return temp;
}
// int to return error code
// pass sub_start as pointer to pointer, as it might be updated
int add_descending(sub_Node** psub_start, int piece_value)
{
sub_Node *piece, *current, *prev = NULL;
if( !psub_start){
return 5; // this should not happen
}
current = *psub_start;
piece = new_piece( piece_value );
if( !piece ) return 1; // no mem
if(!current){
// this is the first and only one
*psub_start = piece;
return 0; // OK
}
while(current && current->value >= piece_value)
{
prev = current;
current = current->next;
}
if( prev )
prev->next = piece;
piece->next = current;
if( current == *psub_start ){
*psub_start = piece;
}
return 0 ; // OK
}
void add_piece(Node * player, int piece_value)
{
if ( !player) {
return ;
}
if(add_descending (&(player->sub_start), piece_value) == 0 )
return ; //OK
printf("an error occured while adding a piece (%d) to player '%s'\n",piece_value,player->name);
}
void print_pieces(Node *player)
{
sub_Node *q;
if( !player ){
return;
}
if( !player->sub_start ){
printf("Player '%s' has no pieces\n",player->name);
return;
}
printf("The values of the owned pieces are:");
for(q = player->sub_start; q != NULL; q = q->next)
printf(" %d", q->value);
printf("\n");
}
void lose_piece(Node *player)
{
if( !player ){
return;
}
sub_Node *q, *prev = NULL;
int aux;
if( !player->sub_start ){
printf("Player '%s' has no pieces\n",player->name);
return;
}
// i think you want drop the last one
for(q = player->sub_start; q->next != NULL ;prev = q, q = q->next) {
;
}
if(prev)
prev->next = NULL;
else
player->sub_start = NULL;
aux = q->value;
free(q);
printf("\nThe player loses the piece: %d\n", aux);
return;
}
void print_players()
{
Node *p;
if( !start ){
printf("there are no players, try to add some\n");
return;
}
printf("The players are: ");
for(p = start; p != NULL; p = p->next)
printf("%s ", p->name);
printf("\n");
}
void print_menu(void){
printf("Insert a digit to execute the desired task:\n"
"<0> end the program\n"
"<1> add a player, who doesn't own any piece yet\n"
"<2> remove a player and all his pieces\n"
"<3> print the name of all the players\n"
"<4> a player gets a piece\n"
"<5> a player loses the piece with the lowest value out of the ones that he has\n"
"<6> prints the pieces of a player in a descending order by value\n\n");
}
Node * get_player(char *name){
Node *player = find_player(name);
if(!player)
printf("Player '%s' do not exists\n",name);
return player;
}
int main()
{
// initialize(); no more needed
int y, value;
char name[20];
Node *player;
print_menu();
do
{
printf("digit: ");
scanf("%d", &y);
switch(y)
{
case 1:
printf("Insert the player's name: ");
scanf("%s", name);
add_player(name);
break;
case 2:
printf("Insert the player's name: ");
scanf("%s", name);
player = get_player(name);
if( player )
break;
case 3:
print_players();
break;
case 4:
printf("Insert the player's name: ");
scanf("%s", name);
player = get_player(name);
if( player ){
printf("Insert the value of the piece: ");
scanf("%d", &value);
add_piece(player, value);
}
break;
case 5:
printf("Insert the player's name: ");
scanf("%s", name);
player = get_player(name);
lose_piece(player);
break;
case 6:
printf("Insert the player's name: ");
scanf("%s", name);
player = get_player(name);
print_pieces(player);
}
} while(y != 0);
return 0;
}

Resources