Erreurs, bugs, questions - page 2460

 
Il m'a fallu 2 heures pour isoler le problème du code du projet.
#define  PRINT(x) Print(#x, ":", string(x))

template<typename DATA_TYPE>
struct Wrapper{
   uchar type;
   DATA_TYPE data;
   
   template<typename T>
   void operator=(T value){                  // при замене данной строки на "void operator=(T &value){" происходит перезапись оператора присвоения в классе наследнике B (код не компилируется).
      this.data = value;   
   };
   
   void operator=(DATA_TYPE &_data){
      this.data = _data;   
   };
};

struct A{
   string data;
   
   void operator=(string value){
      data = value;
   };
};

struct B : Wrapper<A>{};


void OnStart(){  
  B b;
  
  string str_value;
  b = str_value;
  
  A a;
  b = a;
  
  B b1;
  b = b1;
}


En utilisant le code ci-dessus, tout fonctionne comme prévu,
. Cependant, si nous essayons d'étendre la fonctionnalité et d'ajouter le support non seulement de types simples comme (string) de la classe A, mais aussi de structures,
, il s'avère que l'opérateur d'assignation de la classe de base commence à remplacer les opérateurs d'assignation par défaut des classes descendantes, tuant toute fonctionnalité.
D'autres opérateurs peuvent être utilisés comme solutions de contournement, tels que "operator*=", mais c'est un désordre.


Aux développeurs :
Veuillez ajouter la possibilité de spécifier la génération de code forcée pour l'opérateur d'affectation par défaut (constructeur de copie) :
class_name & class_name :: operator= ( const class_name & ) = default;  
class_name & class_name :: operator= ( const class_name & ) = delete;   
 

Pouvez-vous me dire si j'utilise des indicateurs standards dans mon EA, par exemple iMA,

comment puis-je définir leurs styles de dessin pour les afficher correctement dans la fenêtre de visualisation ?

 
Игорь Евдокимов:

Pouvez-vous me dire si j'utilise des indicateurs standards dans mon EA, par exemple iMA,

comment puis-je définir les styles de dessin pour qu'ils s'affichent correctement dans la fenêtre de visualisation ?

Comme ceci :Couleur d'entrée de la moyenne mobile personnalisée

 
Des gens bien informés, un conseil ! J'ai un symbole personnalisé basé sur un vrai symbole. Comment puis-je faire en sorte qu'une transaction soit disponible à partir du graphique de ce symbole ? Ou cette fonctionnalité n'existe-t-elle pas dans MT5 ?
 

En fait, vous devez écrire votre propre indicateur. La réécriture des indicateurs standard n'est pas la solution.

La question était de savoir exactement comment définir le style pour l'indicateur standard.

Y a-t-il un autre moyen ?

 
Dans les versions récentes de MT, dans le cadre du changement de paradigme dans la gestion des chaînes de caractères, il est considéré comme abandonnant l'utilisation des chaînes terminées par NULL.
Cependant, le fonctionnement de la fonction StringSetLength soulève un certain nombre de questions.

Avec StringSetLength, vous ne pouvez que tronquer la longueur d'une chaîne, mais jamais l'augmenter, ce qui n'a pas de sens.
Est-ce un comportement voulu ?

#define  PRINT(x) Print(#x, ":", string(x))

void OnStart(){  
  string str = "123456789";
  PRINT(str);
  PRINT(StringLen(str));
  
  
  PRINT(StringSetLength(str, StringLen(str)-1));
  PRINT(str);
  PRINT(StringLen(str));
  
  PRINT(StringSetLength(str, StringLen(str)+2));
  PRINT(str);
  PRINT(StringLen(str));
}

Résultat :
2019.05.15 01:22:08.208 StringFormat_1 (EURUSD,H1)      str:123456789
2019.05.15 01:22:08.208 StringFormat_1 (EURUSD,H1)      StringLen(str):9
2019.05.15 01:22:08.208 StringFormat_1 (EURUSD,H1)      StringSetLength(str,StringLen(str)-1):true
2019.05.15 01:22:08.208 StringFormat_1 (EURUSD,H1)      str:12345678
2019.05.15 01:22:08.208 StringFormat_1 (EURUSD,H1)      StringLen(str):8
2019.05.15 01:22:08.208 StringFormat_1 (EURUSD,H1)      StringSetLength(str,StringLen(str)+2):false
2019.05.15 01:22:08.208 StringFormat_1 (EURUSD,H1)      str:12345678
2019.05.15 01:22:08.208 StringFormat_1 (EURUSD,H1)      StringLen(str):8
 
L'utilisateur préfère se tirer une balle plutôt que d'implémenter unStringSetLength"à part entière", avec de "nouveaux" caractères initialisés comme 0x0000.

#define  PRINT(x) Print(#x, ":", string(x))

void OnStart(){  
  string str = "123\x0000\x0000\x0000\x0000456789";
  PRINT(str);
  PRINT(StringLen(str));                                                  // StringLen(str):13      StringLen поддерживает работу с 0х0000 short value
  
  PRINT(StringSetLength_using_StringInit(str, 100));                      // false                  StringInit           не поддерживает работу с 0х0000 short value
  PRINT(StringSetLength_using_ShortArrayToString(str, 100));              // false                  ShortArrayToString   не поддерживает работу с 0х0000 short value
  PRINT(StringSetLength_using_StringInit_with_StringFill(str, 100));      // false                  StringFill           не поддерживает работу с 0х0000 short value
}


bool StringSetLength_using_StringInit(string &string_var, int new_length){
   bool result = false;

   int prev_length = StringLen(string_var);
   if(new_length == prev_length){
      result = true;
      return result;
   }
   
   string data = string_var;   
   if(new_length < prev_length){
      StringSetLength(data, new_length);
   }else{
      string string_tail;
      StringInit(string_tail, new_length - prev_length, 0x0000);
      data += string_tail;
   }
   
   if(StringLen(data) == new_length){
      string_var = data;
      result = true;
   }
   return result;
}

bool StringSetLength_using_ShortArrayToString(string &string_var, int new_length){
   bool result = false;

   int prev_length = StringLen(string_var);
   if(new_length == prev_length){
      result = true;
      return result;
   }
   
   string data = string_var;   
   if(new_length < prev_length){
      StringSetLength(data, new_length);
   }else{    
      short data_array[];
      StringToShortArray(data, data_array);
      ArrayResize(data_array, new_length);
      ArrayFill(data_array, prev_length, new_length - prev_length, 0x0000);
      data = ShortArrayToString(data_array, 0, new_length);
   }
   
   if(StringLen(data) == new_length){
      string_var = data;
      result = true;
   }
   return result;
}

bool StringSetLength_using_StringInit_with_StringFill(string &string_var, int new_length){
   bool result = false;

   int prev_length = StringLen(string_var);
   if(new_length == prev_length){
      result = true;
      return result;
   }
   
   string data = string_var;   
   if(new_length < prev_length){
      StringSetLength(data, new_length);
   }else{    
      string string_tail;
      StringInit(string_tail, new_length - prev_length, 0x1111);
      StringFill(string_tail, 0x0000);
      data += string_tail;
   }
   
   if(StringLen(data) == new_length){
      string_var = data;
      result = true;
   }
   return result;
}
 
Sergey Dzyublik:
Dans les versions récentes de MT, dans le cadre du changement de paradigme dans la gestion des chaînes de caractères, on constate un refus d'utiliser les chaînes terminées par NULL.

Pourriez-vous développer cette idée ?

 
rsrozhkov:
Les personnes bien informées peuvent-elles me donner un indice ? J'ai créé un symbole personnalisé basé sur un symbole réel. Comment puis-je faire en sorte qu'une transaction soit disponible à partir du graphique de ce symbole ? Ou cette fonctionnalité n'existe-t-elle pas dans MT5 ?

La réponse est évidente. Un symbole personnalisé est obtenu par une sorte de transformation à partir de symboles réels. Quelqu'un (EA, script ou manuellement) doit effectuer la transformation inverse et envoyer des ordres pour les symboles réels.

 
fxsaber:

Pourriez-vous développer ce point ?

Ce qui suit est mon opinion subjective. Si je me trompe quelque part, je serai heureux de vous aider.


StringLen fonctionnait en O(n) jusqu'au premier caractère NULL (0x0000) dans la chaîne, maintenant il fonctionne en O(1).
Lalongueur des chaînes pouvait toujours être tronquée via StringSetCharacter(str, pos, 0x00), mais ils ont introduit StringSetLength pour une raison quelconque.

Très probablement, l'analyseur a résolu la tâche d'accélération du code lors du travail avec des chaînes de caractères.
La tâche d'accélérer le code a été résolue et personne ne se soucie du fait que la moitié de la fonction gère maintenant les caractères NULL dans les chaînes de caractères et que l'autre moitié ne le fait pas.

#define  PRINT(x) Print(#x, ":", string(x))

void OnStart(){  
   string str = "123456789";
   PRINT(str);
   PRINT(StringLen(str));
   
   PRINT(StringSetCharacter(str, 7, 0x00));
   PRINT(StringLen(str));
   
   str += "\x00" + str;
   PRINT(StringLen(str));
   
   str += str;
   PRINT(str);
   PRINT(StringLen(str));
   
   ushort array[];
   PRINT(StringToShortArray(str, array));
   ArrayPrint(array);
   
   PRINT(StringLen(str));
   PRINT(StringLen(ShortArrayToString(array)));
   PRINT(StringLen(ShortArrayToString(array, 0, StringLen(str))));
} 

Le résultat :

2019.05.15 14:02:11.895 StringFormat_1 (EURUSD,H1)      str:123456789
2019.05.15 14:02:11.895 StringFormat_1 (EURUSD,H1)      StringLen(str):9
2019.05.15 14:02:11.895 StringFormat_1 (EURUSD,H1)      StringSetCharacter(str,7,0x00):true
2019.05.15 14:02:11.895 StringFormat_1 (EURUSD,H1)      StringLen(str):7
2019.05.15 14:02:11.895 StringFormat_1 (EURUSD,H1)      StringLen(str):15
2019.05.15 14:02:11.895 StringFormat_1 (EURUSD,H1)      str:1234567
2019.05.15 14:02:11.895 StringFormat_1 (EURUSD,H1)      StringLen(str):30
2019.05.15 14:02:11.895 StringFormat_1 (EURUSD,H1)      StringToShortArray(str,array):31
2019.05.15 14:02:11.895 StringFormat_1 (EURUSD,H1)      49 50 51 52 53 54 55  0 49 50 51 52 53 54 55 49 50 51 52 53 54 55  0 49 50 51 52 53 54 55  0
2019.05.15 14:02:11.895 StringFormat_1 (EURUSD,H1)      StringLen(str):30
2019.05.15 14:02:11.895 StringFormat_1 (EURUSD,H1)      StringLen(ShortArrayToString(array)):7
2019.05.15 14:02:11.895 StringFormat_1 (EURUSD,H1)      StringLen(ShortArrayToString(array,0,StringLen(str))):7