OOP, mql5의 템플릿 및 매크로, 미묘함 및 사용 기술 - 페이지 28

 
Maxim Kuznetsov :

첫째, SQLite에서 필드 유형은 선택 사항이며 유형 변환 및 포인팅에 대해 걱정할 필요가 없습니다. 그는 단지 "라이트"가 아닙니다.

긴 쿼리는 3-4-5로 나눌 수 있습니다 :-)

BEGIN TRANSACTION

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

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

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

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

이것은 오래된 기억에서 나온 것입니다. 즉, 인증서에서 명확히해야합니다.

재현 가능한 쿼리 코드를 원합니다. 오랫동안 구글링을 하고 산발적으로 데이터베이스를 작업했습니다. 작업이 있습니다. 구글링을 하고 결정했습니다. 하지만 실패한 데이터베이스 요청을 보고 싶습니다.

 
Vladimir Simakov :

특히 작업은 다음과 같아야 합니다.

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

편집할 대괄호가 더 많은 작은 수정 :-)
주요 아이디어는 UPDATE x VALUES()가 아니라 UPDATE x SET name1=value1,name2=value2를 사용하는 것입니다. 데이터베이스 구조가 변경될 때 쿼리가 올바르게 작동하고 필드 열거 순서에 의존하지 않도록

 

이 코드와 같은 것이 있습니다 (데이터베이스에서 텍스트 필드 를 읽고 열거 형으로 변환하고 싶습니다)

 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) A의 Aq = Aq

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

2020.09.01 18:59:02.593 tst (EURUSD,M5) 오류, C가 아님

모든 것이 작동하지만 질문은 다시 최적의 코드에 있습니다.

txtToEnumA() , txtToEnumB() , txtToEnumC() 대신 쓰는 방법이 있는 경우

하나의 템플릿 메서드( 템플릿 )

enum의 다른 수의 요소 문제

 

그리고 그러한 열거형이 있는 경우:

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

?

 
Dmitry Fedoseev :

그리고 그러한 열거형이 있는 경우:

?

열거의 요소에 번호를 매기는 것은 질문이 아니며 무엇을 줄 것인지 명확하지 않습니다.

번호가 지정되지 않은 목록이 4개뿐입니다.

문제는 열거형에 새 요소를 추가하고 싶을 수 있다는 것입니다. 내 코드에서 NOT에 극단적인 요소를 추가합니다. 코드가 작동합니다. 이 코드의 번거로움이 마음에 들지 않습니다.


그러나 우리는 모든 경우에 대한 일종의 범용 코드에 대해 이야기하는 것이 아니라 템플릿의 현재 작업이 필요합니다.


추신: 열거에서 벗어날 수 없을 것입니다. 소스 코드와 데이터베이스 모두에서 동일한 방식으로 데이터를 읽을 수 있고 데이터베이스에서 일부 필드를 손으로 수정할 수 있어 편리합니다. .... 일반적으로 모든 것이 적합합니다.

 
Igor Makanu :

열거의 요소에 번호를 매기는 것은 질문이 아니며 무엇을 줄 것인지 명확하지 않습니다.

번호가 지정되지 않은 목록이 4개뿐입니다.

문제는 열거형에 새 요소를 추가하고 싶을 수 있다는 것입니다. 내 코드에서 NOT에 극단적인 요소를 추가할 것입니다. 코드가 작동합니다. 이 코드의 부피가 마음에 들지 않습니다.


그러나 우리는 모든 경우에 대한 일종의 범용 코드에 대해 이야기하는 것이 아니라 템플릿의 현재 작업이 필요합니다.


추신: 열거에서 벗어날 수 없을 것입니다. 소스 코드와 데이터베이스 모두에서 동일한 방식으로 데이터를 읽을 수 있고 데이터베이스에서 일부 필드를 손으로 수정할 수 있어 편리합니다. .... 일반적으로 모든 것이 적합합니다.

바로 전역 배열을 만들고 { EnumToString(x) , x } 쌍으로 채웁니다.

struct StringID {

   string str;

   int id;

};

StringID IDS[];

템플릿이 필요하지 않습니다.
 
Maxim Kuznetsov :

바로 전역 배열을 만들고 { EnumToString(x) , x } 쌍으로 채웁니다.

struct StringID {

   string str;

   int id;

};

StringID IDS[];

템플릿이 필요하지 않습니다.

내 버전과 크게 다르지 않고 번거롭기도 하고 코드에 변경 사항이 있으면 배열을 수정해야 합니다.

 

다음과 같이 내 소원을 해결했습니다.

 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) A의 Aq = Aq

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

2020.09.01 22:08:47.417 tst (EURUSD,M5) 오류, C가 아님



more는 LastElement를 도입하지 않도록 정의하지만 일반적으로 코드는 이미 더 간결합니다.

 
온갖 것들을 쓰려면 얼마나 많은 것들이 필요할까