OOP, plantillas y macros en mql5, sutilezas y usos - página 28

 
Maxim Kuznetsov:

Recuerdo que en SQLite, los tipos de campo son opcionales y no hay que preocuparse de especificar y castear tipos. Es "Lite" por una razón.

puedes dividir una consulta larga en 3-4-5 consultas :-)

BEGIN TRANSACTION

INSERT INTO myTable VALUES (...); --- тут можно получить PrimaryKey

UPDATE myTable .... ; --- обновить по Primary

UPDATE myTable ...  ; --- ещё...

COMMIT ; --- это если все запросы удачны.. иначе ROLLBACK

es de la memoria antigua, por lo que debe comprobar en la ayuda

me gustaria tener un codigo de consulta reproducible, me tomara mucho tiempo buscar en google, he trabajado con una base de datos ocasionalmente - tengo un problema, lo he buscado en google, lo he resuelto - pero me gustaria ver una consulta de base de datos fallida

 
Vladimir Simakov:

Su problema particular debería resolverse así:

string MakeRequest(string md5txt){
   static ENUM_STATISTICS intIndex[]={STAT_CONPROFITMAX_TRADES,
                                      STAT_MAX_CONPROFIT_TRADES,
                                      STAT_CONLOSSMAX_TRADES,
                                      STAT_MAX_CONLOSS_TRADES,
                                      STAT_DEALS,
                                      STAT_TRADES,
                                      STAT_PROFIT_TRADES,
                                      STAT_LOSS_TRADES,
                                      STAT_SHORT_TRADES,
                                      STAT_LONG_TRADES,
                                      STAT_PROFIT_SHORTTRADES,
                                      STAT_PROFIT_LONGTRADES,
                                      STAT_PROFITTRADES_AVGCON,
                                      STAT_LOSSTRADES_AVGCON};
   string ret="INSERT INTO \"TesterStatistics\" + StringFormat(" set md5= %d ,md5txt),
   for (int i=0,ii=0;i<=STAT_LOSSTRADES_AVGCON;++i){
      ret+=",";
      if (i==intIndex[ii]){
         ret+=StringFormat("%s = %d,",EnumToString((ENUM_STATISTICS)i),(int)TesterStatistics((ENUM_STATISTICS)i) ));
         ++ii;}
      else ret+=StringFormat("%s =%G",EnumToString((ENUM_STATISTICS),i),TesterStatistics((ENUM_STATISTICS)i));}
   return ret;}
   
DatabaseExecute(handleDB, MakeRequest("md5txt"));

un pequeño arreglo, con más paréntesis para arreglar :-)
la idea principal no es usar UPDATE x VALUES (), sino UPDATE x SET nombre1=valor1,nombre2=valor2. Para que la consulta funcione correctamente si se cambia la estructura de la base de datos y no dependa del orden de los campos

 

hay aproximadamente el siguiente código (leo los campos de texto de la base de datos y quiero convertirlos en enum)

class MyClass
{
public:
   enum A            {Aq, Aw, Ae, Ar, At, Ay};
   enum B            {Bq, Bw, Be};
   enum C            {Cq, Cw, Ce, Cr};

   static bool       txtToEnumA(const string txt, A &result);
   static bool       txtToEnumB(const string txt, B &result);
   static bool       txtToEnumC(const string txt, C &result);
};
//+------------------------------------------------------------------+
static bool MyClass::txtToEnumA(const string txt, A &result)
{
   for(int i = 0; i <= (int)A::Ay; i++)
   {
      if(StringCompare(EnumToString((A)i), txt) == 0)
      {
         result = (MyClass::A)i;
         return(true);
      }
   }
   return(false);
}
//+------------------------------------------------------------------+
static bool MyClass::txtToEnumB(const string txt, B &result)
{
   for(int i = 0; i <= (int)B::Be; i++)
   {
      if(StringCompare(EnumToString((B)i), txt) == 0)
      {
         result = (MyClass::B)i;
         return(true);
      }
   }
   return(false);
}
//+------------------------------------------------------------------+
static bool MyClass::txtToEnumC(const string txt, C &result)
{
   for(int i = 0; i <= (int)C::Cr; i++)
   {
      if(StringCompare(EnumToString((A)i), txt) == 0)
      {
         result = (MyClass::C)i;
         return(true);
      }
   }
   return(false);
}
//+------------------------------------------------------------------+
void OnStart()
{
   MyClass::A a;
   MyClass::B b;
   MyClass::C c;
   string txt[] = {"Aq", "Bw", "No"};

   if(MyClass::txtToEnumA(txt[0], a)) Print(txt[0], " in A = ", EnumToString(a));
   else Print("Error, ", txt[0], " not in A");

   if(MyClass::txtToEnumB(txt[1], b)) Print(txt[1], " in B = ", EnumToString(b));
   else Print("Error, ", txt[1], " not in B");

   if(MyClass::txtToEnumC(txt[2], c)) Print(txt[2], " in C = ", EnumToString(c));
   else Print("Error, ", txt[2], " not in C");
}
//+------------------------------------------------------------------+

2020.09.01 18:59:02.593 tst (EURUSD,M5) Aq en A = Aq

2020.09.01 18:59:02.593 tst (EURUSD,M5) Bw en B = Bw

2020.09.01 18:59:02.593 tst (EURUSD,M5) Error, No no en C

Todo funciona, pero la pregunta es de nuevo sobre el código óptimo:

si hay alguna manera de escribir en lugar de txtToEnumA() , txtToEnumB(), txtToEnumC()

método de la plantilla ( plantilla )

el problema es el diferente número de elementos en el enum

 

¿Qué pasa si hay un enum:

enum A            {Aq=10, Aw=9, Ae=8, Ar=7, At=6, Ay=5};

?

 
Dmitry Fedoseev:

¿Qué pasa si hay un enum:

?

la numeración de los elementos del enum no es una cuestión, no está claro para qué serviría

Sólo tengo 4 enumeraciones, no numeradas

el problema es que puedo querer añadir nuevos elementos a la enumeración - en mi código, voy a añadir nuevos elementos a NO los más externos - el código va a funcionar - no me gusta lo engorroso de este código


pero no estamos hablando de un código universal para todas las ocasiones, necesitamos las tareas actuales en una plantilla


SZY: no puedo prescindir de la enumeración - es conveniente, puedo leer igualmente los datos tanto en la fuente como en la base de datos, y en la base de datos tal vez quiero corregir algunos campos manualmente.... en general, todo me conviene

 
Igor Makanu:

la numeración de los elementos de la enumeración no es un problema, no está claro para qué servirá

Sólo tengo 4 enumeraciones, no numeradas

el problema es que puedo querer añadir nuevos elementos a las listas - en mi código, voy a añadir nuevos elementos a NO los más externos - el código va a funcionar - no me gusta la falta de manejabilidad del código


pero no estamos hablando de un código universal para todas las ocasiones, necesitamos las tareas actuales en una plantilla


SZY: no puedo prescindir de la enumeración - es conveniente, puedo leer igualmente los datos tanto en la fuente como en la base de datos, y en la base de datos tal vez quiero corregir algunos campos manualmente.... todo me parece bien

hacer un array global y llenarlo con pares { EnumToString(x) , x }

struct StringID {

   string str;

   int id;

};

StringID IDS[];

y las plantillas serán innecesarias.
 
Maxim Kuznetsov:

hacer un array global y llenarlo con pares { EnumToString(x) , x }

struct StringID {

   string str;

   int id;

};

StringID IDS[];

y no necesitarás plantillas.

Tu forma de hacerlo no difiere mucho de la mía: también es engorroso, y si hay algún cambio en el código, tendrás que editar también las matrices.

 

resolvió mi deseo de esta manera:

class MyClass
{
public:
   enum A            {Aq, Aw, Ae, Ar, At, Ay};
   enum B            {Bq, Bw, Be};
   enum C            {Cq, Cw, Ce, Cr};
   template<typename T>
   static bool       txtToEnum(const T LastElement, const string txt, T &result);
};
//+------------------------------------------------------------------+
template<typename T>
static bool MyClass::txtToEnum(const T LastElement, const string txt, T &result)
{
   for(int i = 0; i <= (int)LastElement; i++)
   {
      if(StringCompare(EnumToString((T)i), txt) == 0)
      {
         result = (T)i;
         return(true);
      }
   }
   return(false);
}
//+------------------------------------------------------------------+
void OnStart()
{
   MyClass::A a;
   MyClass::B b;
   MyClass::C c;
   string txt[] = {"Aq", "Bw", "No"};

   if(MyClass::txtToEnum(MyClass::Ay, txt[0], a)) Print(txt[0], " in A = ", EnumToString(a));
   else Print("Error, ", txt[0], " not in A");

   if(MyClass::txtToEnum(MyClass::Be, txt[1], b)) Print(txt[1], " in B = ", EnumToString(b));
   else Print("Error, ", txt[1], " not in B");

   if(MyClass::txtToEnum(MyClass::Cr, txt[2], c)) Print(txt[2], " in C = ", EnumToString(c));
   else Print("Error, ", txt[2], " not in C");

}
//+------------------------------------------------------------------+

2020.09.01 22:08:47.417 tst (EURUSD,M5) Aq en A = Aq

2020.09.01 22:08:47.417 tst (EURUSD,M5) Bw en B = Bw

2020.09.01 22:08:47.417 tst (EURUSD,M5) Error, No no en C



Necesitaría más definiciones para no introducir LastElement, pero en general este código es más compacto

 
Cuánto cuesta escribir todo tipo de cosas