OOP, Vorlagen und Makros in mql5, Feinheiten und Anwendungen - Seite 28

 
Maxim Kuznetsov:

Ich erinnere mich, dass in SQLite die Feldtypen optional sind und man sich nicht um die Angabe und Zuordnung von Typen kümmern muss. Es heißt nicht umsonst "Lite".

Sie können eine lange Abfrage in 3-4-5 Abfragen aufteilen :-)

BEGIN TRANSACTION

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

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

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

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

er stammt aus dem alten Speicher, also sollten Sie in der Hilfe nachsehen

ich hätte gerne einen reproduzierbaren Abfragecode, es wird lange dauern zu googeln, ich habe gelegentlich mit einer Datenbank gearbeitet - ich habe ein Problem, ich habe es gegoogelt, ich habe es gelöst - aber ich würde gerne eine fehlgeschlagene Datenbankabfrage sehen

 
Vladimir Simakov:

Ihr spezielles Problem sollte folgendermaßen gelöst werden:

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"));

eine kleine Korrektur, mit mehr Klammern zum Korrigieren :-)
die Hauptidee ist, nicht UPDATE x VALUES (), sondern UPDATE x SET name1=value1,name2=value2 zu verwenden. Damit die Abfrage korrekt funktioniert, wenn die Datenbankstruktur geändert wird, und nicht von der Reihenfolge der Felder abhängt

 

Es gibt ungefähr den folgenden Code (ich lese Textfelder aus der Datenbank und möchte sie in eine Aufzählung umwandeln)

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 in A = Aq

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

2020.09.01 18:59:02.593 tst (EURUSD,M5) Error, No not in C

Alles funktioniert, aber es stellt sich wieder die Frage nach dem optimalen Code:

ob eine Möglichkeit besteht, anstelle von txtToEnumA() , txtToEnumB(), txtToEnumC() zu schreiben

Schablonenmethode ( Schablone )

das Problem ist die unterschiedliche Anzahl von Elementen in der Aufzählung

 

Was, wenn es eine Aufzählung gibt:

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

?

 
Dmitry Fedoseev:

Was, wenn es eine Aufzählung gibt:

?

die Nummerierung der Enum-Elemente ist kein Problem, es ist nicht klar, was dies bewirken würde

Ich habe nur 4 Aufzählungen, nicht nummeriert

das Problem ist, dass ich neue Elemente zu Aufzählung hinzufügen möchten - in meinem Code, werde ich neue Elemente hinzufügen, um NICHT die äußersten - der Code wird funktionieren - ich mag nicht die Umständlichkeit dieses Codes


aber es geht nicht um einen universellen Code für alle Fälle, wir brauchen die aktuellen Aufgaben in einer Vorlage


SZY: Ich kann nicht auf die Aufzählung verzichten - sie ist praktisch, ich kann Daten sowohl in der Quelle als auch in der Datenbank lesen, und in der Datenbank möchte ich vielleicht einige Felder manuell korrigieren.... Im Allgemeinen passt alles zu mir.

 
Igor Makanu:

die Nummerierung der Elemente der Aufzählung ist kein Problem, es ist nicht klar, was dies bewirkt

Ich habe nur 4 Aufzählungen, nicht nummeriert

das Problem ist, dass ich neue Elemente zu Listen hinzufügen möchten - in meinem Code, werde ich neue Elemente NICHT die äußersten hinzufügen - der Code wird funktionieren - ich mag nicht die Unhandlichkeit des Codes


aber es geht nicht um einen universellen Code für alle Gelegenheiten, wir brauchen die aktuellen Aufgaben in einer Vorlage


SZY: Ich kann nicht auf die Aufzählung verzichten - sie ist praktisch, ich kann Daten sowohl in der Quelle als auch in der Datenbank lesen, und in der Datenbank möchte ich vielleicht einige Felder manuell korrigieren.... alles passt mir gut

ein globales Array erstellen und es mit Paaren { EnumToString(x) , x } füllen

struct StringID {

   string str;

   int id;

};

StringID IDS[];

und Vorlagen werden überflüssig sein.
 
Maxim Kuznetsov:

ein globales Array erstellen und es mit Paaren { EnumToString(x) , x } füllen

struct StringID {

   string str;

   int id;

};

StringID IDS[];

und Sie werden keine Vorlagen benötigen.

Ihre Vorgehensweise unterscheidet sich nicht wesentlich von meiner - sie ist auch umständlich, und wenn es Änderungen im Code gibt, müssen Sie auch die Arrays bearbeiten.

 

meinen Wunsch auf diese Weise gelöst:

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 in A = Aq

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

2020.09.01 22:08:47.417 tst (EURUSD,M5) Error, No not in C



Ich würde mehr Definitionen brauchen, um LastElement nicht einzugeben, aber insgesamt ist dieser Code kompakter

 
Wie viel es kostet, alles Mögliche zu schreiben