MQL5 array in for loop takes too long, any better way? - arrays

I'm writing a EA for strategy tester purpose only, to evaluate portfolio. So I have hundreads/thousands of trades in an array, with open price and open time, and every 1 minute bar I check in a for loop if there's any trade to open in that minute. And it's taking forever.
How can I check (in a faster way) if in an array there's a open-time that coincides with current time?
Thanks!
if(NewBar)
{
CopyRates(_Symbol,PERIOD_M1,0,5,candle);
sizeAr=ArraySize(ar);
arColumns=ArrayRange(ar,1);
datetime candleNowTime = candle[0].time;
datetime nextCandleTime = candle[0].time+60;
for(int i=0;i<sizeAr/arColumns;i++)
{
if(ar[i][openTime]>candleNowTime && ar[i][openTime]<nextCandleTime)
{
//code to open trades
}
}
}
And the complete code is here:
//+------------------------------------------------------------------+
//| HedgeExperienceV001.mq5 |
//| Carlos Duna |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Carlos Duna"
#property link "https://www.mql5.com"
#property version "1.00"
#property tester_file "sinais.csv"
#include <Trade\Trade.mqh>
CTrade trade;
#include <Trade\SymbolInfo.mqh>
CSymbolInfo mysymbol;
#define columns 19
input double initialVolume = 0.01; // Volume inicial
input double slFixo = 0; // SL fixo (pips)(zero=SL do sinal)
input double tpFixo = 0; // TP fixo (pips)(zero=TP do sinal)
input ulong maxSlippage = 0; // Max Deviation/Slippage(0-não usa)
input double maxPricesVariation =10;// Max % variação Bid x TP x SL x OP
MqlRates candle[];
MqlDateTime TimeStruct;
MqlDateTime dealDay;
datetime dealDayStruct;
datetime now;
int secAnterior;
int previousDay;
bool NewBar;
datetime hj;
string orderComment;
bool orderOkToOpen;
datetime inicioHedge=0;
double profitPerMagic[][2];
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
struct SLine
{
string field[];
};
SLine lines[];
string ar[][columns];
int sizeLine;
int sizeAr;
int arColumns;
double stopLossDelta;
double takeProfitDelta;
/*
lines[i].field[j]
** i= numero de cada trade, iniciando no zero (não há títulos de colunas), indo dinamicamente até a ultima linha
** j= valores dos campos
0 - tCanal
1 - str(msgId)
2 - dataHora HoraEntrada
3 - str(opType) CompraOuVenda
4 - ativo.upper()
5 - str(openPrice)
6 - str(stopLoss)
7 - str(takeProfit1)
8 - str(takeProfit2)
9 - str(takeProfit3)
10 - str(takeProfit4)
11 - str(takeProfit5)
12 - 'false' posição já foi aberta? true/false
13 - 'false' posição já foi fechada? true/false
14 - HalfCloseTime
15 - ManualCloseTime
16 - SLModify_Time
17 - SLModify_Price])
18 - magicCanal
*/
int xCanal = 0; // tCanal
int xOpCod = 1; // str(msgId)
int xDtEnt = 2; // dataHora HoraEntrada
int xBuySell=3; // str(opType) CompraOuVenda
int xAtv= 4; // ativo.upper()
int xOP = 5; // str(openPrice)
int xSL=6; // str(stopLoss)
int xTP1 = 7; // str(takeProfit1)
int xTP2 = 8; // str(takeProfit2)
int xTP3 = 9; // str(takeProfit3)
int xTP4 = 10; // str(takeProfit4)
int xTP5 = 11; // str(takeProfit5)
int xOpened = 12; // posição já foi aberta? true/false
int xClosed = 13; // posição já foi fechada? true/false
int xHalfC=14; // HalfCloseTime
int xManualC = 15; // ManualCloseTime
int xSLMTime = 16; // SLModify_Time
int xSLMPrice= 17; // SLModify_Price
int xMagic=18; // magicCanal
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
ArraySetAsSeries(candle,true);
if(!ReadFileToArrayCSV("sinais.csv",lines))
{
Alert("Error, see the \"Experts\" tab for details");
return(INIT_FAILED);
}
sizeLine=ArraySize(lines);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
ArrayFree(lines);
ArrayFree(ar);
double a = ProfitClosedPosition();
Print(a);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
now=TimeCurrent();
TimeToStruct(TimeCurrent(),TimeStruct);
if(previousDay!=TimeStruct.day_of_year) //Runs once a day
{
previousDay=TimeStruct.day_of_year;
// recria diariamente o array auxiliar ar
ArrayResize(ar,sizeLine);
for(int i=0;i<sizeLine;i++)
{
for(int j=0;j<columns;j++)
{
ar[i][j]=lines[i].field[j];
}
}
// após array ar recriado, elimina-se o que não for ser usado no dia
for(int i=sizeLine-1; i>=0; i--)
{
TimeToStruct((datetime)lines[i].field[xDtEnt],dealDay);
// if temporario; o deal close não será por data, e sim pelo fechamento do trade, a ser sinalizado no futuro
if(dealDay.day_of_year+2<TimeStruct.day_of_year && dealDay.year==TimeStruct.year)
{
ArrayRemove(ar,i,1);
}
// remove entradas cujas datas de entrada sejam superiores ao dia de hoje ou que possuam flag 'closed'
if((dealDay.day_of_year>TimeStruct.day_of_year && dealDay.year<=TimeStruct.year) || (lines[i].field[xClosed]==true))
{
ArrayRemove(ar,i,1);
}
}
}
NewBar=isNewBar();
if(NewBar)
{
CopyRates(_Symbol,PERIOD_M1,0,5,candle);
sizeAr=ArraySize(ar);
arColumns=ArrayRange(ar,1);
datetime candleNowTime = candle[0].time;
datetime nextCandleTime = candle[0].time+60;
for(int i=0;i<sizeAr/arColumns;i++)
{
if(ar[i][xDtEnt]>candleNowTime && ar[i][xDtEnt]<nextCandleTime)
{
fAbrirOp(i);
Print(ar[i][xCanal]," / ",ar[i][xOP]," / ",ar[i][xSL]," / ",ar[i][xTP1]);
}
}
}
}
//+------------------------------------------------------------------+
//| Função que transforma arquivo CSV em array |
//+------------------------------------------------------------------+
bool ReadFileToArrayCSV(string FileName,SLine &Lines[])
{
ResetLastError();
int h=FileOpen(FileName,FILE_READ|FILE_ANSI|FILE_CSV|FILE_COMMON,";");
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
if(h==INVALID_HANDLE)
{
int ErrNum=GetLastError();
printf("Error opening file %s # %i",FileName,ErrNum);
return(false);
}
int lcnt=0; // variable for calculating lines
int fcnt=0; // variable for calculating line fields
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
while(!FileIsEnding(h))
{
string str=FileReadString(h);
// new line (new element of the structure array)
if(lcnt>=ArraySize(Lines))
{ // structure array completely filled
ArrayResize(Lines,ArraySize(Lines)+1024); // increase the array size by 1024 elements
}
ArrayResize(Lines[lcnt].field,64);// change the array size in the structure
Lines[lcnt].field[0]=str; // assign the first field value
// start reading other fields in the line
fcnt=1; // till one element in the line array is occupied
while(!FileIsLineEnding(h))
{ // read the rest of fields in the line
str=FileReadString(h);
if(fcnt>=ArraySize(Lines[lcnt].field))
{ // field array is completely filled
ArrayResize(Lines[lcnt].field,ArraySize(Lines[lcnt].field)+64); // increase the array size by 64 elements
}
Lines[lcnt].field[fcnt]=str; // assign the value of the next field
fcnt++; // increase the line counter
}
ArrayResize(Lines[lcnt].field,fcnt); // change the size of the field array according to the actual number of fields
lcnt++; // increase the line counter
}
ArrayResize(Lines,lcnt); // change the array of structures (lines) according to the actual number of lines
FileClose(h);
return(true);
}
//+------------------------------------------------------------------+
//| Função checar nova barra |
//+------------------------------------------------------------------+
bool isNewBar(void)
{
//--- memorize the time of opening of the last bar in the static variable
static datetime last_time=0;
//--- current time
datetime lastbar_time=(datetime)SeriesInfoInteger(Symbol(),PERIOD_M1,SERIES_LASTBAR_DATE);
//--- if it is the first call of the function
if(last_time==0)
{
//--- set the time and exit
last_time=lastbar_time;
return(false);
}
//--- if the time differs
if(last_time!=lastbar_time)
{
//--- memorize the time and return true
last_time=lastbar_time;
return(true);
}
//--- if we passed to this line, then the bar is not new; return false
return(false);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| entrada em operação |
//+------------------------------------------------------------------+
void fAbrirOp(int i)
{
if(inicioHedge==0)inicioHedge=datetime(ar[i][xDtEnt]);
double _TP;
double _SL;
orderOkToOpen=true;
Print("iniciando ativo: ",ar[i][xAtv]);
if(!mysymbol.Name(ar[i][xAtv]))
{
Print("Erro ao selecionar ativo ",ar[i][xAtv],"; operação não será aberta.");
orderOkToOpen=false;
}
mysymbol.RefreshRates();
double spread=mysymbol.Spread();
double bid = mysymbol.Bid();
double ask = mysymbol.Ask();
double maxPrice = ask * (100 + maxPricesVariation)/100;
double minPrice = bid * (100 - maxPricesVariation)/100;
//--- tuning for 3 or 5 digits
int digits_adjust=1;
if(mysymbol.Digits()==3 || mysymbol.Digits()==5)
digits_adjust=10;
stopLossDelta = slFixo*digits_adjust;
takeProfitDelta = tpFixo*digits_adjust;
if(maxSlippage!=0) trade.SetDeviationInPoints(maxSlippage);
if(double(ar[i][xOP])<minPrice || double(ar[i][xOP])>maxPrice || double(ar[i][xSL])<minPrice || double(ar[i][xSL])>maxPrice || double(ar[i][xTP1])<minPrice || double(ar[i][xTP1])>maxPrice)
{
Print("Erro nos níveis de preço do ativo ",ar[i][xAtv],". Bid = ",bid," / Open Price: ",ar[i][xOP]," / SL: ",ar[i][xSL]," / TP: ",ar[i][xTP1]," operação não será aberta.");
orderOkToOpen=false;
}
if(orderOkToOpen)
{
trade.SetExpertMagicNumber(ulong(ar[i][xMagic]));
if(ar[i][xBuySell]=="buy")
{
_TP = tpFixo == 0 ? double(ar[i][xTP1]) : double(ar[i][xOP]) + takeProfitDelta;
_SL = slFixo == 0 ? double(ar[i][xSL]) : double(ar[i][xOP]) - stopLossDelta;
if(trade.Buy(initialVolume,ar[i][xAtv],double(ar[i][xOP]),_SL,_TP,ar[i][xCanal]))
{
ar[i][xOpened]=true;
Print("Ordem colocada, ticket: ",trade.ResultDeal());
Print("preço: ",trade.ResultPrice()," , era pra ter sido por ",ar[i][xOP]);
trade.PrintResult();
}
else
{
Print(trade.ResultRetcodeDescription());
trade.PrintRequest();
}
}
else if(ar[i][xBuySell]=="sell")
{
_TP = tpFixo == 0 ? double(ar[i][xTP1]) : double(ar[i][xOP]) - takeProfitDelta;
_SL = slFixo == 0 ? double(ar[i][xSL]) : double(ar[i][xOP]) + stopLossDelta;
if(trade.Sell(initialVolume,ar[i][xAtv],double(ar[i][xOP]),_SL,_TP,ar[i][xCanal]))
{
ar[i][xOpened]=true;
Print("Ordem colocada, ticket: ",trade.ResultDeal());
Print("preço: ",trade.ResultPrice()," , era pra ter sido por ",ar[i][xOP]);
trade.PrintResult();
}
else
{
Print(trade.ResultRetcodeDescription());
trade.PrintRequest();
}
}
}
}
//+------------------------------------------------------------------+
//| Lucro acumulado do dia |
//+------------------------------------------------------------------+
double ProfitClosedPosition()
{
int lSize;
bool magicFound;
double profit=0;
int counter=1;
HistorySelect(inicioHedge,TimeCurrent());
int deals=HistoryDealsTotal();
int colunas = ArrayRange(profitPerMagic,1);
//---
for(int i=0;i<deals;i++)
{
ulong deal_ticket=HistoryDealGetTicket(i);
string symbol= HistoryDealGetString(deal_ticket,DEAL_SYMBOL);
double _p_profit=HistoryDealGetDouble(deal_ticket,DEAL_PROFIT);
int dealType = (int)HistoryDealGetInteger(deal_ticket,DEAL_TYPE);
int dealMagic = (int)HistoryDealGetInteger(deal_ticket,DEAL_MAGIC);
string dealComment =HistoryDealGetString(deal_ticket,DEAL_COMMENT);
if(dealType!=0 && dealType!=1) continue;
lSize = ArraySize(profitPerMagic);
magicFound=false;
if(lSize==0)ArrayResize(profitPerMagic,(lSize/colunas)+1);
for(int j=0;j<(ArraySize(profitPerMagic)/colunas);j++)
{
if(profitPerMagic[j][0]==double(dealMagic))
{
profitPerMagic[j][1]+=_p_profit;
magicFound=true;
break;
}
}
if(!magicFound)
{
ArrayResize(profitPerMagic,(lSize/colunas)+1);
for(int j=(ArraySize(profitPerMagic)/colunas)-1;j>=0;j--)
{
profitPerMagic[j][0]=dealMagic;
profitPerMagic[j][1]=profit;
break;
}
}
profit+=_p_profit;
Print(counter+": Ativo: "+symbol+" R$ "+_p_profit+" do tipo "+dealType+" , magic: "+dealMagic," / ",dealComment);
counter++;
}
for(int i=0;i<(ArraySize(profitPerMagic)/colunas);i++)
{
Print(profitPerMagic[i][0], " / " ,profitPerMagic[i][1]);
}
return(profit);
}
//+------------------------------------------------------------------+

The easiest way is to use classes, each class extends CObject and you must implement Compare function.
First, create a structure of entering (in=true) and exiting (in=false):
struct SEvent
{
datetime m_time;
double m_price;
bool m_in;
void Init(const datetime time,const double price,const bool in)
{
m_time=time;
m_price=price;
m_in=in;
}
int Compare(SEvent &another)const
{
return int(m_time-another.m_time);
}
};
Next, create the class CDeal : public CObject
class CDeal : public CObject
{
static int getDir(string cmd)
{
if(cmd=="Sell")
return(-1);
if(cmd=="Buy")
return(1);
if(cmd=="Type" || cmd=="Balance")
return(0);
printf("%i %s: unknown cmd=|%s|",__LINE__,__FILE__,cmd);
return(0);
}
static string getSymbol(string line)
{
return StringSubstr(line,0,StringLen(line)-StringLen(InpReportSuffix))+InpSymbolSuffix;
}
public:
intX m_id;
int m_dir;
SEvent m_in;
SEvent m_out;
double m_lot;
string m_symbol;
double m_osl;
double m_otp;
CDeal(string line)
{
//2019.05.13 18:27:56;Sell;0.10;EURCADm#;1.51270;;;2019.05.14 13:36:47;1.51142;;;0.10;
string array[];
const ushort separator=(ushort)';';
int size=StringSplit(line,separator,array);
if(size<11)
{
printf("%i %s: size=%d str=%s",__LINE__,__FILE__,size,line);
m_dir=0;
return;
}
m_dir=getDir(array[1]);
m_lot=StringToDouble(array[2]);
m_symbol=getSymbol(array[3]);
m_in.Init(StringToTime(array[0]),StringToDouble(array[4]),true);
m_osl=StringLen(array[5])>0 ? StringToDouble(array[5]) : 0;
m_otp=StringLen(array[6])>0 ? StringToDouble(array[6]) : 0;
m_out.Init(StringToTime(array[7]),StringToDouble(array[8]),false);
}
~CDeal(){}
virtual int Compare(const CObject *node,const int mode=0) const
{
CDeal *another=(CDeal*)node;
if(mode==1)
{
return m_in.Compare(another.m_in);
}
else
{
return m_out.Compare(another.m_out);
}
}
virtual string toString()const
{
return StringFormat("%s;%d;%.2f;%s;%.5f;%.5f;%.5f;%s;%.5f;%s",TimeToString(m_in.m_time),m_dir,m_lot,m_symbol,
m_in.m_price,m_osl,m_otp,TimeToString(m_out.m_time),m_out.m_price,m_pnl.toString());
}
};
Then, load all CDeals from string into CArrayObj and list.Sort(1) in order to sort them by time of entry. Then loop, either from some static int cursor=0; that increments if TimeCurrent()>((CDeal*) list.At(cursor)).m_in.m_time of course keeping in mind that you may reach end of your list, or detach the element if same condition is true, and attach to another CArrayObj listOfOpenDeals. Do not forget to sort the list of existing open deals each time you add an element. Same way check whether it is time to close some deal from the list of open deals, and delete element after closing.
Altogether 300 lines of code.

Related

how do i fix this code that _ insert zone, delete_zone, print_zone

For the creation of the map, the user is left with the possibility of requesting the following four functions via a menu with one (switch):
Insertion of a zone at the end of the insert_zone function list. It creates the new zone in dynamic memory malloc, inserts it in the list by modifying the value of the next_zone pointer of the last land in the list with the result of the malloc. The type of the zone as well as the object found within the zone are randomly generated: all zones are equiprobable, no_object has a 40% probability while the other objects in the enum Object_type_zone have equal probability. Finally, the enum field Tipo_prova prova will be inserted with a certain probability every time a player arrives in a given zone see function advance .
Delete the last zone inserted in the path cancel_zone
Print the fields of all the zones created up to that moment print_map.
i leaves the possibility to the user to use a menu to perform the following four functions:
insert_zone: delete_zone: print_map;
.
I leave a copy of the file.h (works well); "you can help to find the solution for the problem"
#ifndef H_GAMELIB
#define H_GAMELIB
extern void imposta_gioco();
extern void gioca();
extern void termina_gioco();
extern void inserisci_zona();
extern void stampa_mappa();
extern void chiudi_mappa();
extern void cancella_zona();
enum Tipo_Difficolta { dilettante, intermedio, incubo };
enum Tipo_oggetto_iniziale { EMF, spirit_box, videocamera, calmanti, sale };
enum Tipo_oggetto_zona { adrenalina, cento_dollari, coltello, calmanti1, nessun_oggetto };
enum Tipo_zona { caravan, cucina, soggiorno, camera, bagno, garage, seminterrato };
enum Tipo_prova { prova_EMF, prova_spirit_box, prova_videocamera, nessuna_prova };
struct Zona_mappa {
enum Tipo_zona zona;
enum Tipo_prova prova;
enum Tipo_oggetto_zona oggetto_zona;
struct Zona_mappa* prossima_zona;
};
struct Giocatore {
char nome_giocatore[30];
unsigned char sanita_mentale;
struct Zona_mappa* posizione;
unsigned char zaino[4];
};
#endif
main.c
#include "gamelib.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <time.h>
int main (void){
unsigned short numero;
int c = 0;
printf("\033[1;35m ____ ____ ____ ____ ____ ____ ____ ____ \n");
printf(" ||P |||h |||a |||l |||s |||o |||P |||h ||\n");
printf(" ||__|||__|||__|||__|||__|||__|||__|||__||\n");
printf(" |/__\\|/__\\|/__\\|/__\\|/__\\|/__\\|/__\\|/__\\|\n");
printf("\033[0m\n");
printf("||preme 'invio' per continuare||\n");
while(getchar()!= '\n');
do{
printf("\n");
printf("> \033[1;93m1\033[1m: Imposta Gioco.\n");
printf("> \033[1;96m2\033[2m: Gioca.\n");
printf("> \033[1;91m3\033[3m: Termina gioco.\n\n");
printf ("\033[92mScelta:\033[0m ");
scanf("%hu",&numero);
while ((c = getchar()) != '\n' && c != EOF); //pulizia dei buffer
switch(numero){
case 1:
printf("hai inserito il primo numero\n");
imposta_gioco();
break;
case 2:
printf("hai inserito il secondo numero\n");
gioca();break;
case 3:
printf("hai inserito il terzo numero");
termina_gioco();break;
default: printf("\033[31mAttenzione!\033[0m Opzione non valida, per favore inserisci \033[31mun numero da 1 a 3\033[0m.\n");
}
}while (numero != 3);
return 0;
}
gamelib.c
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <time.h>
#include "gamelib.h"
#define ERROR_ARGS_NUM(_min, _max) printf("\033[31mAttenzione!\033[5m Opzione non valida, per favore inserisci \033[31mun numero da " #_min " a " #_max "\033[0m.\n")
#define CHECK_NUM_INPUT_RANGE(n, _min, _max)
struct Zona_mappa *pLast = NULL;
struct Zona_mappa *pFirst = NULL;
static struct Giocatore players[4];
static int nplayers = 0;
static int difficulty_level;
int ask_num(const char *prompt)
{
if (prompt)
printf("%s", prompt);
int n;
if (scanf("%d", &n) <= 0)
n = -1;
return n;
}
void mostra_zaino(struct Giocatore *giocatore)
{
const char *nome_oggetto_iniziale;
switch (giocatore->zaino[0])
{
case EMF:
nome_oggetto_iniziale = "EMF";
break;
case spirit_box:
nome_oggetto_iniziale = "Spirit Box";
break;
case videocamera:
nome_oggetto_iniziale = "Videocamera";
break;
case calmanti:
nome_oggetto_iniziale = "Calmanti";
break;
case sale:
nome_oggetto_iniziale = "Sale";
break;
default:
return;
}
printf("Contenuto zaino di %s:\nOggetto iniziale: %s\n", giocatore->nome_giocatore, nome_oggetto_iniziale);
for (int i = 1; i < 3; i++)
{
switch (giocatore->zaino[i])
{
case cento_dollari:
printf("100$\n");
break;
case nessun_oggetto:
printf("nessun_oggetto\n");
break;
case coltello:
printf("coltello\n");
break;
case calmanti1:
printf("calmanti1\n");
break;
case adrenalina:
printf("adrenalina\n");
break;
}
}
printf("\n");
}
void imposta_gioco()
{
srand(time(NULL));
memset(players, 0, sizeof(players));
nplayers = ask_num("Inserisci il numero di giocatori (da 1 a 4): ");
CHECK_NUM_INPUT_RANGE(nplayers, 1, 4);
printf("Scegli il livello di difficoltà:\n");
printf("> \033[1;93m1\033[0m: Dilettante\n");
printf("> \033[2;93m2\033[0m: Intermedio\n");
printf("> \033[3;93m3\033[0m: Incubo\n");
difficulty_level = ask_num("\033[32mInserisci il numero corrispondente: ");
CHECK_NUM_INPUT_RANGE(difficulty_level, 1, 3);
for (int i = 0; i < nplayers; i++)
{
printf("Inserisci il nome del giocatore %d: ", (i + 1));
if (scanf("%s", players[i].nome_giocatore) <= 0)
return;
players[i].sanita_mentale = 100;
players[i].zaino[0] = rand() % 5;
for (int j = 1; j < 4; j++)
players[i].zaino[j] = nessun_oggetto;
mostra_zaino(&players[i]);
}
}
struct Zona_mappa *genera_mappa()
{
// Crea la prima zona mappa
struct Zona_mappa *prima_zona = malloc(sizeof(struct Zona_mappa));
prima_zona->zona = cucina;
// Crea la seconda zona mappa
struct Zona_mappa *seconda_zona = malloc(sizeof(struct Zona_mappa));
seconda_zona->zona = soggiorno;
prima_zona->prossima_zona = seconda_zona;
// Crea la terza zona
struct Zona_mappa *terza_zona = malloc(sizeof(struct Zona_mappa));
terza_zona->zona = garage;
seconda_zona->prossima_zona = terza_zona;
struct Zona_mappa *quarta_zona = malloc(sizeof(struct Zona_mappa));
quarta_zona->zona = camera;
terza_zona->prossima_zona = quarta_zona;
// Crea la terza zona
struct Zona_mappa *quinta_zona = malloc(sizeof(struct Zona_mappa));
quinta_zona->zona = bagno;
quarta_zona->prossima_zona = quinta_zona;
struct Zona_mappa *ultima_zona = malloc(sizeof(struct Zona_mappa));
ultima_zona->zona = seminterrato;
quinta_zona->prossima_zona = ultima_zona;
ultima_zona->prossima_zona = prima_zona;
// Assegna i valori ai puntatori globali
pFirst = prima_zona;
pLast = ultima_zona;
printf("la lista è pronta\n");
return prima_zona; // Restituisce l'indirizzo della prima zona
}
void inserisci_zona()
{
struct Zona_mappa *nuova_zona = malloc(sizeof(struct Zona_mappa));
if (nuova_zona == NULL)
{
fprintf(stderr, "ERRORE di allocazione di memoria per la nuova zona\n");
return;
}
nuova_zona->zona = rand() % 4;
int r = rand() % 100;
if (r < 80)
{
nuova_zona->zona = cucina;
}
else if (r < 60)
{
nuova_zona->zona = bagno;
}
else if (r < 50)
{
nuova_zona->zona = garage;
}
else if (r < 40)
{
nuova_zona->zona = seminterrato;
}
else if (r < 30)
{
nuova_zona->zona = camera;
}
else
{
nuova_zona->zona = soggiorno;
}
r = rand() % 100;
if (r < 40)
{
nuova_zona->oggetto_zona = nessun_oggetto;
}
else if (r < 60)
{
nuova_zona->oggetto_zona = calmanti1;
}
else if (r < 70)
{
nuova_zona->oggetto_zona = coltello;
}
else if (r < 90)
{
nuova_zona->oggetto_zona = cento_dollari;
}
else
{
nuova_zona->oggetto_zona = adrenalina;
}
// Insert the new zone at the end of the list
if (pFirst == NULL)
{// If the list is empty, set First and Last as the new zone
pFirst = nuova_zona;
pLast = nuova_zona;
pLast->prossima_zona = pFirst;
}
else
{
pLast->prossima_zona = nuova_zona;
pLast = nuova_zona;
pLast->prossima_zona = pFirst;
}
}
void cancella_zona()
{
// Special case: the list is empty
if (pFirst == NULL)
{
return;
}
// Special case: the list contains a single zone
if (pFirst == pLast)
{
free(pFirst);
pFirst = NULL;
pLast = NULL;
return;
}
// Otherwise, find the last zone in the list and delete it
struct Zona_mappa *p = pFirst;
while (p->prossima_zona != pLast)
{
p = p->prossima_zona;
}
free(pLast);
pLast = p;
pLast->prossima_zona = pFirst;
}
void stampa_mappa()
{
// Caso particolare: la lista è vuota
if (pFirst == NULL)
{
printf("La mappa è vuota\n");
return;
}
printf("Stampa della mappa:\n");
struct Zona_mappa *p = pFirst;
do
{
printf(" - Zona di tipo %d, con oggetto %d\n", p->zona, p->oggetto_zona);
p = p->prossima_zona;
} while (p != pFirst);
}
void chiudi_mappa()
{
gioco_impostato = 1;
}
// Funzione che avvia il gioco
void gioca()
{
{
}
}
// Funzione che termina il gioco
void termina_gioco()
{
}
I have problems in the following 3 blocks of code
void inserisci_zona()
{
struct Zona_mappa *nuova_zona = malloc(sizeof(struct Zona_mappa));
if (nuova_zona == NULL)
{
fprintf(stderr, "ERRORE di allocazione di memoria per la nuova zona\n");
return;
}
nuova_zona->zona = rand() % 4;
int r = rand() % 100;
if (r < 80)
{
nuova_zona->zona = cucina;
}
else if (r < 60)
{
nuova_zona->zona = bagno;
}
else if (r < 50)
{
nuova_zona->zona = garage;
}
else if (r < 40)
{
nuova_zona->zona = seminterrato;
}
else if (r < 30)
{
nuova_zona->zona = camera;
}
else
{
nuova_zona->zona = soggiorno;
}
r = rand() % 100;
if (r < 40)
{
nuova_zona->oggetto_zona = nessun_oggetto;
}
else if (r < 60)
{
nuova_zona->oggetto_zona = calmanti1;
}
else if (r < 70)
{
nuova_zona->oggetto_zona = coltello;
}
else if (r < 90)
{
nuova_zona->oggetto_zona = cento_dollari;
}
else
{
nuova_zona->oggetto_zona = adrenalina;
}
// Insert the new zone at the end of the list
if (pFirst == NULL)
{// If the list is empty, set First and Last as the new zone
pFirst = nuova_zona;
pLast = nuova_zona;
pLast->prossima_zona = pFirst;
}
else
{
pLast->prossima_zona = nuova_zona;
pLast = nuova_zona;
pLast->prossima_zona = pFirst;
}
}
void cancella_zona()
{
// Special case: the list is empty
if (pFirst == NULL)
{
return;
}
// Special case: the list contains a single zone
if (pFirst == pLast)
{
free(pFirst);
pFirst = NULL;
pLast = NULL;
return;
}
// Otherwise, find the last zone in the list and delete it
struct Zona_mappa *p = pFirst;
while (p->prossima_zona != pLast)
{
p = p->prossima_zona;
}
free(pLast);
pLast = p;
pLast->prossima_zona = pFirst;
}
void stampa_mappa()
{
// Caso particolare: la lista è vuota
if (pFirst == NULL)
{
printf("La mappa è vuota\n");
return;
}
printf("Stampa della mappa:\n");
struct Zona_mappa *p = pFirst;
do
{
printf(" - Zona di tipo %d, con oggetto %d\n", p->zona, p->oggetto_zona);
p = p->prossima_zona;
} while (p != pFirst);
}
Here's the fixed code. Required modifications to fix the code are marked and explained with comments at the end of the lines starting with "// Edit:". It is a single file where I inserted the header file. At the end is a small main() to test the code.
#include <stdlib.h>
#include <stdio.h>
#ifndef H_GAMELIB
#define H_GAMELIB
void imposta_gioco (void);
void gioca (void);
void termina_gioco (void);
void inserisci_zona(void);
void stampa_mappa (void);
void chiudi_mappa (void);
void cancella_zona (void);
enum Tipo_Difficolta { dilettante, intermedio, incubo };
enum Tipo_oggetto_iniziale { EMF, spirit_box, videocamera, calmanti, sale };
enum Tipo_oggetto_zona { adrenalina, cento_dollari, coltello, calmanti1, nessun_oggetto };
enum Tipo_zona { caravan, cucina, soggiorno, camera, bagno, garage, seminterrato };
enum Tipo_prova { prova_EMF, prova_spirit_box, prova_videocamera, nessuna_prova };
struct Zona_mappa {
enum Tipo_zona zona;
enum Tipo_prova prova;
enum Tipo_oggetto_zona oggetto_zona;
struct Zona_mappa* prossima_zona;
};
struct Giocatore {
char nome_giocatore[30];
unsigned char sanita_mentale;
struct Zona_mappa* posizione;
unsigned char zaino[4];
};
#endif
static struct Zona_mappa* pFirst = NULL; // Edit: Added since pFirst was missing
static struct Zona_mappa* pLast = NULL; // Edit: Added since pLast was missing
void inserisci_zona(void) {
struct Zona_mappa* nuova_zona = malloc(sizeof(struct Zona_mappa));
if (nuova_zona == NULL)
{
fprintf(stderr, "ERROR of memory allocation for the new zone\n");
return;
}
nuova_zona->zona = rand() % 7; // Edit: enum has 7 enumerators
// Edit: Since zones are equiprobable, above line is sufficient
/*
int r = rand() % 100;
if (r < 80)
{
nuova_zona->zona = cucina;
}
else if (r < 60)
{
nuova_zona->zona = bagno;
}
else if (r < 50)
{
nuova_zona->zona = garage;
}
else if (r < 40)
{
nuova_zona->zona = seminterrato;
}
else if (r < 30)
{
nuova_zona->zona = camera;
}
else
{
nuova_zona->zona = soggiorno;
}
*/
int r = rand() % 100;
if (r < 40)
{
nuova_zona->oggetto_zona = nessun_oggetto;
}
else if (r < 55) // Edit: No object has 40% and all others 15%
{
nuova_zona->oggetto_zona = calmanti1;
}
else if (r < 70)
{
nuova_zona->oggetto_zona = coltello;
}
else if (r < 85) // Edit: No object has 40% and all others 15%
{
nuova_zona->oggetto_zona = cento_dollari;
}
else
{
nuova_zona->oggetto_zona = adrenalina;
}
// Insert the new zone at the end of the list
if (pFirst == NULL)
{
// If the list is empty, set First and Last as the new zone
pFirst = nuova_zona;
pLast = nuova_zona;
pLast->prossima_zona = NULL; // Edit: Next of last one has to be NULL
}
else
{
pLast->prossima_zona = nuova_zona;
pLast = nuova_zona;
pLast->prossima_zona = NULL; // Edit: Next of last one has to be NULL
}
}
void cancella_zona(void) {
// Special case: the list is empty
if (pFirst == NULL)
{
return;
}
// Special case: the list contains a single zone
if (pFirst == pLast)
{
free(pFirst);
pFirst = NULL;
pLast = NULL;
return;
}
// Otherwise, find the second to last zone in the list
struct Zona_mappa *p = pFirst;
while (p->prossima_zona != pLast)
{
p = p->prossima_zona;
}
free(pLast);
pLast = p;
pLast->prossima_zona = NULL; // Edit: Next of last zone has to be NULL
}
void stampa_mappa(void) {
// Special case: the list is empty
if (pFirst == NULL)
{
printf("The map is empty\n");
return;
}
printf("Map printing:\n");
struct Zona_mappa *p = pFirst;
do
{
printf(" - Zone of type %d, with object %d\n", p->zona, p->oggetto_zona);
p = p->prossima_zona;
} while (p != NULL); // Edit: Iterate until there's no next Zona_mappa which is the case if next is NULL
}
int main(void) {
stampa_mappa();
inserisci_zona();
inserisci_zona();
inserisci_zona();
stampa_mappa();
cancella_zona();
stampa_mappa();
cancella_zona();
cancella_zona();
stampa_mappa();
for (;;);
return 0;
}

How to store strings in a 2D array in C?

I want to store strings in a char * array but I don't know how I can do that.
Each cell in the 2d array can contain letters or numbers with 2 digits.
|_|S|_|
|_|10|_|
|_|W|_|
|_|_|_|
|_|_|_|
I tried this, I used struct:
struct Etage {
char Idsalles[20];
int** etage;
int width;
int height;
};
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include "etage.h"
#define COLS 15
#define ROWS 9
Etage *createMap()
{
Etage *e = malloc(sizeof(Etage));
e->width = COLS; // columns
e->height = ROWS; // rows
e->etage = malloc(sizeof(char *) * e->height);
for (int i = 0; i < e->height; i += 1)
{
e->etage[i] = malloc(sizeof(char) * e->width);
for (int j = 0; j < e->width; j += 1)
{
e->etage[i][j] = "0";
}
}
return e;
}
void randomId(Etage *e, int maxSalles)
{
srand(time(NULL));
int i = 0;
if (maxSalles < 10)
{
printf("Seulement %d disponibles, veuiller générer plus de salles.\n", maxSalles);
return;
}
while (i < 10)
{
int id = (rand() % maxSalles) + 1;
int existe = testId(e, id);
if (existe != 1)
{
e->Idsalles[i] = id;
i += 1;
}
}
return;
}
int testId(Etage *e, int id)
{
for (int i = 0; i < 10; i += 1)
{
if (id == e->Idsalles[i])
{
return 1;
}
}
return 0;
}
void printEtage(Etage *e)
{
for (int i = 0; i < e->height; i += 1)
{
for (int j = 0; j < e->width; j += 1)
{
if(e->etage[i][j] == 0){
printf(" ");
}else{
printf("%s", e->etage[i][j]);
printf(" ");
}
}
printf("\n");
}
printf("Id des salles de cette étage: ");
for(int i =0; i <10;i+=1){
printf("%d ",e->Idsalles[i]);
}
printf("\n");
}
void freeEtage(Etage *e)
{
//free(e->etage);
free(e);
}
void placerSalles(Etage* e){
int a=ROWS/2;
int b=COLS/2;
//0 = Haut; 1 = Droite; 2 = Bas; 3 = Gauche
e->etage[a][b] = e->Idsalles[0]+"\0"; // On place la premiere salle au centre de l'étage sa sera le spawner 'S'
srand(time(NULL));
int i = 1;
while(i<10){
int dir = randomDirections();
if(dir==0){ // On se déplace en haut
a = a-1; //On se déplace
if(e->etage[a][b] == 0 && a > 0){
e->etage[a][b] = e->Idsalles[i]+"\0";
i+=1;
}else{
a = a+1; // Sionon on revien a la derniere case connu
}
}else if(dir==1){ // On se déplace à droite
b=b+1;
if(e->etage[a][b] == 0 && b< e->width){
e->etage[a][b] = e->Idsalles[i]+"\0";
i+=1;
}else{
b = b-1;
}
}else if(dir==2){ // On se déplace en bas
a = a+1;
if(e->etage[a][b] == 0 && a>e->height){
e->etage[a][b] = e->Idsalles[i]+"\0";
i+=1;
}else{
a = a-1;
}
}else if(dir==3){ // On se déplace à gauche
b = b-1;
if(e->etage[a][b] == 0 && b>0){
e->etage[a][b] = e->Idsalles[i]+"\0";
i+=1;
}else{
b = b+1;
}
}
}
}
int randomDirections(){
int i = 0;
int id = rand() % 4; // Remplacé 10 par le nbrSalles
//printf("Position: %d\n",id);
return id;
}
I have a good understanding with 2d array but three...
I tried using malloc.
I don't even think this is possible...
If your string is a maximum of 2 characters long (your strings will be 3 chars long)
char array[rows][cols][3] = {{"2", "a", "34"}, ... };
or to use malloc
char (*array)[cols][3] = malloc(rows * sizeof(*array));

Tic Tac Toe Minimax not working in certain placement

It would give me a board that looks like
==============
| X | 1 | O |
-------------
| 3 | X | 5 |
-------------
| O | 7 | 8 |
==============
The issue i think is that the first move is not in the middle which will cause the AI to lose.
#include <stdio.h>
#include <stdbool.h>
#define X 'X'
#define O 'O'
#define T 'T'
struct Move
{
int row;
int column;
};
void generateBoard(char board[3][3]);
bool canMakeMove(char board[3][3], struct Move move);
bool makeMove(char board[3][3], struct Move move, char moveSymbol);
void copyBoard(char originalBoard[3][3], char duplicateBoard[3][3]);
int minimax(char board[3][3], int depth, bool isMaximizing);
char generatePlayerChar(int player);
char checkWinner(char board[3][3]);
bool hasAvailableSpot(char board[3][3]);
void generateBoard(char board[3][3])
{
printf("\n"
"==============\n"
"| %c | %c | %c |\n"
"-------------\n"
"| %c | %c | %c |\n"
"-------------\n"
"| %c | %c | %c |\n"
"==============\n",
board[0][0], board[0][1], board[0][2],
board[1][0], board[1][1], board[1][2],
board[2][0], board[2][1], board[2][2]);
}
char generatePlayerChar(int player)
{
return ((player == 1) ? 'X' : 'O');
}
/// #brief Given a board, check if there's any available spot available to use
/// #param board
/// #return
bool hasAvailableSpot(char board[3][3])
{
int count = 0;
for (int rows = 0; rows < 3; rows++)
{
for (int cols = 0; cols < 3; cols++)
{
struct Move attemptedMove = {rows, cols};
if (canMakeMove(board, attemptedMove))
{
count++;
}
}
}
if (count > 0)
{
return true;
}
return false;
}
/// #brief Check for both vertical/horizontal/diagonal winner
/// #param board
/// #return Return 'X'/'O'/'T'/-1 depending on who won the game/tie
char checkWinner(char board[3][3])
{
for (int i = 0; i < 3; i++)
{
// Check horizontal winning condition
if ((board[i][0] == board[i][1]) && (board[i][1] == board[i][2]))
{
return board[i][0];
}
// Check vertical winning condition
if ((board[0][i] == board[1][i]) && (board[1][i] == board[2][i]))
{
return board[0][i];
}
}
// Check for diagonal winning condition
if ((board[0][0] == board[1][1]) && (board[1][1] == board[2][2]))
{
return board[0][0];
}
else if ((board[0][2] == board[1][1]) && (board[1][1] == board[2][0]))
{
return board[0][2];
}
// There's no winner so we check if there's any empty space left yet.
if (!hasAvailableSpot(board))
{
return 'T';
}
return -1;
}
/// #brief Place the character on the board
/// #param board
/// #param move
/// #param moveSymbol
/// #return Return true depending on whether it successfully modified the board
bool makeMove(char board[3][3], struct Move move, char moveSymbol)
{
if (canMakeMove(board, move))
{
board[move.row][move.column] = moveSymbol;
return true;
}
return false;
}
/// #brief Takes in a board and does out of bound checking as well as check on available spots on the board
/// #param board The board to check
/// #param move A single structure consisting of row,column
/// #return A boolean true/false whether you can place a move on a specific area on the board
bool canMakeMove(char board[3][3], struct Move move)
{
if ((move.row > 3) || (move.column > 3))
{
return false;
}
if ((board[move.row][move.column] != X) && (board[move.row][move.column] != O))
{
return true;
}
return false;
}
/// #brief Calls each available spot on the board and determine using minimax which is the next bestMove supposed to be
/// #param board Given a board, what's the best next move to do next
/// #return A structure which contains the best determined move to do next
struct Move getBestMove(char board[3][3])
{
int bestScore = -1000;
struct Move bestMove;
for (int rows = 0; rows < 3; rows++)
{
for (int cols = 0; cols < 3; cols++)
{
struct Move attemptedMove = {rows, cols};
if (canMakeMove(board, attemptedMove))
{
char duplicatedBoard[3][3];
copyBoard(board, duplicatedBoard);
// Attempt to put in the next possible move.
makeMove(duplicatedBoard, attemptedMove, X);
int tempScore = minimax(duplicatedBoard, 0, false);
if (tempScore > bestScore)
{
bestScore = tempScore;
bestMove = attemptedMove;
}
}
}
}
return bestMove;
}
// TODO: Include alpha beta pruning
/// #brief The code looks 90% similar to getBestMove. However, one thing that differentiates them is it goes recursively into every single board for possibility.
/// #param board
/// #param depth How deep has the recursion gone
/// #param isMaximizing Checks which player turn. AI is usually maximizing. Player is usually minimizing.
/// #return The
int minimax(char board[3][3], int depth, bool isMaximizing)
{
// Remember that if we do not calculate how to get the results somewhere in this function,
// Return bestScore would be unable to run as there is no one returning a value.
char winResult = checkWinner(board);
if (winResult == X)
{
return (10 - depth);
}
else if (winResult == O)
{
return (-10 + depth);
}
else if (winResult == T)
{
return 0;
}
if (isMaximizing)
{
int bestScore = -1000;
for (int rows = 0; rows < 3; rows++)
{
for (int cols = 0; cols < 3; cols++)
{
struct Move attemptedMove = {rows, cols};
if (canMakeMove(board, attemptedMove)) // Check for available spot in the board.
{
char duplicateBoard[3][3];
copyBoard(board, duplicateBoard);
makeMove(duplicateBoard, attemptedMove, X);
// As long as the game doesn't end recursively call it till we get an end state.
int score = minimax(duplicateBoard, depth++, false);
if (bestScore < score)
{
bestScore = score;
}
}
}
}
return bestScore;
}
else
{
int bestScore = 1000;
for (int rows = 0; rows < 3; rows++)
{
for (int cols = 0; cols < 3; cols++)
{
struct Move attemptedMove = {rows, cols};
if (canMakeMove(board, attemptedMove))
{
char duplicateBoard[3][3];
copyBoard(board, duplicateBoard);
makeMove(duplicateBoard, attemptedMove, O);
// As long as the game doesn't end recursively call it till we get an end state.
int score = minimax(duplicateBoard, depth++, true);
if (bestScore > score)
{
bestScore = score;
}
}
}
}
return bestScore;
}
}
/// #brief Duplicates a board from originalBoard to duplicateBoard which creates a exact value but different array pointer
/// #param originalBoard
/// #param duplicateBoard
void copyBoard(char originalBoard[3][3], char duplicateBoard[3][3])
{
for (int rows = 0; rows < 3; rows++)
{
for (int cols = 0; cols < 3; cols++)
{
duplicateBoard[rows][cols] = originalBoard[rows][cols];
}
}
}
void MultiplayerMode()
{
char board[3][3] = {
{'0', '1', '2'},
{'3', '4', '5'},
{'6', '7', '8'},
};
bool gameInProgress = true;
int player = 0;
while (gameInProgress)
{
char playerChar = generatePlayerChar(player);
generateBoard(board);
printf("\nCurrently player %c turn.", playerChar);
printf("\nPlease enter your desired move: ");
struct Move desiredMove;
scanf(" [%d][%d]", &desiredMove.row, &desiredMove.column);
while (!canMakeMove(board, desiredMove))
{
printf("\nInvalid Move detected.");
printf("\nPlease re-enter your desired move: ");
scanf(" [%d][%d]", &desiredMove.row, &desiredMove.column);
}
makeMove(board, desiredMove, playerChar);
int result = checkWinner(board);
if (result == X)
{
printf("\nPlayer %c has won the game!", X);
gameInProgress = false;
}
else if (result == O)
{
printf("\nPlayer %c has won the game!", O);
gameInProgress = false;
}
else if (result == T)
{
printf("\nGame has resulted in a tie!");
gameInProgress = false;
}
player = !player;
}
}
void BotsMode()
{
char board[3][3] = {
{'0', '1', '2'},
{'3', '4', '5'},
{'6', '7', '8'},
};
bool gameInProgress = true;
int player = 0;
while (gameInProgress)
{
char playerChar = generatePlayerChar(player);
printf("\nCurrently player %c turn", playerChar);
if (player == 0)
{
struct Move desiredMove;
do
{
generateBoard(board);
printf("\nPlease enter your desired move: ");
scanf(" [%d][%d]", &desiredMove.row, &desiredMove.column);
} while (!canMakeMove(board, desiredMove));
makeMove(board, desiredMove, playerChar);
}
else
{
// This belongs to the AI.
struct Move bestMove = getBestMove(board);
printf("\nBest move determined is [%d][%d]", bestMove.row, bestMove.column);
makeMove(board, bestMove, playerChar);
}
int result = checkWinner(board);
if (result == X)
{
printf("\nPlayer %c has won the game!", X);
gameInProgress = false;
}
else if (result == O)
{
printf("\nPlayer %c has won the game!", O);
gameInProgress = false;
}
else if (result == T)
{
printf("\nGame has resulted in a tie!");
gameInProgress = false;
}
// Invert the player
player = !player;
}
}
int main(void)
{
int gameSelection;
do
{
printf("\nTic Tac Toe - Main Menu");
printf("\n1. Multiplayer Mode");
printf("\n2. Bots Mode");
printf("\nPlease enter your selection: ");
scanf("%d", &gameSelection);
} while (gameSelection != 1 && gameSelection != 2);
switch (gameSelection)
{
case 1:
MultiplayerMode();
break;
case 2:
BotsMode();
break;
}
return 0;
}
Hi there, I've tried and it seems to be working in certain combinations.
To use a move, i make use of [rows][cols]
So for the cases below, it doesn't seem to be working
Instruction 1: [0][2]
Instruction 2: [2][0]

RPi 4 GPIO Interrupt on Rising and Falling trigger not working in C

Beginner here learning to code linux kernel modules.
I want to write a kernel module for my RPi 4 in C language.
I want to use interrupts to light on a LED when I push a button. As long as the button is pushed, the LED is on and when I release it, the LED is supposed to turn off.
I use the function request_irq() so that my function handling the interrupt is called on the rising edge and on the falling edge of my button by indicating "IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING". I formerly used the function gpio_to_irq(BUTTON_PIN).
request_irq(button_irq, button_ih, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "button_irq", NULL);
The function is called when I push the button but not when I release it. It is coded as seen below :
static irqreturn_t button_ih(int irq, void *data)
{
int state;
state = gpio_get_value(BUTTON_PIN);
printk(KERN_INFO "Actual state of the button : %d", state);
//Debounce condition
if(jiffies - last_interrupt_time > msecs_to_jiffies(200))
{
if(state)
{
gpio_set_value(LED_PIN, 1);
}else
{
gpio_set_value(LED_PIN, 0);
}
}
last_interrupt_time = jiffies;
return IRQ_HANDLED;
}
I check whether the value of the button is 1 (pressed) or 0 (released) and want to turn on/off the LED accordingly.
When I try different GPIOs, sometimes, the value of my button is 1 even though I haven't pushed it yet(by printing a message from the init function) and sometimes it's 0. So I don't understand if I'm doing something wrong. I don't think the GPIOs are already used cause I can request them with the function gpio_request_one().
So when the button already has the value 1, the LED turn on but won't switch off when I release the button.
And when the value is already 0, the button value doesn't change to become 1 when I enter the interrupt handler function (and the LED obviously doesn't turn on).
Could you tell me what's wrong with it please?
Form simple C program, not kernel module
This minimal to see how I'm doing.
main.h
typedef struct s_Data {
int exitFlag;
struct {int value; int bcmPin;} In01; //<--- Stock actual GPIO Value
struct {int value; int bcmPin;} In02;
....
struct {int value; int bcmPin;} Out01;
struct {int value; int bcmPin;} Out02;
....
} t_Data;
#define NO_Click 0
#define SimpleClick 1
#define LongClick 2
#define MultiClick 3
typedef struct s_Button {
pthread_t button_thread;
int *exitFlag;
int * input; //Button
int * output;
int old_state;
int new_state;
struct timeval t0;
struct timeval t1;
struct timeval pressedTime;
struct timeval releasedTime;
int clickType;
//float debounce = 0.020; // ms debounce period to prevent flickering when pressing or releasing the button
// debounce not necessary while thread have time to take a coffee
float DCgap; // max ms between clicks for a double click event
float holdTime; // ms hold period: how long to wait for press+hold event
} t_Button;
main.c
#include "main.h"
#include <wiringPi.h>
#include <pthread.h>
// initial state
static t_Data data = {
.exitFlag = 0,
.In01.value = 0, .In01.bcmPin = 4,
.In02.value = 0, .In02.bcmPin = 17,
.Out01.value = 0, .Out01.bcmPin = 4,
.Out02.value = 0, .Out02.bcmPin = 17,
}
static _Data data_prev;
static void *inputRead_threadFn(void *p_Data) {
pinMode(Data.In01.bcmPin, INPUT);
pullUpDnControl(Data.In01.bcmPin, PUD_UP);
pinMode(Data.In02.bcmPin, INPUT);
pullUpDnControl(Data.In02.bcmPin, PUD_UP);
while (!Data.exitFlag) {
Data.In01.value = !digitalRead(Data.In01.bcmPin);
Data.In02.value = !digitalRead(Data.In02.bcmPin);
if (Data.In01.value != Data_old.In01.value) {
Data_old.In01.value = Data.In01.value;
}
if (Data.In02.value != Data_old.In02.value) {
Data_old.In02.value = Data.In02.value;
}
usleep(50)
}
}
static void *outputWrite_threadFn(void *p_Data) {
pinMode(Data.In01.bcmPin, OUTPUT);
pinMode(Data.In02.bcmPin, OUTPUT);
while (!Data.exitFlag) {
digitalWrite(Data.Out01.bcmPin, !Data.Out01.value);
digitalWrite(Data.Out02.bcmPin, !Data.Out02.value);
}
usleep(50)
}
static void *button_threadFn(void *p_Data) {
t_Button *button = (t_Button *)p_data;
LOG("Button[%s] thread initialized\r\n", button->name);
button->old_state = 0;
button->new_state = 0;
button->clickType = NO_Click;
int clickCount = 0;
while(*(button->exitFlag) == 0) {
button->new_state = *(button->input) || *(button->web_input); //*((int *)
if( button->old_state == 0 && button->new_state == 1 ) {
//printf("front montant\r\n"); fflush(stdout);
// *****************************
// traitement sur front montant
// rising edge
// *****************************
button->old_state = 1;
gettimeofday(&button->pressedTime, 0);
//Button pressed
} else if( (button->old_state == 1) && (button->new_state == 0) ) {
//printf("front descendant\r\n"); fflush(stdout);
// *****************************
// traitement sur front descendant
// falling edge
// *****************************
button->old_state = 0;
gettimeofday(&button->releasedTime, 0);
if (my_timedifference_msec(button->releasedTime, button->pressedTime ) < button->DCgap) {
clickCount++;
button->clickType = MultiClick;
}
//Button released
} else if( (button->old_state == 0) && (button->new_state == 0) ) {
// printf("front bas\r\n"); fflush(stdout);
// *****************************
// pas de changement d'état : front bas
// no state change : edge down
// *****************************
gettimeofday(&button->t0, 0);
*(button->output) = 0; //<--- here in your case
//Attendre DC_Gap pour connaitre le nombre de click
// Wait for DC_Gap to know click count
if (my_timedifference_msec(button->t0, button->releasedTime) > button->DCgap) {
if (clickCount == 1) {
LOG("SimpleClick");
//Simple Click
} else if ( clickCount > 1 ) {
//Multiclicks
}
button->clickType = NO_Click;
clickCount = 0;
}
} else if( (button->old_state == 1) && (button->new_state == 1) ) {
// printf("front haut\r\n"); fflush(stdout);
// *****************************
// pas de changement d'état : front haut
// no state change : edge up
// *****************************
gettimeofday(&button->t1, 0);
*(button->output) = 1; //<--- here in your case
//long click
if (my_timedifference_msec(button->t1, button->pressedTime) >= button->holdTime) {
LOG("LongClick");
button->clickType = LongClick;
//do what you want while not released
usleep(30*1000);
}
}
usleep(100);
}
printf("Light Loop::exiting...\r\n"); fflush(stdout);
}
int main(int argc, char** argv) {
wiringPiSetup();
wiringPiSetupGpio();
data_prev = data;
//start input thread
//start output thread
int DCGap = 250; //ms
int HoldTime = 600;
t_Button Buttons[] = {
{ //WC
.exitFlag = &Data.exitFlag,
.DCgap = DCGap,
.holdTime = HoldTime,
.input = &Data.In01.value,
.output = &Data.Out01.value,
},
{ //chambre
.exitFlag = &Data.exitFlag,
.DCgap = DCGap,
.holdTime = HoldTime,
.input = &Data.In02.value,
.output= &Data.Out02.value,
}
}
//start buttons threads
for (i = 0; i < (sizeof(Buttons) / sizeof(t_Button)) ; i++) {
ret = pthread_create (&Buttons[i].button_threadFn, NULL, fn_Button, &Buttons[i]);
if (ret) {
fprintf (stderr, "%s", strerror (ret));
}
}
//threads join
return (EXIT_SUCCESS);
}
Ok so thanks for all the comments/answers.
It was indeed because I wasn't using any pull-up or pull-down resistor properly.
So I changed my circuit as following:
Circuit

multiple definition of "" language C and graphics.h

iam trying write some code with language and graphics.h for scale
to draw line chart but :
and i get this :
multiple definition of InitGraphics(char*)' first defined here
multiple definition ofxGraphics2Screen(double)'
... ld returned 1 exit status
i dont know what happen ?
can you help and thanks
Code :
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include "tri.h"
#include<time.h>
#include<graphics.h>
typedef struct {
int key;
unsigned long value;
}Map;
static double s_xGraphicsMin;
static double s_yGraphicsMin;
static double s_xGraphicsMax;
static double s_yGraphicsMax;
static int s_xScreenMax, s_yScreenMax;
int InitGraphics( char * pszBgiPath )
{
int gdriver = DETECT, gmode, errorcode;
// Recherche le meilleur mode possible
initgraph(&gdriver, &gmode, pszBgiPath);
// Verifie que ca marche
errorcode = graphresult();
if (errorcode != grOk)
{
// Probleme !
return -1;
}
// Recupere la taille de l'ecran en pixels
// Sauvegarde dans des globales
s_xScreenMax = getmaxx();
s_yScreenMax = getmaxy();
return 0;
}
int yGraphics2Screen( double yGraphic )
{
int yScreen;
yScreen = (int)(s_yScreenMax -
s_yScreenMax *
(double)(yGraphic - s_yGraphicsMin) /
(double)(s_yGraphicsMax - s_yGraphicsMin));
return yScreen;
}
int xGraphics2Screen( double xGraphic )
{
int xScreen;
xScreen = (int)(s_xScreenMax *
(double)(xGraphic - s_xGraphicsMin) /
(double)(s_xGraphicsMax - s_xGraphicsMin));
return xScreen;
}
void DrawGraphicsAxys( int color, double xPas, double yPas,char * pszxTitle, char * pszyTitle )
{
int xScreenCenter, yScreenCenter;
double x,y;
char sz[25];
// Couleur
setcolor(color);
// Dessine l'axe des X
yScreenCenter = yGraphics2Screen(0);
line( 0, yScreenCenter, s_xScreenMax, yScreenCenter );
// Dessine l'echelle des X au pas xPas
for( x = s_xGraphicsMin; x < s_xGraphicsMax; x += xPas )
{
double xArrondi;
int xScreen;
// On dessine
xArrondi = x - fmod(x,xPas);
if( xArrondi != 0 )
{
xScreen = xGraphics2Screen(xArrondi);
line( xScreen, yScreenCenter - 2,
xScreen, yScreenCenter + 2 );
sprintf( sz, "%5.2f", xArrondi );
outtextxy(xScreen - 5, yScreenCenter + 6, sz );
}
}
// Dessine l'axe des Y
xScreenCenter = xGraphics2Screen(0);
line( xScreenCenter, 0, xScreenCenter, s_yScreenMax );
// Titre en X
if( pszxTitle )
outtextxy(s_xScreenMax - s_xScreenMax/3, yScreenCenter + 20, pszxTitle );
// Dessine l'echelle des Y au pas yPas
for( y = s_yGraphicsMin; y < s_yGraphicsMax; y += yPas )
{
double yArrondi;
int yScreen;
// On dessine
yArrondi = y - fmod(y,yPas);
if( yArrondi != 0 )
{
yScreen = yGraphics2Screen(yArrondi);
line( xScreenCenter - 2, yScreen,
xScreenCenter + 2, yScreen );
sprintf( sz, "%5.2f", yArrondi );
outtextxy(xScreenCenter + 6, yScreen, sz );
}
}
// Titre en Y
if( pszyTitle )
outtextxy( xScreenCenter + 15, 10, pszyTitle );
}
int main()
{
system("pause");
return 0;
}
int InitGraphics( char * pszBgiPath )
Remame the function as it is already in graphics.h
graphics.h contains already a function called InitGraphics(). You need to change name of your function.

Resources