English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Les bases de la programmation MQL5 : Les chaînes

Les bases de la programmation MQL5 : Les chaînes

MetaTrader 5Exemples | 13 janvier 2022, 09:31
627 0
Dmitry Fedoseev
Dmitry Fedoseev

Introduction

Les chaînes, ou plutôt les variables de chaîne, sont utilisées pour stocker des données de caractères, c'est-à-dire du texte :

string str="Any text";

Le langage MQL5 offre une large gamme de fonctionnalités conviviales pour travailler avec des chaînes. Dans la programmation des Expert Advisors et des indicateurs, les chaînes sont principalement utilisées pour générer des messages d'information. Dans les indicateurs, il peut s'agir de messages concernant le respect de certaines conditions (par exemple, les signaux de trading), tandis que dans les Expert Advisors, ils peuvent rapporter les résultats de l'activité de trading. Lorsqu'il est exécuté, un Expert Advisor, un script ou un indicateur peut vérifier les paramètres définis par l'utilisateur et imprimer une notification au cas où les paramètres définis ne sont pas valides. En plus des notifications, vous pouvez parfois voir des messages d'invite qui donnent des recommandations concernant les réglages des paramètres. D'une manière générale, lors de la programmation en MQL5, les chaînes offrent avant tout une convivialité.

De plus, les chaînes sont essentielles lorsque vous travaillez avec des fichiers. L'écriture et la lecture de données à partir de fichiers sont effectuées à l'aide de variables de chaîne. En clair, on peut opter pour une autre façon de travailler avec les fichiers, une méthode binaire qui permet de lire et d'écrire des variables numériques et des tableaux. Cependant, si la quantité de données n'est pas trop importante, il est préférable d'utiliser des fichiers texte et des chaînes. Dans ce cas, le fonctionnement du programme est plus clair pour l'utilisateur et le processus de développement du programme est plus simple, offrant un contrôle immédiat des données. Les données du fichier texte ont la même apparence que les données à l'intérieur du programme.

L'utilisation de chaînes peut élargir considérablement les fonctionnalités du programme associées à l'entrée de données (paramètres) dans les cas où le nombre requis de paramètres n'est pas connu à l'avance (par exemple, la taille des lots pour les accumulations moyennes). Dans un tel cas, les valeurs peuvent être écrites dans une seule chaîne séparée par un séparateur, tel que le point-virgule :

input string Lots="0.1; 0.2; 0.3; 0.5";

Ensuite, lors de l'initialisation de l'Expert Advisor, la chaîne est divisée et un tableau de valeurs numériques est rempli. Malheureusement, il est impossible de passer en revue de tels paramètres de chaîne en optimisation, c'est-à-dire de définir la valeur initiale et finale ainsi que la valeur du pas. Dans certains cas, il peut être préférable d'utiliser un grand nombre de variables numériques dans la fenêtre des propriétés. Mais comme ils peuvent être virtuellement illimités en nombre, nous pouvons être confrontés à un problème de commodité et de finalité (si la possibilité d'optimisation est requise).

Il peut très bien exister d'autres cas où l'optimisation d'un paramètre n'est pas nécessaire, par exemple l'activation des notifications. MQL5 prend en charge différentes méthodes de notification de l'utilisateur : notifications sonores, notifications pop-up, notifications par e-mail et notifications push. Vous pouvez créer un commutateur de type bool pour chacune de ces notifications dans la fenêtre des propriétés (cela nécessitera au moins quatre variables) ou réduire le nombre de variables à une variable de chaîne.

Si vous devez activer les notifications sonores, vous écrivez "s" (son). Si vous avez également besoin d'avoir des notifications par e-mail, vous ajoutez "e". Ainsi, vous pouvez activer n'importe quelle combinaison de notifications en utilisant une seule variable. Pour un Expert Advisor, le nombre de paramètres externes importe peu. C'est juste une question de convivialité.

D'autre part, lors de l'élaboration d'indicateurs, vous devez chercher à réduire le nombre de paramètres externes. Il est très probable que l'indicateur soit appelé depuis un Expert Advisor ou un autre indicateur utilisant les fonctions iCustom() ou IndicatorCreate() dont le nombre de paramètres est limité (iCustom() n'a que 64 paramètres et la taille du tableau de paramètres de IndicatorCreate( ) est de 64 éléments). L'utilisation de chaînes peut donc être d'une grande valeur pratique.

Cet article passera en revue toutes les fonctions MQL5 standard pour travailler avec des chaînes et nous créerons également quelques fonctions personnalisées utiles.

 

Déclaration d'une variable chaîne

Comme tout autre type de variables, les variables de chaîne peuvent être déclarées :

string str;
ou recevoir une valeur lors de leur déclaration (initialisées à une valeur) :
string str="Any text";

Il n'y a aucune restriction quant à la longueur de la chaîne. Une longue chaîne peut, pour des raisons de commodité, être divisée en plusieurs sous-chaînes :

string str= "A long string can be "
            "split into several "
            "substrings";
//--- output the results
Alert(str);

Lorsqu'elle est initialisée de cette façon, la variable str aura la chaîne contenant "Une longue chaîne peut être divisée en plusieurs sous-chaînes".

En avançant légèrement ici, notons que la valeur d'une variable chaîne déclarée sans paramètres n'est pas identique à une chaîne vide :

string str="";

Vous pouvez le constater par vous-même :

string str1;
string str2="";
//--- output the comparison results
Alert(str1==str2);

Lors de l'exécution de ce code, une fenêtre d'alerte "faux" s'affichera. La variable chaîne non initialisée a la valeur NULL, ce qui n'est pas la même chose qu'une chaîne vide "". Vous devriez garder cela à l'esprit ! Lorsque l'on travaille avec des chaînes, nous devons très souvent vérifier si une chaîne est vide. Par conséquent, vous devez soit vous en tenir à la règle d'initialisation de toutes les chaînes avec une chaîne vide "" soit vérifier qu'elles ne sont pas égales à "" et non égales à NULL :

if(str!="" && str!=NULL)
  {
   //--- some operation with a string
  }

La première méthode est plus conseillée car elle simplifie la condition de vérification. 

Vous pouvez faire de même lors de la vérification de la taille d'une variable. Pour déterminer la taille, nous utilisons la fonction StringLen() :

if(StringLen(str)!=0)
  { 
   //--- some operation with a string
  }


Chaînes de concaténation

L'opération principale et la plus courante que vous pouvez effectuer lorsque vous travaillez avec des chaînes est de les concaténer, c'est-à-dire de construire des phrases à l'aide de mots. La concaténation est mise en œuvre à l'aide du signe "+":

string str1,str2,str3,str4,str5;
//--- assign values
str1="Programming";
str2="in MQL5";
str3="for MetaTrader 5";
//--- add up the strings
str4=str1+" "+str2;
str5=str1+" "+str3;
//--- output the results
Alert(str4);
Alert(str5);

Suite à l'exécution de ce code, la variable str4 contiendra "Programmation en MQL5", tandis que la variable str5 contiendra "Programmation pour MetaTrader 5". L'exemple ci-dessus a montré comment vous pouvez concaténer deux chaînes, la chaîne résultante étant affectée à une autre variable.

Une chaîne supplémentaire est très souvent concaténée avec la chaîne principale : 

string str1,str2,str3;
//--- assign values
str1="Programming";
str2="in MQL5";
str3="for MetaTrader 5";
//--- add up the strings to the main string
str1=str1+" "+str2;
str1=str1+" "+str3;
//--- output the results
Alert(str1);

Suite à l'exécution de ce code, la chaîne str1 contiendra "Programmation en MQL5 pour MetaTrader 5". L'exemple ci-dessus a montré comment vous pouvez concaténer des chaînes avec la chaîne principale str1, le résultat étant affecté à cette dernière. Les mêmes opérations peuvent être écrites de manière beaucoup plus simple :

str1+=str2;
str1+=str3;
ou :
str1+=str2+str3;

Le signe "+" à gauche de "=" signifie que l'expression à droite de "=" est ajoutée à la variable str1.

Vous pouvez également ajouter une chaîne au début de la chaîne principale. Cela peut être implémenté comme indiqué dans l'avant-dernier exemple : la chaîne principale est ajoutée à la chaîne supplémentaire et la chaîne résultante est affectée à la variable principale :

string str1,str2,str3;
//--- assign values
str1="Programming";
str2="in MQL5";
str3="for MetaTrader 5";
//--- concatenate strings, with a string being added to the beginning
str3=str2+" "+str3;
str3=str1+" "+str3;
//--- output the results
Alert(str3);

L'expression suivante : "Programmer en MQL5 pour MetaTrader 5" sera désormais dans la variable str3. Vous pouvez implémenter la même chose en utilisant une seule chaîne : 

str3=str1+" "+str2+" "+str3;
Dans certains cas, vous pouvez effectuer la concaténation en utilisant "," (virgule). C'est possible lors de l'appel des fonctions Alert(), Print() ou Comment() :
Print(str1," ",str2," ",str3);

Les résultats finaux seront dans ce cas identiques à l'utilisation du signe "+":

Print(str1+" "+str2+" "+str3);

Le symbole "," ne concatène en fait pas de chaînes. Une virgule est un séparateur de paramètres dans toutes les fonctions. C'est également vrai pour les fonctions Alert(), Print() et Comment(). Ces fonctions ont un paramètre obligatoire et de nombreux paramètres facultatifs. Les paramètres sont en effet passés à la fonction où ils sont concaténés. Le nombre maximum de paramètres est de 64.

Nous pouvons voir quelque chose de similaire lors de l'écriture d'une chaîne dans un fichier à l'aide de la fonction FileWrite(). Cependant, si vous ouvrez un fichier en mode FILE_CSV (avec séparateurs de champs), les virgules seront remplacées par le caractère séparateur spécifié lors de l'ouverture du fichier (si le séparateur n'est pas spécifié, la tabulation est utilisée par défaut). Lors de l'ouverture d'un fichier en mode FILE_TXT sans spécifier le séparateur, les résultats de l'utilisation du signe "+" et "," seront les mêmes :

//--- write to the first file
int h=FileOpen("1.txt",FILE_WRITE|FILE_ANSI|FILE_CSV);
FileWrite(h,"1","2","3");
FileClose(h);
//--- write to the second file
h=FileOpen("2.txt",FILE_WRITE|FILE_ANSI|FILE_CSV);
FileWrite(h,"1"+"2"+"3");
FileClose(h);
//--- write to the third file
h=FileOpen("3.txt",FILE_WRITE|FILE_ANSI|FILE_TXT);
FileWrite(h,"1","2","3");
FileClose(h);
//--- write to the fourth file
h=FileOpen("4.txt",FILE_WRITE|FILE_ANSI|FILE_TXT);
FileWrite(h,"1"+"2"+"3");
FileClose(h);

Après avoir exécuté ce code, le fichier 1.txt contiendra "1 2 3", tandis que le fichier 2.txt contiendra "123" (les fichiers ont été ouverts en mode FILE_CSV). 3.txt et 4.txt auront un contenu identique : "123" (ouvert en mode FILE_TXT). Cet article ne se concentre pas sur les opérations sur les fichiers. Par conséquent, s'il y a quelque chose dans le dernier exemple qui ne vous semble pas clair, peu importe car cela n'affectera pas votre compréhension du matériel exposé plus loin dans cet article. Notez simplement que l'utilisation de "+" et "," ne produit pas toujours le même effet lorsqu'il s'agit d'ajouter des chaînes.

En plus du signe "+", MQL5 fournit des fonctions spéciales pour l'ajout de chaînes : StringAdd() et StringConcatenate(). D'après la description de ces fonctions dans la référence MQL5, elles nous permettent d'ajouter des chaînes de manière plus efficace en termes d'espace (en termes de mémoire de travail occupée) et plus rapidement. La fonction StringAdd() permet d'ajouter une chaîne à une autre :

string str1,str2,str3;
//--- assign values
str1="Programming";
str2="in MQL5";
str3="for MetaTrader 5";
//--- call the function to concatenate strings
StringAdd(str1," ");
StringAdd(str1,str2);
StringAdd(str1," ");
StringAdd(str1,str3);
//--- output the results
Alert(str1);

Suite à l'exécution de ce code, la variable str1 aura la chaîne contenant "Programmation en MQL5 pour MetaTrader 5".

La fonction StringConcatenate() permet de combiner simultanément plusieurs chaînes. Le premier paramètre passé à la fonction est la variable de la chaîne à laquelle les autres chaînes répertoriées seront ajoutées. Le nombre maximum de paramètres que vous pouvez passer à la fonction est de 64 :

string str1,str2,str3;
//--- assign values
str1="Programming";
str2="in MQL5";

str3="for MetaTrader 5";
//--- call the function for combining several strings
StringConcatenate(str1,str1," ",str2," ",str3);
//--- output the results
Alert(str1);

Après avoir exécuté ce code, la variable str1 contiendra également "Programmation en MQL5 pour MetaTrader 5".

 

Conversion de diverses variables en chaîne

Lors de la génération d'une chaîne de message, nous avons très souvent besoin d'ajouter des valeurs de variables numériques. Pour convertir les valeurs des variables entières (char, uchar, bool, short, ushort, int, uint, color, long, ulong, datetime) en une chaîne, nous utilisons la fonction IntegerToString() :

int x=1;
string str="x = "+IntegerToString(x);

Lors de la conversion d'une variable de type bool, une chaîne renvoyée contiendra soit "0" (faux) soit "1" (vrai). De même, si vous convertissez des variables de type couleur ou date, la chaîne retournée contiendra une expression numérique de la couleur ou de la date (par exemple, "65535" pour la couleur jaune de clrYellow ou "1325376000" pour la date comme suit : 2012.01.01 00:00).

Pour convertir des variables réelles (double, float) en chaîne, nous utilisons la fonction DoubleToString(). Le deuxième paramètre de cette fonction détermine la précision (le nombre de décimales) :

double x=1.23456;
string str1="x = "+DoubleToString(x,2);
string str2="x = "+DoubleToString(x,3);

Suite à l'exécution de ce code, la variable str1 contiendra la chaîne "1.23", tandis que la variable str2 contiendra la chaîne "1.235". La troncature au nombre de chiffres spécifié est effectuée à l'aide des règles d'arrondi mathématiques.

La fonction TimeToString() est utilisée pour convertir la date et l'heure en une chaîne de format standard (facilement compréhensible par les êtres humains) :

datetime tm=TimeCurrent(); // Current time 
string str1=IntegerToString(tm);
string str2=TimeToString(tm);

Après l'exécution de ce code la variable str1 contiendra la chaîne avec une expression numérique du temps (le nombre de secondes écoulées depuis le 1er janvier 1970), tandis que la variable str2 contiendra le temps formaté, par exemple "2012.11.02 22:00" (année, mois, jour, heure, minute).

Lors de l'appel de la fonction TimeToString(), vous avez la possibilité de spécifier le format de date et d'heure. Les options disponibles sont :

string str1="Date and time with minutes: "+TimeToString(tm);
string str2="Date only: "+TimeToString(tm,TIME_DATE);
string str3="Time with minutes only: "+TimeToString(tm,TIME_MINUTES);
string str4="Time with seconds only: "+TimeToString(tm,TIME_SECONDS);
string str5="Date and time with seconds: "+TimeToString(tm,TIME_DATE|TIME_SECONDS);

MQL5 offre une fonction très pratique pour créer des énumérations qui sont affichées dans la fenêtre des propriétés du programme sous forme de listes déroulantes d'options. Les valeurs de ces variables peuvent également être converties en une chaîne à l'aide de la fonction EnumToString(). Vous trouverez ci-dessous le code du script démontrant le fonctionnement de cette fonction :

//+------------------------------------------------------------------+
//| Create an enumeration                                            |
//+------------------------------------------------------------------+
enum EMode
  {
   OFF=0,
   Mode1 = 1,
   Mode2 = 2,
   Mode3 = 3 
  };
//+------------------------------------------------------------------+
//| Start the script                                                 |
//+------------------------------------------------------------------+
void OnStart()
  {
   EMode Value=1;
   //--- join strings together
   string str="The "+IntegerToString(Value)+ value" corresponds to "+EnumToString(Value)+ entry" of the Emode enumeration";
   //--- output the results
   Alert(str);
  } 
Il existe une possibilité similaire vous permettant de convertir des variables de couleur. Vous pouvez convertir la valeur de la couleur en nom de la couleur à l'aide de la fonction ColorToString() :
color ColorValue=clrRed;
string str=ColorToString(ColorValue,true);

Après avoir exécuté ce code, la variable str stockera la chaîne contenant "clrRed". Si le deuxième paramètre est défini comme faux, la fonction renverra la chaîne de caractères avec les valeurs des composantes RVB (rouge, vert et bleu) :

color ColorValue=clrRed;
string str=ColorToString(ColorValue,false);

Dans ce cas, la chaîne stockée dans la variable str sera "255,0,0". Si la couleur que vous traitez n'est pas standard (non définie sur la palette de couleurs Web et par conséquent sans nom), la fonction ColorToString() peut être utilisée pour renvoyer la chaîne avec les valeurs des composants quelle que soit la valeur du deuxième paramètre.

Il existe encore une autre méthode pour convertir des variables à l'aide du transtypage :

int x=123;
string str=(string)x;

Lorsqu'une variable de type bool est convertie de cette manière, la valeur de la chaîne sera soit vrai "true" soit faux "false" : 

bool x=true;
string str=(string)x;

La conversion des variables de type double et flottant doit être aussi précise que possible, vous permettant de ne supprimer que des zéros dans la partie fractionnaire : 

double x1=0.1;
double x2=0.123string str1=(string)x1;
string str2=(string)x2;

Suite à l'exécution de ce code, la variable str1 stockera la valeur de chaîne de "0.1" et la variable str2 contiendra la valeur de chaîne de "0.123".

 

Sortie de caractères spéciaux

Lors de l'initialisation d'une variable de chaîne à une valeur, la chaîne attribuable doit être écrite entre guillemets doubles afin que le compilateur puisse distinguer la chaîne du code du programme. Pour pouvoir mettre les guillemets à l'intérieur de la chaîne, vous devez spécifier le fait que les marques ne sont pas utilisées ici pour leur usage normal (en tant que caractères séparant une chaîne d'un code) mais plutôt comme partie d'une chaîne. Pour implémenter cela, placez une barre oblique inverse "\" juste avant le guillemet :

string str1="Simple text";
string str2="\"Text in quotes\"";
//--- output the results
Alert(str1);
Alert(str2);

Comme la barre oblique inversée est également considérée comme un caractère spécial, il faut la faire précéder d'une autre barre oblique inversée pour la faire apparaître dans une chaîne de caractères :

string str="\\";
Alert(str);

Après avoir exécuté ce code, le seul caractère que la chaîne contiendra sera "\".

Une chaîne peut également contenir un caractère de tabulation horizontale représenté par "\t":

string str="Column-1\tColumn-2\tColumn-3";
Alert(str);

Dans ce cas, la variable str aura la chaîne contenant "Colonne-1        Colonne-2        Colonne-3".

Un texte peut également être imprimé avec des sauts de ligne, découpé en plusieurs lignes par "\n":

string str="Line-1\nLine-2\nLine-3";
Alert(str);

Ici, à la suite de l'exécution de la fonction Alert(), vous aurez trois lignes de texte.

Lors de l'impression à l'aide des fonctions Alert() et MessageBox(), ainsi que lors de l'écriture dans un fichier, vous pouvez utiliser à la fois "\t" et "\n". Cependant, lors de l'impression d'un commentaire de graphique (la fonction Comment()), seul "\n" s'applique comme caractère d'habillage, tandis que le caractère de tabulation "\t" est ignoré. Lorsque la sortie est effectuée à l'aide de la fonction Print(), "\n" s'applique comme avant (chaque partie d'une chaîne est sortie dans une ligne distincte du journal) et "\t" est remplacé par un espace comme dans le fichier journal qui stocke tous les messages générés à l'aide de la fonction Print().

 

Formatage des chaînes de caractères basé sur des motifs ;

Lors du formatage d'une chaîne pour la sortie, vous devrez peut-être y inclure les valeurs de plusieurs variables numériques. Ceci peut être réalisé en additionnant des chaînes et en convertissant des variables numériques en chaînes. Cependant, dans ce cas, la chaîne de code composant un message sera trop longue et difficile à comprendre et à éditer, si des modifications du programme sont nécessaires :

//--- initialize the variables
int Variable1=1;
int Variable2=2;
int Variable3=3;
//--- long addition of strings
string str="Variable1 = "+IntegerToString(Variable1)+", Variable2 = "+IntegerToString(Variable2)+", Variable3 = "+IntegerToString(Variable2);
//--- output the results
Alert(str);

La même tâche peut être résolue de manière beaucoup plus simple à l'aide de la fonction StringFormat(). Le premier paramètre passé à cette fonction est un modèle de message, avec des emplacements indiqués pour insérer des variables et définir le format de sortie. Elle est suivie de l'énumération de toutes les variables dans l'ordre dans lequel elles apparaissent dans le modèle : 

//--- initialize the variables
int Variable1=1;
int Variable2=2;
int Variable3=3;
//--- simpler addition of strings
string str=StringFormat("Variable1 = %i, Variable2 = %i, Variable3 = %i",Variable1,Variable2,Variable3);
//--- output the results
Alert(str);

Les emplacements d'insertion de variables sont marqués de "%" suivi de "i", ce qui dans l'exemple ci-dessus indique que les variables doivent être sorties sous forme d'entiers. Ou plutôt, "i" représente les variables entières de caractères (char, short, int, color), alors que nous utilisons "u" pour les variables entières non signées (uchar, bool, ushort, uint). Pour les variables du type de données long, ulong et datetime, vous devez en outre spécifier la taille de la variable en mettant "I64" avant le type :

string LongMin=StringFormat("%I64i",LONG_MIN);
string LongMax=StringFormat("%I64i",LONG_MAX);
string ULongMax=StringFormat("%I64u",ULONG_MAX);
string DateTimeMax=StringFormat("%I64u",DateMax);
//--- output the results
Alert("LongMin = "+LongMin);
Alert("LongMax = "+LongMax);
Alert("ULongMax = "+ULongMax);
Alert("DateTimeMax = "+DateTimeMax);
À la suite de ce code, vous verrez une fenêtre pop-up avec des valeurs variables.

Le format des nombres réels est noté "f":
double Percents=5.5;
//--- real number as a string
string str=StringFormat("Percents = %f",Percents);
//--- output the results
Alert(str);

Après avoir exécuté ce code, la variable str stockera la chaîne suivante : "Pourcentages = 5.500.000". La précision de sortie par défaut est de six décimales. Vous pouvez définir le nombre requis de décimales :

string str=StringFormat("Percents = %.2f",Percents);

Pour cela, mettez un point désignant un symbole décimal immédiatement suivi du nombre de décimales, par exemple 2 comme dans l'exemple ci-dessus. Dans ce cas, la variable str contiendra la chaîne comme suit : "Pourcentages = 5,50". Cette option de mise en forme est totalement identique à la fonction DoubleToString().

Vous pouvez spécifier la longueur totale d'un nombre en écrivant "0" et un nombre qui détermine la longueur du nombre à portée de main juste après "%", puis spécifier le nombre de décimales (si nécessaire) :

string str=StringFormat("Percents = %06.2f",Percents);

Ici, nous avons une longueur totale de 6 chiffres, dont un sera utilisé pour la virgule et deux autres représenteront deux décimales. Par conséquent, la chaîne stockée dans la variable str sera "Pourcentages = 005,50".

Si vous devez afficher le signe de pourcentage "%" dans un message, vous devez l'écrire deux fois de suite, c'est-à-dire "%%", car l'un d'entre eux sera utilisé pour indiquer les emplacements d'insertion de valeurs :

string str=StringFormat("Percents = %06.2f%%",Percents);

Dans ce cas, la variable str contiendra "Pourcentages = 005.50%".

Vous pouvez également déterminer la longueur d'un nombre lors de la sortie de variables entières :

int Variable=123;
//--- integer as a string with a set output length
string str=StringFormat("Variable = %05i",Variable);
//--- output the results
Alert(str);

Après l'exécution de ce code la variable str stockera la chaîne suivante : "Variable = 00123".

Si le nombre de chiffres spécifié est inférieur au nombre de chiffres du nombre, la sortie sera toujours effectuée correctement :

string str=StringFormat("Variable = %02i",Variable); 

Ici, la variable str contiendra la chaîne comme suit : "Variable = 123", c'est-à-dire que le numéro de sortie aura 3 chiffres malgré le fait que la longueur spécifiée soit 2.

Les nombres réels peuvent être sortis en utilisant la notation scientifique (mantisse de six décimales et puissance) pour laquelle nous utilisons le caractère "e":

double Variable=123.456;
//--- real number as a string in scientific notation
string str=StringFormat("Variable = %e",Variable);
//--- output the results
Alert(str);

Après avoir exécuté ce code, la variable str contiendra "1.234560e+002". Vous pouvez également utiliser le "E" majuscule dont l'effet est similaire au "e" minuscule, le "E" majuscule remplaçant le "e" minuscule dans une chaîne formatée.

Il existe encore une autre façon de formater les nombres réels - en utilisant "g" où seuls six chiffres (à l'exclusion de tout point décimal) peuvent être sortis. Si la longueur de la partie entière d'un nombre dépasse six chiffres, le nombre sera généré en utilisant la notation scientifique :

double Variable1=12.3456789;
double Variable2=1234567.89;
//--- get real numbers as strings using "g"
string str1=StringFormat("Variable = %g",Variable1);
string str2=StringFormat("Variable = %g",Variable2);
//--- output the results
Alert(str1+" "+str2);

Dans l'exemple ci-dessus, la variable str1 contiendra "12.3457" et la variable str2 contiendra "1.23457e+006". L'effet sera le même si vous utilisez plutôt le "G" majuscule, la seule différence étant que dans la sortie, le "g" minuscule sera remplacé par le "G" majuscule.

La fonction StringFormat() permet de transformer les formats de représentation des nombres, c'est-à-dire de convertir les nombres du système décimal au système octal ou hexadécimal. Pour convertir un nombre au système octal, vous devez utiliser le caractère "o":

int Variable=17;
//--- real number as a string in the octal system
string str=StringFormat("Variable = %o",Variable);
//--- output the results
Alert(str);

Suite à l'exécution de ce code, la variable str stockera la chaîne comme suit : "Variable = 21" (8*2+1=17).

"x" ou "X" est utilisé pour convertir un nombre au système hexadécimal. Dans un tel cas, si vous utilisez le "x" minuscule, un nombre du système hexadécimal sera composé de lettres minuscules, ou de lettres majuscules, si le "X" majuscule est utilisé :

color Variable=clrBlue;
//--- real number as a string in the hexadecimal system
string str=StringFormat("Variable = %x",Variable);
//--- output the results
Alert(str);

Après avoir exécuté ce code, la variable str contiendra "Variable = ff0000".

De même, vous pouvez reconvertir un nombre du système hexadécimal en système décimal à l'aide du caractère "d":

int Variable=0x0000ff;
//--- real number as a string in the decimal system
string str=StringFormat("Variable = %d",Variable);
//--- output the results
Alert(str);

Après l'exécution de ce code, la chaîne que la variable str stockera sera "Variable = 255".

Le caractère "s" peut être utilisé pour sortir des variables de chaîne :

string Variable="text";
//--- output the string variable
string str=StringFormat("Variable = %s",Variable);
//--- output the results
Alert(str);

Dès que vous exécutez le code ci-dessus, la chaîne contenant "Variable = text" sera stockée dans la variable str.

Parfois, vous devrez peut-être aligner les nombres lors de leur sortie dans une colonne, étant donné que les nombres négatifs se déplacent à cause du signe "-". Pour aligner les nombres positifs avec les négatifs, vous devez ajouter un espace au début de la chaîne, juste après "%". Dans ce cas, les nombres négatifs seront affichés sans espace contrairement aux nombres positifs qui auront un espace au début :

int Variable1=1;
int Variable2=-1;
//--- representation of numbers as aligned strings
string str1=StringFormat("Variable1=% 03i",Variable1);
string str2=StringFormat("Variable2=% 03i",Variable2);
//--- output the results
Alert(str1);
Alert(str2);

Suite à l'exécution de ce code, la variable str1 contiendra "Variable1= 01" (la chaîne avec un espace), tandis que la variable str2 stockera la chaîne comme suit : "Variable2=-01".

Il existe deux autres fonctions similaires à StringFormat(). Ce sont PrintFormat() et printf() qui sont absolument identiques en termes d'action. Leur seule différence par rapport à la fonction StringFormat() est qu'ils génèrent du texte dans le journal de la même manière que la fonction Print().

En fait, la fonction StringFormat() offre beaucoup plus de fonctionnalités, tandis que le matériel fourni ci-dessus représente le minimum requis pour résoudre la majorité des problèmes concernant le formatage des nombres pour la sortie.
 

Messages dans différentes langues

La fonction StringFormat() vous donne la possibilité d'améliorer votre programme avec une fonctionnalité très utile qui permet d'imprimer des messages dans différentes langues, en fonction de la langue d'interface définie dans le terminal.

Vous pouvez savoir quelle langue d'interface est définie en appelant la fonction TerminalInfoString() avec l'identifiant TERMINAL_LANGUAGE. Lors de l'exécution d'un programme, nous préparons une chaîne de format en fonction de la langue de l'interface, puis l'utilisons dans le programme. Vous trouverez ci-dessous un modèle d’Expert Advisor avec la fonctionnalité ci-dessus implémentée :

//--- variable for a format string
string FormatString;
//+------------------------------------------------------------------+
//| Handling the Init event                                          |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- get the format string
   FormatString=GetFormatString();
//--- additional call in case you want to ensure that the Expert Advisor operates at least once at weekends
   OnTick();
   return(0);
  }
//+------------------------------------------------------------------+
//| Handling the Tick event                                          |
//+------------------------------------------------------------------+
void OnTick()
  {
   int Variable1,Variable2,Variable3;
   Variable1=MathRand()%10;        // Random number from 0 to 10
   Variable2=MathRand()%10;        // Another random number
   Variable3=Variable1+Variable2; // Sum of numbers
//--- output the results
   Alert(StringFormat(FormatString,Variable1,Variable2,Variable3));
  }
//+------------------------------------------------------------------+
//| Determining the format string                                    |
//+------------------------------------------------------------------+
string GetFormatString(void)
  {
   string Language=TerminalInfoString(TERMINAL_LANGUAGE);
//--- language check
   if(Language=="Russian") return("%i плюс %i равно %i");     // Russian
   if(Language=="Spanish") return("%i más %i es igual a %i"); // Spanish
//--- English - in all other cases
   return("%i plus %i equals %i");
  }

L'Expert Advisor calcule la somme de deux nombres aléatoires et affiche le message concernant ses actions, par exemple "1 plus 2 font 3".

C'est à peu près tout en ce qui concerne la sortie des chaînes. Nous allons maintenant passer à des manipulations de chaînes un peu plus complexes, mais plus intéressantes.

 

Fonctions clés pour travailler avec des chaînes

Si une chaîne est saisie via la fenêtre des propriétés du programme ou lue à partir d'un fichier, elle peut contenir des espaces inutiles. Ils peuvent apparaître en raison d'une imprudence fortuite de l'utilisateur ou par commodité. Avant d'utiliser la chaîne de quelque manière que ce soit, il est conseillé de supprimer les espaces à gauche et à droite. À cette fin, MQL5 propose deux fonctions - StringTrimLeft() (supprime les espaces à l'extrémité gauche) et StringTrimRight() (supprime les espaces à l'extrémité droite). En plus des espaces, ces fonctions suppriment également les tabulations et les caractères de nouvelle ligne. Lorsque nous travaillons avec des chaînes, nous devons souvent supprimer les espaces aux deux extrémités à la fois, donc une fonction qui implémente cela sera très utile :

string Trim(string Str)
  {
   StringTrimLeft(Str);
   StringTrimRight(Str);
   return(Str);
  } 

Lors de la saisie de nombres réels, l'utilisateur peut souvent mettre une virgule au lieu d'un point. Par conséquent, lorsque vous travaillez avec des nombres réels, vous devez offrir la possibilité d'utiliser à la fois le point et la virgule comme symbole décimal. Pour remplacer une chaîne par une autre, nous utilisons la fonction StringReplace() :

string str="123,456";
//--- replace a comma with a dot
StringReplace(str,",",".");
double Value=StringToDouble(str);
//--- output the results
Alert(DoubleToString(Value));

Si vous ne remplacez pas "," par ".", la partie fractionnaire du nombre sera tronquée lors de la conversion d'une chaîne en nombre.

Dans certains cas, vous devrez peut-être remplacer une série d'espaces par un seul espace. Pour ce faire, vous devez d'abord remplacer les caractères de tabulation par un espace, puis remplacer deux espaces par un jusqu'à ce qu'il ne reste plus qu'un espace :

string str="Column-1 \t Column-2 \t Column-3";
//--- replace the tab character with a space
StringReplace(str,"\t"," ");
//--- get one space instead of the series of spaces
while(StringReplace(str,"  "," ")>0){}
//--- output the results
Alert(str);

La fonction StringReplace() renvoie le nombre de remplacements effectués ou -1 en cas d'erreur. Ainsi, la boucle se poursuit avec la fonction renvoyant une valeur supérieure à zéro jusqu'à ce que toutes les séries d'espaces soient remplacées par un espace qui reste dans chaque cas. Le corps de la boucle ne contient aucun code. Lors de la vérification de la condition de boucle à chaque itération, nous appelons la fonction StringReplace().

La fonction StringReplace() nous permet de remplacer des sous-chaînes de différentes longueurs :

string str="Programming in MQL5!";
//--- replace the substring, output the results
StringReplace(str,"in MQL5","for MetaTrader 5");
Alert(str);
//--- reverse replacement, output the results
StringReplace(str,"for MetaTrader 5","in MQL5");
Alert(str);

Lors de l'exécution de ce code, la variable str après le premier remplacement aura la chaîne contenant "Programmation pour MetaTrader 5" et "Programmation en MQL5 !" après le deuxième remplacement.

La fonction StringFind() est utilisée pour rechercher une sous-chaîne. Il renvoie l'index de la première occurrence de la sous-chaîne dans une chaîne. Le premier paramètre passé à la fonction est une chaîne dans laquelle la recherche est effectuée. Le deuxième paramètre détermine la sous-chaîne cible, tandis que le troisième paramètre (facultatif) peut déterminer la position à laquelle la recherche commence. Si le troisième paramètre n'est pas spécifié, la fonction fonctionne comme si sa valeur était 0, c'est-à-dire que la recherche commence au tout début de la chaîne. Trouvons la position de la sous-chaîne « 5 » dans la chaîne « Programmation en MQL5 pour MetaTrader 5 » :

string str="Programming in MQL5 for MetaTrader 5";
//--- get the position of the character
int Pos=StringFind(str,"5");
//--- output the results
Alert(IntegerToString(Pos));

Suite à l'exécution de ce code, la valeur de la variable Pos sera 23. La sous-chaîne "5" apparaît deux fois au total, mais la fonction ne renvoie que la position de la première occurrence. Si vous comptez la position en regardant simplement la chaîne, vous obtiendrez 24. Le fait est que la fonction commence à compter à partir de zéro plutôt que de un. Si la sous-chaîne cible n'est pas trouvée dans la chaîne, la fonction renvoie -1.

De temps en temps, vous devrez peut-être trouver une position de la dernière occurrence de la sous-chaîne. Pour cela, nous devrons écrire une fonction personnalisée, StringFindRev(). On va commencer par rechercher la première occurrence de la sous-chaîne, puis décaler le début de la recherche en fonction de la position trouvée, etc. dans une boucle :

int StringFindRev(string Str,string Find)
  {
//--- the pos variable for the returned value
   int pos;
//--- auxiliary variable initialized to -1,
//--- in case the substring is not found in the string
   int tmp=-1;
//--- loop. It will be executed at least once
   do
     {
      //--- assign the last known position of the substring
      pos=tmp;
      //--- continue searching (using the third parameter of the function)
      tmp=StringFind(Str,Find,tmp+1);
     }
   while(tmp!=-1); // If the substring is not found in the remaining part of the string, the loop 
                   // is terminated and the pos variable stores the last
                   // known position
//--- return the position
   return(pos);
  }
Essayons d'utiliser cette fonction :
string str="Programming in MQL5 for MetaTrader 5";
//--- call the function for searching for a position of the last occurrence of the character in the string
int pos=StringFindRev(str,"5");
//--- output the results
Alert(pos);

Après avoir exécuté ce code, la variable Pos aura la valeur 40.

La fonction StringSubstr() est utilisée pour obtenir une sous-chaîne d'une longueur donnée à partir d'une position donnée. Obtenez la sous-chaîne de longueur 1 à partir de la position 23 :

string str="Programming in MQL5 for MetaTrader 5";
//--- get the substring of the given length from the given position
string str2=StringSubstr(str,23,1);
//--- output the results
Alert(str2);

Le chiffre obtenu est "5".

Maintenant que nous avons considéré les fonctions principales, utilisons-les pour écrire une fonction utile pour supprimer une liste donnée de caractères d'une chaîne. La fonction reçoit la chaîne source et une chaîne qui représente une liste de caractères à supprimer de la chaîne source.

string TrimL(string Str,string List="\t\n ;")
  {
//--- variable for one character of the Str string
   string ch;
   int Len=StringLen(Str);
   int i=0;
//--- loop iteration over all characters of the Str string
   for(;i<Len;i++)
     {
      //--- the next character of the Str string
      ch=StringSubstr(Str,i,1);
      //--- if this character is not on the List list, the string should start from this position 
      if(StringFind(List,ch,0)==-1)
        {
         break; // terminate the loop
        }
     }
//--- get the substring and return it
   return(StringSubstr(Str,i));
  }

La fonction supprime la tabulation et le caractère de nouvelle ligne, ainsi qu'un espace et un point-virgule ";" par défaut.

La même fonction pour supprimer à l'extrémité droite :

string TrimR(string Str,string List="\t\n ;")
  {
//--- variable for one character of the Str string
   string ch;
   int Len=StringLen(Str);
//--- characters in the string are numbered from 0, so the last character index is one less than the string length
   int i=Len-1;
//--- loop iteration over all characters of the Str string
   for(;i>=0;i--)
     {
      //--- the next character of the Str string
      ch=StringSubstr(Str,i,1);
      //--- if this character is not on the List list, the string should start from this position 
      if(StringFind(List,ch,0)==-1)
        {
         break; // terminate the loop
        }
     }
//--- get the substring and return it
   return(StringSubstr(Str,0,i+1));
  }

Cette fonction supprime également la tabulation et le caractère de nouvelle ligne, ainsi qu'un espace et un point-virgule ";" par défaut. Cela peut s'avérer utile lors de la lecture de fichiers CSV. À l'intérieur de ces fichiers, il peut y avoir beaucoup de séparateurs de champs (généralement des points-virgules ";") à l'extrémité droite d'une chaîne.

Lettres majuscules et minuscules, par exemple "А" et "а" ne sont pas considérés comme différents dans leur sens par les humains, alors que les ordinateurs les traitent comme deux caractères complètement différents. Si vous écrivez "eurusd" au lieu de "EURUSD" lorsque vous demandez les données du marché à l'aide de la fonction SymbolInfoDouble(), la fonction ne renverra pas la valeur requise. Cela est très susceptible de se produire lors de la saisie du nom du symbole dans la fenêtre des propriétés. Pour changer la casse dans MQL5, vous pouvez utiliser la fonction StringToLower() (pour passer en minuscule) et la fonction StringToUpper() (pour passer en majuscule) :

string str="EuRuSd";
string str1=str;
string str2=str;
//--- change the case of strings
StringToUpper(str1);
StringToLower(str2);
//--- output the results
Alert(str1," ",str2);

Suite à l'exécution de ce code, la variable str1 stockera la chaîne qui contient "EURUSD", tandis que la variable str2 aura la chaîne contenant "eurusd".

Si ce dont vous avez besoin est de comparer les chaînes sans prendre en compte leur casse, la fonction StringCompare() sera la meilleure solution. Les deux premiers paramètres de la fonction sont les chaînes de comparaison. Le troisième paramètre détermine si les chaînes doivent être comparées, en tenant compte (vrai) ou non (faux) de leur casse :

int Result=StringCompare("eurusd","EURUSD",false);
Alert(Result); 

Si la fonction renvoie 0, les chaînes sont identiques. La fonction peut retourner -1 si la première chaîne est inférieure à la seconde, ou 1 si la première chaîne est supérieure à la seconde. "Plus grand" et "moins grand" signifient l'état de la chaîne lorsqu'elle est triée par ordre alphabétique. La lettre "b" est supérieure à la lettre "a":

int Result=StringCompare("a","b",true);
Alert(Result); 

Dans ce cas, la fonction renverra -1.

Maintenant, avant de continuer avec d'autres fonctions, il est nécessaire de faire une brève digression théorique.
  

Les chaînes vues par les gens et les ordinateurs

Ce qu'est une chaîne pour un homme est assez clair - c'est un texte composé de caractères. L'ordinateur, comparé à un être humain, est un peu plus simple dans sa structure, ne traitant que des nombres. L'ordinateur voit les images, les chaînes et tout le reste comme des nombres. Une chaîne est un tableau de nombres où un caractère correspond à un nombre, ou plutôt un code, un autre caractère à un autre code, etc. Ces codes sont appelés codes ASCII (abréviation de American Standard Code for Information Interchange). Nous utiliserons plus loin le terme ASCII, impliquant un ASCII étendu contenant 256 codes. Ainsi, on peut dire que "l'alphabet" informatique est composé de 256 caractères. Tout comme il existe différents alphabets pour différents peuples et langues, l'ordinateur possède différents jeux de caractères - des pages de codes. Les utilisateurs d'ordinateurs en Russie utilisent principalement Windows-1251, un codage de caractères qui comprend des caractères latins et cyrilliques, ainsi que des chiffres, des signes de ponctuation et d'autres symboles. La figure 1 montre la page de codes Windows-1251 :


Fig. 1. Page de codes Windows-1251.

Les 32 premiers caractères ne sont pas affichés, ce sont des caractères de contrôle. Ils ne sont pas affichés en tant que tels mais affectent l'affichage d'autres caractères, par exemple tabulation (code 9), saut de ligne (code 10), etc.

L'encodage utilisé pour représenter les textes dans les langues d'Europe centrale est Windows-1250 (Fig. 2) :


Fig. 2. Page de codes Windows-1250.

Veuillez noter qu'à partir du code 192 où la page de code 1251 comporte des lettres de l'alphabet russe, la page de code 1250 contient des lettres qui contiennent des signes diacritiques (lettres avec des signes diacritiques qui déterminent de légers changements dans la valeur sonore) dans les langues européennes.

256 caractères sont un très petit nombre. Des difficultés surviennent lorsqu'un texte doit être écrit en plusieurs langues, par exemple le russe et le français (comporte un grand nombre de signes diacritiques) ou l'anglais et l'arabe (les caractères sont très différents des caractères d'autres langues). Il existe également une écriture hiéroglyphique, comme en chinois et en japonais, qui comporte des milliers de caractères et les difficultés dans ce cas sont encore plus évidentes. Vous devrez peut-être encoder des caractères non inclus dans leur page de codes d'une autre manière. Ceux d'entre vous qui sont familiers avec HTML doivent connaître la possibilité d'insérer des caractères non standard dans une page HTML, par exemple le code &Agrave; est utilisé pour afficher À et &Aacute; rendre Á, etc.

Il est récemment devenu courant d'utiliser l'encodage Unicode où un caractère est encodé non pas sur un seul octet (nombre de 0 à 255), mais sur deux octets, totalisant ainsi 65536 caractères. Ce jeu de caractères comprend des lettres de tous les alphabets existant dans le monde et même les hiéroglyphes les plus courants comme le montre la figure 3 (les polices appropriées doivent toujours être installées sur votre ordinateur) :

Fig. 3. Les lettres de différents alphabets et hiéroglyphes. 

Fig. 3. Les lettres de différents alphabets et hiéroglyphes.

Les chaînes en MQL5 sont encodées en Unicode. En d'autres termes, un caractère dans une chaîne peut être représenté par un nombre de 0 à 65535. Les caractères avec des codes de 0 à 127 sont les mêmes en ASCII et Unicode. Les fichiers texte peuvent contenir des textes codés en ASCII ou Unicode et par conséquent la fonctionnalité MQL5 pour travailler avec des chaînes en ASCII et Unicode est différente.

 

Conversion d'une chaîne en tableau et retour en chaîne

Lorsque vous travaillez avec des chaînes, les fonctions StringLen(), StringFind(), StringSubst() et StringReplace() suffisent généralement à résoudre la majorité des tâches pratiques. Mais il peut y avoir des tâches beaucoup plus faciles à résoudre en utilisant des chaînes comme des nombres, telles que le cryptage, la compression de données, le calcul de valeurs de contrôle. Bien que des tâches de ce type ne soient pas traitées au quotidien, il est possible que vous deviez les résoudre un jour. Il existe également des tâches plus importantes qui nécessitent la conversion d'une chaîne en tableau, c'est-à-dire la transmission de paramètres de chaîne aux fonctions de l'API Windows (interfaces de programmation d'applications).

Pour convertir une chaîne en un tableau Unicode, nous utilisons la fonction StringToShortArray() et pour convertir en un tableau ASCII - la fonction StringToCharArray() :

string str="MetaTrader 5";
//--- converting the string to a Unicode array
short sha[];
StringToShortArray(str,sha);
//--- converting the string to a ASCII array
uchar cha[];
StringToCharArray(str,cha);
//--- flag the difference
bool Dif=false;
//--- compare the arrays element by element
for(int i=0;i<StringLen(str);i++)
  {
   if(sha[i]!=cha[i])
     {
      Dif=true;
     }
  }
//--- output the results
if(Dif) Alert("Different");
else    Alert("Identical");

Si les tableaux obtenus à l'aide des fonctions StringToShortArray() et StringToCharArray() dans l'exemple ci-dessus sont identiques, une fenêtre apparaîtra avec le message "Identical" et s'il y a des différences, le message indiquera "Different". Pour la chaîne "MetaTrader 5", les tableaux sont identiques car la chaîne se compose de caractères avec des codes de caractères jusqu'à 127.

Tout est un peu différent avec des codes de caractères supérieurs à 127. Les résultats de l'opération de la fonction StringToShortArray() seront toujours les mêmes partout, tandis que les résultats de l'opération de la fonction StringToCharArray() dépendront des paramètres régionaux du système d'exploitation.

Sous Windows 7, la langue du système peut être sélectionnée dans Panneau de configuration - Région et langue - Changer la langue d'affichage.

Regardez l'exemple suivant. Dans la page de code 1251, le code 192 correspond à la lettre "А" (première lettre de l'alphabet russe), tandis que le même code dans le codage 1250 correspond à la lettre "Ŕ" (l'une des lettres les plus connues de l'alphabet tchèque) . Lors de l'utilisation de la fonction StringToShortArray(), la lettre "А" aura toujours le code 1040, tandis que la lettre "Ŕ" code 340. Si le système est réglé sur la langue russe, lors de l'utilisation de la fonction StringToCharArray(), la lettre "А" correspondra au code 192 (correct), tandis que la lettre "Ŕ" correspondra au code 82 (latin "R"). Si toutefois le système est réglé sur la langue tchèque, la lettre "А" correspondra au code 63 (point d'interrogation) et la lettre "Ŕ" correspondra au code 192 (correct). Les caractères qui contiennent des signes diacritiques sont remplacés par des caractères latins similaires, tandis que les caractères moins courants sont remplacés par un point d'interrogation.

Veuillez noter la taille de la chaîne et les tableaux résultants :

int StrLen=StringLen(str);
int shaLen=ArraySize(sha);
int chaLen=ArraySize(cha);
//--- output the lengths
Alert(StringFormat("%i, %i, %i",StrLen,shaLen,chaLen));

Le nombre d'éléments des tableaux est supérieur de un au nombre de caractères de la chaîne. Cela est dû au fait que la fin de la chaîne est marquée par le caractère avec le code 0. Ce caractère n'est pas affiché dans la chaîne mais il est significatif pour l'ordinateur indiquant la fin de la chaîne affichée. L'échange de données ne se fait pas toujours avec un débit d'un octet (caractère) à la fois dans la quantité correspondant à la longueur de la chaîne mais le caractère avec le code 0 permet de déterminer la fin de la chaîne dans tous les cas. Le même zéro peut également poser des problèmes, par exemple un certain caractère peut être converti en caractère avec le code 0 lors du cryptage ou de l'application d'un algorithme de compression. Dans ce cas, si vous inversez la conversion d'un tableau en chaîne, la chaîne ne sera pas complète. Les tâches de ce type nécessitent l'utilisation d'astuces spéciales mais cela dépasse le cadre de cet article.

La conversion inverse d'un tableau en chaîne est possible à l'aide des fonctions ShortArrayToString() et CharArrayToString() :

//--- convert an array of Unicode codes to a string
short sha[]={85,110,105,99,111,100,101};
string str1=ShortArrayToString(sha);
//--- convert an array of ASCII codes to a string
uchar cha[]={65,83,67,73,73};
string str2=CharArrayToString(cha);
//--- output the results
Alert(str1+" "+str2);

En raison du code ci-dessus, la variable str1 stockera la chaîne "Unicode" et str2 stockera la chaîne "ASCII".

Il existe deux autres fonctions similaires : ShortToString() et CharToString(). Ils convertissent une seule variable de type short ou char en une chaîne composée d'un caractère. La fonction CharToString() a une grande valeur pratique. Un objet graphique qui vous permet d'afficher différents symboles, OBJ_ARROW, est ancré à l'axe des prix verticalement et à l'axe du temps horizontalement afin que les symboles se déplacent lorsque vous faites défiler le graphique. L'utilisation d'OBJ_LABEL avec la police Wingdings nous permet d'afficher différents symboles ancrés aux coordonnées sur l'écran nous permettant ainsi de créer divers panneaux d'information. Nous trouvons le symbole requis dans la table des symboles Wingdings, convertissons son code en une chaîne qui est ensuite affichée à l'aide de l'objet graphique OBJ_LABEL :

   ObjectCreate(0,"lbl",OBJ_LABEL,0,0,0);           // create the LABEL graphical object
   ObjectSetInteger(0,"lbl",OBJPROP_XDISTANCE,100);   // set the X-coordinate
   ObjectSetInteger(0,"lbl",OBJPROP_YDISTANCE,100);   // set the Y-coordinate
   ObjectSetInteger(0,"lbl",OBJPROP_FONTSIZE,20);     // set the size
   ObjectSetString(0,"lbl",OBJPROP_FONT,"Wingdings"); // set the Wingdings font
   string Icon=CharToString(37);                   // 37 - the bell
   ObjectSetString(0,"lbl",OBJPROP_TEXT,Icon);       // set the displayed text

À la suite de ce code, vous verrez une icône de cloche dans le graphique. La cloche restera à sa place pendant que vous faites défiler le graphique.

Deux autres fonctions pour travailler avec des codes de caractères sont StringGetCharacter() et StringSetCharacter(). Ils fonctionnent avec des codes Unicode. La fonction StringGetCharacter() permet d'obtenir le code du caractère à une position donnée dans la chaîne :

string str="L5";
//--- get the Unicode code of the character at the given position in the string
ushort uch1=StringGetCharacter(str,0);
ushort uch2=StringGetCharacter(str,1);
//--- output the results
Alert(StringFormat("%i, %i",uch1,uch2));

Suite à l'exécution de ce code, la variable uch1 stockera la valeur de 76 et uch2 stockera 53.

La fonction StringSetCharacter() permet de changer le code du caractère à une position donnée, ainsi que d'ajouter un caractère à la fin d'une chaîne :

string str="MQ5";
//--- replace the character at the given position in the string with the Unicode character corresponding to the passed code
StringSetCharacter(str,2,76);
Alert(str);
//--- add the Unicode character corresponding to the passed code to the end of the string
StringSetCharacter(str,3,53);
Alert(str);

Lors de l'exécution de ce code, la variable str au lieu de "MQ5" stockera d'abord "MQL" puis "MQL5".

 

Appel des fonctions API

Certaines fonctions API utilisent des paramètres de chaîne comme variables. Par exemple, la fonction pour applications tierces WinExec utilise un tableau de type uchar comme premier paramètre :

#import "kernel32.dll"
int WinExec(uchar &Path[],int Flag);
#import 

Essayons d'exécuter notepad.exe (Notepad), un programme Windows standard. Convertissez le chemin vers le bloc-notes en un tableau de type uchar :

string PathName="C:\\WINDOWS\\notepad.exe";
uchar ucha[];
StringToCharArray(PathName,ucha);
int x=WinExec(ucha,1); 

Cette opération de fonction doit entraîner l'ouverture de l'éditeur de texte du Bloc-notes.

Un autre exemple d'utilisation de paramètres de chaîne dans les fonctions API est la fonction MessageBoxW qui imprime un message dans la fenêtre à l'aide d'Unicode. Pour cette raison, nous passerons en paramètres des tableaux de type ushort :

#import "user32.dll"
int MessageBoxW(int hWnd,ushort &szText[],ushort &szCaption[],int nType);
#import

Utilisez maintenant cette fonction pour imprimer un message dans la fenêtre :

ushort arr[];
ushort capt[];
//--- convert
StringToShortArray("Programming in MQL5 for MetaTrader 5.",arr);
StringToShortArray("Message",capt);
//--- print the message
MessageBoxW(0,arr,capt,0);

À la suite de ce code, vous pourrez voir une fenêtre avec le message suivant : "Programmation en MQL5 pour MetaTrader 5".

Il est à noter que l'utilisation de tableaux de type ushort dans l'exemple ci-dessus n'est pas nécessaire et vous pouvez simplement passer des chaînes comme paramètres de la fonction :

#import "user32.dll"
int MessageBoxW(int hWnd,string szText,string szCaption,int nType);
#import
//+------------------------------------------------------------------+
//| Function for running the script                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   MessageBoxW(0,"Programming in MQL5 for MetaTrader 5","Message",0);
  }

Le résultat de ce code sera le même que ci-dessus. Cependant, vous ne pourrez pas utiliser des tableaux de type uchar comme paramètres de fonction, afin d'imprimer le message correct :

#import "user32.dll"
int MessageBoxW(int hWnd,uchar &szText[],uchar &szCaption[],int nType);
#import
//+------------------------------------------------------------------+
//| Function for running the script                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   uchar arr[];
   uchar capt[];
//--- convert
   StringToCharArray("Programming in MQL5 for MetaTrader 5.",arr);
   StringToCharArray("Message",capt);
//--- print the message
   MessageBoxW(0,arr,capt,0);
  }

Le code sera exécuté sans erreur et une fenêtre contextuelle apparaîtra mais le message sera déformé.

Pour les cas où il est nécessaire d'imprimer une chaîne dans l'encodage ASCII (par exemple si vous avez déjà un tableau de type uchar), il existe une fonction similaire, MessageBoxA. Pour afficher correctement le message, seuls les tableaux de type uchar doivent être passés à la fonction en tant que paramètres de chaîne. Importez maintenant cette fonction et appelez-la pour imprimer le message :

#import "user32.dll"
int MessageBoxA(int hWnd,uchar &szText[],uchar &szCaption[],int nType);
#import
//+------------------------------------------------------------------+
//| Function for running the script                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   uchar arr[];
   uchar capt[];
//--- convert
   StringToCharArray("Programming in MQL5 for MetaTrader 5",arr);
   StringToCharArray("Message",capt);
//--- print the message
   MessageBoxA(0,arr,capt,0);
  }

Et nous obtenons à nouveau le message correct "Programmation en MQL5 pour MetaTrader 5".

Fondamentalement, il existe 2 options pour la plupart des fonctions WinAPI qui fonctionnent avec des chaînes - l'option pour travailler avec des chaînes ASCII et l'option pour travailler avec des chaînes Unicode.

Pour pouvoir appeler les fonctions, activez l'utilisation des DLL dans les paramètres du terminal (Terminal - Menu principal - Outils - Options - Expert Advisors - Autoriser les importations de DLL) ou cochez "Autoriser les importations de DLL" dans l'onglet Dépendances de la fenêtre de propriétés lorsque exécuter un script, un Expert Advisor ou un indicateur. Spécifiez la propriété de script appropriée afin de permettre l'ouverture de la fenêtre de propriétés du script :

#property script_show_inputs

 

Entrée de paramètres illimitée

L'utilisateur saisit les paramètres dans la fenêtre des propriétés en les séparant par un point-virgule :

input string Lots="0.1; 0.2; 0.3; 0.5";

Nous devons convertir cette chaîne en un tableau de variables de type double.

En MQL5, une chaîne peut être fractionnée à l'aide de la fonction StringSplit(). Le premier paramètre passé à la fonction est une chaîne, le deuxième paramètre est le code ASCII du séparateur et le troisième paramètre passé est un tableau qui stockera les résultats de l'opération de la fonction. Il existe un moyen très simple de déterminer le code ASCII - vous devez mettre le caractère requis entre guillemets simples :

int Code='A';
Alert(IntegerToString(Code)); 

À la suite de ce code, la variable Code stockera la valeur de 65, étant le code ASCII du caractère latin "A".

Exprimons la solution de ce problème sous la forme d'une fonction distincte afin de pouvoir l'utiliser facilement en cas de besoin. Le premier paramètre passé à la fonction sera une chaîne et le deuxième paramètre sera un tableau renvoyé par référence. Le code de la fonction est fourni ci-dessous avec des commentaires détaillés et ne nécessite pas d'explications supplémentaires :

int ParamsToArray(string Str,double &Params[])
  {
//--- delete spaces at the ends
   StringTrimLeft(Str);
   StringTrimRight(Str);
//--- if the string is empty
   if(StringLen(Str)==0)
     {
      ArrayFree(Params); // free the array
      return(0);         // function operation complete
     }
//--- auxiliary array
   string tmp[];
//--- split the string
   int size=StringSplit(Str,';',tmp);
//--- delete spaces at the ends for each element of the array
   for(int i=0;i<size;i++)
     {
      StringTrimLeft(tmp[i]);
      StringTrimRight(tmp[i]);
     }
//--- delete empty elements from the array (user could accidentally 
//--- put the separator two times in a row or at the end of the string)
   for(int i=size-1;i>=0;i--)
     {
      if(StringLen(tmp[i])==0)
        {
         ArrayCopy(tmp,tmp,i,i+1);
         size--; // array size reduced
        }
     }
//--- scale the array according to the new size
   ArrayResize(tmp,size);
//--- replace commas with dots
   for(int i=0;i<size;i++)
     {
      StringReplace(tmp[i],",",".");
     }
//--- prepare the array to be returned
   ArrayResize(Params,size);
//--- convert all elements to the double type and fill the array to be returned 
   for(int i=0;i<size;i++)
     {
      Params[i]=StringToDouble(tmp[i]);
     }
//--- the function returns the number of parameters
   return(size);
  }

 

Conversion de chaînes en diverses variables

La fonction ParamsToArray() a utilisé la fonction StringToDouble() standard pour convertir la chaîne en variable de type double. La même fonction est utilisée pour la conversion au type flottant. Il existe des fonctions standard qui sont utilisées pour les conversions vers d'autres types de variables.

La fonction StringToInteger() convertit une chaîne en variable entière :

string Str="12345.678";
//--- convert the string to an integer
long Val=StringToInteger(Str);
//--- inverse convert and output the results
Alert(IntegerToString(Val));

À la suite de ce code, la variable Val stockera la valeur de 12345. La partie fractionnaire est simplement tronquée.

La fonction StringToTime() convertit une expression de chaîne de temps en la valeur numérique appropriée. Si vous ne précisez pas l'heure, la valeur par défaut sera "00:00" :

string Str1="2012.11.02 22:00";
string Str2="2012.01.01";
//--- convert the string expression of time to the datetime type
datetime DateTime1=StringToTime(Str1);
datetime DateTime2=StringToTime(Str2);

La fonction StringToColor() vous permet de convertir un nom de couleur (couleur Web standard) en la valeur numérique appropriée, ou de convertir une chaîne de composants RVB :

string Str1="clrYellow";
string Str2="255,255,0";
color Color1=StringToColor(Str1);
color Color2=StringToColor(Str2); 

Il existe un autre moyen de convertir les chaînes en date et en type de couleur. Il peut être utilisé lors de l'affectation de certaines valeurs à des variables :

datetime DateTime=D'2012.11.02 22:00';
color Color=C'255,255,0'; 

"D" est écrit avant l'expression de chaîne de date et la date elle-même est entourée de guillemets simples. L'expression de chaîne de couleur est précédée de la lettre "С" et les composants RVB sont entourés de guillemets simples et séparés par une virgule.

 

Activation des notifications

L'utilisateur entre une série de caractères qui permettent un certain type de notification. Cette méthode peut être utilisée pour activer diverses combinaisons de notifications. La notification d'alerte correspond à "à", la notification sonore à "s", la notification par e-mail à "e" et la notification push à "p". De plus, vous pouvez ajouter 1 ou 0 à la chaîne pour désigner la barre sur laquelle les signaux sont vérifiés (cela peut être utile dans les indicateurs). Le code est exprimé sous la forme d'une fonction dont le premier paramètre est une chaîne suivie de la variable Shift (numéro de la barre) renvoyée par référence et des variables de type bool correspondant aux différentes méthodes de notification. Le code est fourni avec des commentaires détaillés :

void NotifyOnOff(string Str,int &Shift,bool &Alerts,bool &Sounds,bool &EMail,bool &Push)
  {
//--- Convert the string to lower case to allow the user
//--- to use both lowercase and uppercase characters.
   StringToLower(Str);
//--- search for characters in the string
   Alerts=(StringFind(Str,"a")!=-1);    // "a" found
   Sounds=(StringFind(Str,"s")!=-1);    // "s" found
   EMail=(StringFind(Str,"e")!=-1);     // "e" found
   Push=(StringFind(Str,"p")!=-1);      // "p" found
//--- search for zero
   if(StringFind(Str,"0")!=-1) Shift=0;  // "0" found in the string
   else                       Shift=1; // by default
  }

Désormais, au lieu de cinq variables dans la fenêtre des propriétés, une seule suffira. 

 

Tampon de chaîne

Il nous reste à revoir trois fonctions standards : StringInit(), StringFill() et StringBufferLen().

La fonction StringInit() remplit une chaîne avec des caractères identiques dans le nombre spécifié :

string str;
StringInit(str,10,'|');
Alert(str); 

Suite à l'exécution de ce code, la variable str stockera la chaîne contenant "||||||||||". Le caractère est spécifié à l'aide de son code ASCII, c'est-à-dire que le caractère doit être entouré de guillemets simples.

La fonction StringFill() remplit une chaîne avec des caractères identiques sans modifier la taille de la chaîne. Dans la continuité de l'exemple précédent :

StringFill(str,'/');
Alert(str); 

Ensuite, la variable str stockera la chaîne contenant "//////////".

Essayons maintenant de remplir une chaîne avec un caractère de code 0 (fin de chaîne) :

StringFill(str,0); 
Vérifiez la taille de la chaîne :
int Length=StringLen(str);
Alert(IntegerToString(Length)); 

La taille est égale à 0 et le caractère avec le code 0 est au point de départ de la chaîne. Vérifiez la taille du tampon :

int BLength=StringBufferLen(str);
Alert(IntegerToString(BLength)); 

La taille du tampon est différente de 0 et dépasse la taille de la chaîne initiale. La mémoire allouée à la chaîne est plus que suffisante. Désormais, lors de l'attribution d'une valeur à la chaîne dans la plage de taille de tampon, la réallocation de mémoire ne sera pas nécessaire et la valeur sera attribuée très rapidement. Pour s'assurer que la taille de la mémoire tampon n'est pas réduite, la nouvelle valeur doit être ajoutée à la chaîne plutôt que de lui être affectée :

str+="a"; 

La longueur de la chaîne est désormais 1, tandis que la taille de la mémoire tampon est restée la même. De cette façon, vous pouvez quelque peu accélérer le traitement des chaînes. Une chaîne peut être effacée en insérant le caractère avec le code 0 au début de la chaîne :

StringSetCharacter(str,0,0); 

 

Conclusion

On pourrait penser que le sujet de l'article est d'importance mineure, peu pertinent par rapport à l'objectif principal du langage MQL5, à savoir développer des Expert Advisors et des indicateurs. Cependant, ce que nous avons obtenu ici est un article assez complet inspiré par un large éventail de fonctionnalités pour travailler avec des chaînes proposées par le langage. Il n'est pas improbable que dans de nombreux cas, lors de la programmation d'Expert Advisors et d'indicateurs, vous n'ayez pas à traiter de chaînes, mais cela peut être nécessaire un jour. Après avoir lu cet article, vous êtes prêt à utiliser les chaînes, au besoin, sans perdre de temps à étudier les fonctions. Vous pourrez facilement faire ce qui est nécessaire.

Rappelons les informations fournies dans l'article en classant les fonctions selon leur finalité, leur importance et leur fréquence d'utilisation.

  1. StringLen(), StringFind(), StringSubstr(), StringReplace() et StringSplit() sont des fonctions essentielles qui sont utilisées pour déterminer la longueur de la chaîne, la recherche de sous-chaîne, l'obtention et le remplacement d'une sous-chaîne, ainsi que le fractionnement d'une chaîne.
     
  2. StringTrimLeft(), StringTrinRight(), StringToLower() et StringToUpper() sont des fonctions auxiliaires très utiles qui sont utilisées pour supprimer les espaces aux extrémités et changer la casse.
     
  3. ColorToString(), DoubleToString(), EnumToString(), IntegerToString(), TimeToString() et StringFormat() sont des fonctions qui convertissent des variables numériques en chaîne.
     
  4. StringToColor(), StringToDouble(), StringToInteger(), StringToTime() et StringCompare() sont des fonctions qui convertissent une chaîne en variable numérique.
     
  5. StringAdd() et StringConcatenate() sont des fonctions que vous pouvez utiliser pour additionner et combiner des chaînes de manière efficace en termes d'espace.
     
  6. ShortToString(), ShortArrayToString(), StringToShortArray(), ainsi que CharToString(), CharArrayToString() et StringToCharArray() sont des fonctions permettant de travailler avec des chaînes sous forme de tableaux qui peuvent être utiles pour traiter des tâches nécessitant des manipulations de chaînes très complexes. À partir de la liste ci-dessus, nous pouvons souligner deux fonctions comme étant particulièrement importantes : 

    • CharToString() est utilisé pour travailler avec des objets graphiques avec la police Wingdings,
    • CharArrayToString() est utilisé pour préparer un paramètre de chaîne lors de l'appel des fonctions API.

  7. StringSetCharacter(), StringGetCharacter(), StringInit(), StringFill() et StringBufferLen() sont des fonctions secondaires.

 

Fichiers joints

  1. IncStrFunctions.mqh contient les fonctions Trim(), StringFindRev(), TrimL(), TrimR(), ParamsToArray() et NotifyOnOff().
  2. eMultiLanguageMessage.mq5 est un exemple d’un Expert Advisor proposant des messages dans différentes langues.

Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/585

Comment tester un robot de trading avant d’acheter Comment tester un robot de trading avant d’acheter
L’achat d’un robot de trading sur MQL5 Market présente un avantage distinct par rapport à toutes les autres options similaires - un système automatisé proposé peut être testé en profondeur directement dans le terminal MetaTrader 5. Avant d’acheter, un Expert Advisor peut et doit être exécuté avec soin dans tous les modes défavorables du Strategy Tester intégré pour avoir une compréhension complète du système.
Apprentissage automatique : Comment les machines à vecteurs de support peuvent être utilisées dans le trading Apprentissage automatique : Comment les machines à vecteurs de support peuvent être utilisées dans le trading
Les machines à vecteurs de support sont utilisées depuis longtemps dans des domaines tels que la bio-informatique et les mathématiques appliquées pour évaluer des ensembles de données complexes et extraire des modèles utiles pouvant être utilisés pour classer les données. Cet article examine ce qu'est une machine à vecteurs de support, comment elle fonctionne et pourquoi elle peut être si utile pour extraire des motifs complexes. Nous étudions ensuite comment ils peuvent être appliqués au marché et potentiellement utilisés pour conseiller sur le trading. À l'aide de l'outil d'apprentissage par machine à vecteur de support, l'article fournit des exemples concrets qui permettent aux lecteurs d'expérimenter leur propre trading.
Comment devenir un fournisseur de signaux pour MetaTrader 4 et MetaTrader 5 Comment devenir un fournisseur de signaux pour MetaTrader 4 et MetaTrader 5
Voulez-vous offrir vos signaux de trading et gagner de l’argent ? Inscrivez-vous sur le site MQL5.com en tant que vendeur, spécifiez votre compte de trading et proposez aux traders un abonnement pour copier vos transactions.
Modifier les paramètres de l'Expert Advisor à partir du panneau de l'utilisateur "On The Fly" Modifier les paramètres de l'Expert Advisor à partir du panneau de l'utilisateur "On The Fly"
Cet article fournit un petit exemple illustrant la mise en œuvre d'un Expert Advisor dont les paramètres peuvent être contrôlés depuis le panneau utilisateur. Lors de la modification des paramètres "On The Fly", l'Expert Advisor écrit les valeurs obtenues à partir du panneau d'informations dans un fichier pour les lire davantage à partir du fichier et les afficher en conséquence sur le panneau. Cet article peut être pertinent pour ceux qui tradent manuellement ou en mode semi-automatique.