Le basi sulla programmazione in MQL5: Stringhe
Introduzione
Le stringhe, o meglio le variabili di stringa, vengono utilizzate per memorizzare i dati dei caratteri, ovvero il testo:
string str="Any text";
Il linguaggio MQL5 offre un'ampia gamma di funzionalità intuitive per lavorare con le stringhe. Nella programmazione di Expert Advisor e indicatori, le stringhe vengono utilizzate principalmente per generare messaggi informativi. Negli indicatori, questi possono essere messaggi riguardanti il soddisfacimento di determinate condizioni (es. segnali di trading), mentre negli Expert Advisor possono riportare i risultati dell'attività di trading. Quando viene eseguito, un Expert Advisor, uno script o un indicatore può controllare i parametri impostati dall'utente e stampare una notifica nel caso in cui i parametri impostati non siano validi. Oltre alle notifiche, a volte potresti visualizzare messaggi di richiesta che forniscono consigli sulle impostazioni dei parametri. In generale, quando si programma in MQL5, le stringhe offrono soprattutto facilità d'uso.
Inoltre, le stringhe sono essenziali quando si lavora con i file. La scrittura e la lettura dei dati dai file viene eseguita utilizzando variabili stringa. Chiaramente si può optare per un altro modo di lavorare con i file, un metodo binario che prevede la lettura e la scrittura di variabili numeriche e array. Tuttavia, se la quantità di dati non è troppo grande, è meglio utilizzare file di testo e stringhe. In questo caso, il funzionamento del programma è più chiaro per l'utente e il processo di sviluppo del programma è più semplice, fornendo un controllo immediato dei dati. I dati del file di testo hanno lo stesso aspetto dei dati all'interno del programma.
L'uso di stringhe può ampliare notevolmente le funzionalità del programma associate all'immissione dei dati (parametri) nei casi in cui il numero di parametri richiesto non è noto in anticipo (ad es. dimensioni dei lotti per la media degli accumuli). In tal caso, i valori possono essere scritti in un'unica stringa separata da un separatore, ad esempio punto e virgola:
input string Lots="0.1; 0.2; 0.3; 0.5";
Quindi, quando si inizializza l'Expert Advisor, la stringa viene divisa e viene riempita una matrice di valori numerici. Sfortunatamente, è impossibile superare tali parametri di stringa in fase di ottimizzazione, ovvero impostare il valore iniziale e finale insieme al valore del passo. In alcuni casi, potrebbe forse essere preferibile utilizzare un numero elevato di variabili numeriche nella finestra delle proprietà. Ma poiché il loro numero potrebbe essere illimitato, potremmo affrontare un problema di convenienza e scopo (se è richiesta la possibilità di ottimizzazione).
Potrebbero esserci altri casi in cui l'ottimizzazione di un parametro non è necessaria, ad esempio l'abilitazione delle notifiche. MQL5 supporta vari metodi di notifica utente: notifiche sonore, notifiche pop-up, notifiche e-mail e notifiche push. È possibile creare un'opzione di tipo bool per ciascuna di queste notifiche nella finestra delle proprietà (richiede almeno quattro variabili) o ridurre il numero di variabili a una variabile stringa.
Se devi abilitare le notifiche sonore, scrivi "s" (suono). Se hai bisogno anche di notifiche e-mail, aggiungi "e". Pertanto, puoi abilitare qualsiasi combinazione di notifiche utilizzando una sola variabile. Per un Expert Advisor, il numero di parametri esterni è di scarsa importanza. È solo una questione di facilità d'uso.
D'altra parte, quando si sviluppano indicatori si dovrebbe cercare di ridurre il numero di parametri esterni. È molto probabile che l'indicatore venga chiamato da un Expert Advisor o da un altro indicatore utilizzando le funzioni iCustom() o IndicatorCreate() il cui numero di parametri è limitato. Il che significa che iCustom() ha solo 64 parametri e la dimensione dell'array di parametri della funzione IndicatorCreate( ) è di 64 elementi. L'uso di stringhe può quindi essere di grande valore pratico.
Questo articolo esaminerà tutte le funzioni MQL5 standard per lavorare con le stringhe. Creeremo anche alcune utili funzioni personalizzate.
Dichiarazione di una variabile stringa
Come qualsiasi altro tipo di variabile, le variabili stringa possono essere dichiarate:
string str;
o può venir assegnato loro un valore al momento della dichiarazione (inizializzato a un valore): string str="Any text";
Non ci sono restrizioni sulla lunghezza della stringa. Una stringa lunga può per comodità essere suddivisa in diverse sottostringhe:
string str= "A long string can be " "split into several " "substrings"; //--- output the results Alert(str);
Quando inizializzata in questo modo, la variabile str avrà la stringa contenente "Una stringa lunga può essere divisa in più sottostringhe".
Saltando un po' più avanti, dovremmo notare che il valore di una variabile stringa dichiarata senza parametri non è identico a una stringa vuota:
string str="";
Puoi vederlo di persona:
string str1; string str2=""; //--- output the comparison results Alert(str1==str2);
Quando si esegue questo codice, verrà visualizzata una finestra di avviso "falso". La variabile stringa non inizializzata ha il valore NULL che non è lo stesso di una stringa vuota "". Dovresti tenerlo a mente! Quando lavoriamo con le stringhe, molto spesso dobbiamo controllare se una stringa è vuota. Pertanto dovresti attenerti alla regola di inizializzare tutte le stringhe con una stringa vuota "" o controllarle per non essere uguali a "" e non uguali a NULL:
if(str!="" && str!=NULL) { //--- some operation with a string }
Il primo metodo è più consigliabile in quanto semplifica la condizione di controllo.
Puoi fare lo stesso quando controlli la dimensione di una variabile. Per determinare la dimensione, usiamo la funzione StringLen():
if(StringLen(str)!=0) { //--- some operation with a string }
Concatenazione di stringhe
L'operazione principale e più comune che puoi eseguire quando lavori con le stringhe è la loro concatenazione, ad esempio la creazione di frasi usando le parole. La concatenazione viene implementata utilizzando il segno "+":
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);
Dopo l'esecuzione di questo codice la variabile str4 conterrà "Programmazione in MQL5", mentre la variabile str5 conterrà "Programmazione per MetaTrader 5". L'esempio precedente ha dimostrato come sia possibile concatenare due stringhe, con la stringa risultante assegnata a un'altra variabile.
Una stringa aggiuntiva è molto spesso concatenata con la stringa 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);
Dopo l'esecuzione di questo codice la stringa str1 conterrà "Programmazione in MQL5 per MetaTrader 5". L'esempio precedente ha dimostrato come sia possibile concatenare stringhe con la stringa principale str1, con il risultato assegnato a quest'ultima. Le stesse operazioni possono essere scritte in modo molto più semplice:
str1+=str2; str1+=str3;o
str1+=str2+str3;
Il segno "+" a sinistra di "=" significa che l'espressione a destra di "=" viene aggiunta alla variabile str1.
Puoi anche aggiungere una stringa all'inizio della stringa principale. Questo può essere implementato come mostrato nel penultimo esempio: la stringa principale viene aggiunta alla stringa aggiuntiva e la stringa risultante viene assegnata alla variabile 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);
La seguente frase: "Programmazione in MQL5 per MetaTrader 5" sarà ora nella variabile str3. Puoi implementare lo stesso usando una singola stringa:
str3=str1+" "+str2+" "+str3;In alcuni casi è possibile eseguire la concatenazione utilizzando "," (virgola). È possibile quando si chiamano le funzioni Alert(), Print() o Comment():
Print(str1," ",str2," ",str3);
I risultati finali saranno in questo caso identici all'utilizzo del segno "+":
Print(str1+" "+str2+" "+str3);
Il simbolo "," infatti non concatena le stringhe. Una virgola è un separatore di parametri in tutte le funzioni. Vale anche per le funzioni Alert(), Print() e Comment(). Queste funzioni hanno un parametro obbligatorio e molti parametri facoltativi. I parametri vengono in effetti passati alla funzione in cui sono concatenati. Il numero massimo di parametri è 64.
Possiamo vedere qualcosa di simile quando scriviamo una stringa in un file usando la funzione FileWrite(). Tuttavia, se si apre un file in modalità FILE_CSV (con separatori di campo), le virgole verranno sostituite con il carattere separatore specificato all'apertura del file (se il separatore non è specificato, per impostazione predefinita viene utilizzata la tabulazione). Quando si apre un file in modalità FILE_TXT senza specificare il separatore, i risultati dell'utilizzo del segno "+" e "," saranno gli stessi:
//--- 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);
Dopo aver eseguito questo codice, il file 1.txt conterrà "1 2 3", mentre il file 2.txt conterrà "123" (i file sono stati aperti in modalità FILE_CSV). 3.txt e 4.txt avranno contenuto identico: "123" (aperto in modalità FILE_TXT). Questo articolo non è incentrato sulle operazioni sui file. Pertanto, se c'è qualcosa nell'ultimo esempio che non ti sembra chiaro, non importa perché non influenzerà la tua comprensione del materiale esposto più avanti in questo articolo. Basta notare che l'uso di "+" e "," non produce sempre lo stesso effetto quando si aggiungono stringhe.
Oltre al segno "+", MQL5 fornisce funzioni speciali per l'aggiunta di stringhe: StringAdd() e StringConcatenate(). Secondo la descrizione di queste funzioni in MQL5 Reference, esse ci consentono di sommare le stringhe in modo più efficiente in termini di spazio (in termini di memoria di lavoro occupata) e più veloce. La funzione StringAdd() ci permette di aggiungere una stringa a un'altra:
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);
Dopo l'esecuzione di questo codice la variabile str1 avrà la stringa contenente "Programmazione in MQL5 per MetaTrader 5".
La funzione StringConcatenate() consente di combinare contemporaneamente più stringhe. Il primo parametro passato alla funzione è la variabile della stringa a cui verranno aggiunte ulteriori stringhe elencate. Il numero massimo di parametri che puoi passare alla funzione è 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);
Dopo aver eseguito questo codice, la variabile str1 conterrà anche "Programmazione in MQL5 per MetaTrader 5".
Conversione di varie variabili in una stringa
Quando si genera una stringa di messaggio, molto spesso è necessario aggiungere valori di variabili numeriche. Per convertire i valori delle variabili intere (char, uchar, bool, short, ushort, int, uint, color, long, ulong, datetime) in una stringa, utilizziamo la funzione IntegerToString():
int x=1; string str="x = "+IntegerToString(x);
Quando si converte una variabile di tipo bool, una stringa restituita conterrà "0" (falso) o "1" (vero). Allo stesso modo, se si convertono variabili di tipo color o datetime, una stringa restituita conterrà un'espressione numerica di colore o data (ad esempio "65535" per il colore giallo di clrYellow o "1325376000" per la data come segue: 2012.01.01 00:00).
Per convertire le variabili real (double, float) in una stringa, utilizziamo la funzione DoubleToString(). Il secondo parametro di questa funzione determina la precisione (il numero di cifre decimali):
double x=1.23456; string str1="x = "+DoubleToString(x,2); string str2="x = "+DoubleToString(x,3);
A seguito dell'esecuzione di questo codice, la variabile str1 conterrà la stringa "1.23", mentre la variabile str2 conterrà la stringa "1.235". Il troncamento al numero di cifre specificato viene eseguito utilizzando le regole di arrotondamento matematiche.
La funzione TimeToString() viene utilizzata per convertire data e ora in una stringa di formato standard (facilmente comprensibile dagli esseri umani):
datetime tm=TimeCurrent(); // Current time string str1=IntegerToString(tm); string str2=TimeToString(tm);
Dopo l'esecuzione di questo codice la variabile str1 conterrà la stringa con un'espressione numerica di tempo (il numero di secondi trascorsi dal 1 gennaio 1970), mentre la variabile str2 conterrà l'ora formattata, ad es. "2012.11.02 22:00" (anno, mese, giorno, ora, minuto).
Quando si chiama la funzione TimeToString(), è disponibile un'opzione per specificare il formato della data e dell'ora. Le opzioni disponibili sono:
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 un'ottima funzionalità utile per creare enumerazioni che vengono visualizzate nella finestra delle proprietà del programma come elenchi a discesa di opzioni. I valori di tali variabili possono anche essere convertiti in una stringa utilizzando la funzione EnumToString(). Di seguito è riportato il codice dello script che dimostra il funzionamento di questa funzione:
//+------------------------------------------------------------------+ //| 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); }Esiste una possibilità simile che consente di convertire le variabili di colore. Puoi convertire il valore del colore nel nome del colore usando la funzione ColorToString():
color ColorValue=clrRed; string str=ColorToString(ColorValue,true);
Dopo aver eseguito questo codice, la variabile str memorizzerà la stringa contenente "clrRed". Se il secondo parametro è impostato su false, la funzione restituirà la stringa con i valori delle componenti RGB (rosso, verde e blu):
color ColorValue=clrRed; string str=ColorToString(ColorValue,false);
In questo caso, la stringa memorizzata nella variabile str sarà "255,0,0". Se il colore con cui si ha a che fare è non standard (non definito sulla tavolozza dei colori web e quindi senza nome), la funzione ColorToString() può essere utilizzata per restituire la stringa con i valori dei componenti indipendentemente dal valore del secondo parametro.
Esiste ancora un altro metodo per convertire le variabili utilizzando il casting di tipo:
int x=123; string str=(string)x;
Quando una variabile di tipo bool viene convertita in questo modo, il valore della stringa sarà " true" o "false":
bool x=true; string str=(string)x;
La conversione delle variabili di tipo double e float dovrebbe essere il più precisa possibile, consentendo di eliminare solo zeri nella parte frazionaria:
double x1=0.1; double x2=0.123; string str1=(string)x1; string str2=(string)x2;
Dopo l'esecuzione di questo codice la variabile str1 memorizzerà il valore stringa di "0.1" e la variabile str2 conterrà il valore stringa di "0.123".
Uscita caratteri speciali
Quando si inizializza una variabile stringa su un valore, la stringa assegnabile deve essere scritta tra virgolette doppie in modo che il compilatore possa distinguere la stringa dal codice del programma. Per poter inserire le virgolette all'interno della stringa, è necessario specificare il fatto che i segni non vengono utilizzati per il loro scopo normale (come caratteri che separano una stringa da un codice) ma piuttosto come parte di una stringa. Per implementare ciò, inserisci una barra rovesciata "\" subito prima delle virgolette:
string str1="Simple text"; string str2="\"Text in quotes\""; //--- output the results Alert(str1); Alert(str2);
Poiché anche la barra rovesciata è considerata uno dei caratteri speciali, è necessario inserire un'altra barra rovesciata prima di essa per implementare l'output della barra rovesciata in una stringa:
string str="\\"; Alert(str);
Dopo aver eseguito questo codice, l'unico carattere che la stringa conterrà sarà "\".
Una stringa può anche contenere un carattere di tabulazione orizzontale rappresentato da "\t":
string str="Column-1\tColumn-2\tColumn-3"; Alert(str);
In questo caso, la variabile str avrà la stringa contenente "Colonna-1 Colonna-2 Colonna-3".
Un testo può anche essere stampato con interruzioni di riga, diviso in più righe usando "\n":
string str="Line-1\nLine-2\nLine-3"; Alert(str);
Qui, come risultato dell'esecuzione della funzione Alert(), avrai tre righe di testo.
Quando si stampa utilizzando le funzioni Alert() e MessageBox(), così come quando si scrive su un file, è possibile utilizzare sia "\t" che "\n". Tuttavia, quando si stampa su un commento del grafico (la funzione Comment()), solo "\n" si applica come carattere di ritorno a capo, mentre il carattere di tabulazione "\t" viene ignorato. Quando l'output viene eseguito utilizzando la funzione Print(), "\n" si applica come prima (ogni parte di una stringa viene emessa in una riga separata del journal) e "\t" viene sostituito con uno spazio come nel file di registro che memorizza tutti i messaggi in uscita utilizzando la funzione Print().
Formattazione delle stringhe basata su pattern
Quando si formatta una stringa per l'output, potrebbe essere necessario includere in essa dei valori di diverse variabili numeriche. Ciò può essere ottenuto sommando stringhe e convertendo variabili numeriche in stringhe. Tuttavia in questo caso, qualora fossero necessarie modifiche al programma, la stringa di codice che costruisce un messaggio sarebbe troppo lunga e difficile da comprendere e modificare:
//--- 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);
Lo stesso compito può essere risolto in un modo molto più semplice utilizzando la funzione StringFormat(). Il primo parametro passato a questa funzione è un modello di messaggio, con i posti indicati per l'inserimento delle variabili e formato di output preimpostato. È seguito dall'enumerazione di tutte le variabili nell'ordine in cui appaiono nel modello:
//--- 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);
I posti per l'inserimento delle variabili sono contrassegnati con "%" seguito da "i", che nell'esempio sopra indica che le variabili devono essere emesse come numeri interi. O meglio, "i" sta per variabili carattere intere (char, short, int, color), mentre usiamo "u" per variabili intere senza segno (uchar, bool, ushort, uint). Per le variabili del tipo di dati long, ulong e datetime, è necessario specificare anche la dimensione della variabile inserendo "I64" prima del tipo:
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);Come risultato di questo codice, vedrai una finestra pop-up con valori variabili.
Il formato dei numeri reali è indicato da "f":
double Percents=5.5; //--- real number as a string string str=StringFormat("Percents = %f",Percents); //--- output the results Alert(str);
Dopo aver eseguito questo codice, la variabile str memorizzerà la seguente stringa: "Percentuali = 5.500000". La precisione di output predefinita è di sei cifre decimali. È possibile impostare il numero richiesto di cifre decimali:
string str=StringFormat("Percents = %.2f",Percents);
A tal fine, metti un punto che denota un simbolo decimale seguito immediatamente dal numero di posizioni decimali, ad es. 2 come nell'esempio sopra. In questo caso la variabile str conterrà la stringa come segue: "Percentuali = 5,50". Questa opzione di formattazione è completamente identica alla funzione DoubleToString().
Puoi specificare la lunghezza totale di un numero scrivendo "0" e un numero che determini la lunghezza del numero a portata di mano subito dopo "%" e poi specificare il numero di cifre decimali (se necessario):
string str=StringFormat("Percents = %06.2f",Percents);
Qui abbiamo una lunghezza totale di 6 cifre, una delle quali verrà utilizzata per la virgola e altre due rappresenteranno due posizioni decimali. Pertanto, la stringa memorizzata nella variabile str sarà "Percents = 005.50".
Se è necessario emettere il segno di percentuale "%" in un messaggio, è necessario scriverlo due volte di seguito, ad esempio "%%", poiché uno di essi verrà utilizzato per indicare i punti in cui inserire i valori:
string str=StringFormat("Percents = %06.2f%%",Percents);
In questo caso, la variabile str conterrà "Percentuale = 005,50%".
Puoi anche determinare la lunghezza di un numero quando emetti variabili intere:
int Variable=123; //--- integer as a string with a set output length string str=StringFormat("Variable = %05i",Variable); //--- output the results Alert(str);
Dopo l'esecuzione di questo codice la variabile str memorizzerà la seguente stringa: "Variabile = 00123".
Se il numero di cifre specificato è inferiore al numero di cifre nel numero, l'output verrà comunque eseguito correttamente:
string str=StringFormat("Variable = %02i",Variable);
Qui, la variabile str conterrà la stringa come segue: "Variabile = 123", ovvero il numero di output avrà 3 cifre nonostante il fatto che la lunghezza specificata sia 2.
I numeri reali possono essere emessi usando la notazione scientifica (mantissa di sei cifre decimali e potenza) per la quale usiamo il carattere "e":
double Variable=123.456; //--- real number as a string in scientific notation string str=StringFormat("Variable = %e",Variable); //--- output the results Alert(str);
Dopo aver eseguito questo codice, la variabile str conterrà "1.234560e+002". Puoi anche usare la "E" maiuscola il cui effetto è simile alla "e" minuscola, con la "E" maiuscola che sostituisce la "e" minuscola in una stringa formattata.
C'è ancora un altro modo per formattare i numeri reali - usando "g" per cui possono essere emesse solo sei cifre (escluso qualsiasi punto decimale). Se la lunghezza della parte intera di un numero supera le sei cifre, il numero verrà emesso utilizzando la notazione scientifica:
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);
Nell'esempio sopra, la variabile str1 conterrà "12.3457" e la variabile str2 conterrà "1.23457e+006". L'effetto sarà lo stesso se si usa invece la "G" maiuscola, con l'unica differenza che nell'output la "g" minuscola verrà sostituita con la "G" maiuscola.
La funzione StringFormat() permette di trasformare i formati di rappresentazione numerica, cioè di convertire i numeri del sistema decimale nel sistema ottale o esadecimale. Per convertire un numero nel sistema ottale, è necessario utilizzare il carattere "o":
int Variable=17; //--- real number as a string in the octal system string str=StringFormat("Variable = %o",Variable); //--- output the results Alert(str);
Dopo l'esecuzione di questo codice, la variabile str memorizzerà la stringa come segue: "Variabile = 21" (8*2+1=17).
"x" o "X" viene utilizzato per convertire un numero nel sistema esadecimale. In tal caso, se si utilizza la "x" minuscola, un numero di sistema esadecimale sarà composto da lettere minuscole, oppure maiuscole se si utilizza la "X" maiuscola:
color Variable=clrBlue; //--- real number as a string in the hexadecimal system string str=StringFormat("Variable = %x",Variable); //--- output the results Alert(str);
Dopo aver eseguito questo codice, la variabile str conterrà "Variable = ff0000".
Allo stesso modo, puoi riconvertire un numero del sistema esadecimale nel sistema decimale usando il carattere "d":
int Variable=0x0000ff; //--- real number as a string in the decimal system string str=StringFormat("Variable = %d",Variable); //--- output the results Alert(str);
Dopo l'esecuzione di questo codice, la stringa che la variabile str memorizzerà sarà "Variable = 255".
Il carattere "s" può essere utilizzato per emettere variabili stringa:
string Variable="text"; //--- output the string variable string str=StringFormat("Variable = %s",Variable); //--- output the results Alert(str);
Non appena si esegue il codice sopra, la stringa contenente "Variable = text" verrà memorizzata nella variabile str.
A volte potrebbe essere necessario allineare i numeri durante l'output in una colonna, dato che i numeri negativi si spostano a causa del segno "-". Per allineare i numeri positivi con quelli negativi, dovresti aggiungere uno spazio all'inizio della stringa, subito dopo "%". In questo caso, i numeri negativi verranno emessi senza spazio a differenza dei numeri positivi che avranno uno spazio all'inizio:
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);
A seguito dell'esecuzione di questo codice, la variabile str1 conterrà "Variable1= 01" (la stringa con uno spazio), mentre la variabile str2 memorizzerà la stringa come segue: "Variable2=-01".
Ci sono altre due funzioni simili a StringFormat(). Questi sono PrintFormat() e printf() che sono assolutamente identici in termini di azione. La loro unica differenza rispetto alla funzione StringFormat() è che inviano il testo al journal in modo simile alla funzione Print().
In effetti, la funzione StringFormat() offre molte più funzionalità, mentre il materiale fornito sopra rappresenta il minimo richiesto per risolvere la maggior parte dei problemi relativi alla formattazione dei numeri per l'output.
Messaggi in diverse lingue
La funzione StringFormat() ti dà l'opportunità di migliorare il tuo programma con una funzionalità molto utile che fornisce la stampa di messaggi in diverse lingue, a seconda della lingua dell'interfaccia impostata nel terminale.
Puoi scoprire quale lingua dell'interfaccia è impostata chiamando la funzione TerminalInfoString() con l'identificatore TERMINAL_LANGUAGE. Quando si esegue un programma, prepariamo una stringa di formato in base alla lingua dell'interfaccia e quindi la utilizziamo nel programma. Di seguito è riportato un modello di un expert advisor con la suddetta funzionalità implementata:
//--- 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 calcola la somma di due numeri casuali ed emette il messaggio relativo alle sue azioni, ad es "1 più 2 fa 3".
Questo è tutto per quanto riguarda l'output delle stringhe. Passeremo ora a manipolazioni di stringhe leggermente più complesse, ma più interessanti.
Funzioni chiave per lavorare con le stringhe
Se una stringa viene immessa tramite la finestra delle proprietà del programma o letta da un file, potrebbe contenere spazi non necessari. Possono apparire a causa di una disattenzione dell'utente o per comodità. Prima di utilizzare la stringa in qualsiasi modo, è consigliabile eliminare gli spazi all'estremità sinistra e destra. A questo scopo, MQL5 offre due funzioni: StringTrimLeft() (elimina gli spazi all'estremità sinistra) e StringTrimRight() (elimina gli spazi all'estremità destra). Oltre agli spazi, queste funzioni rimuovono anche i caratteri di tabulazione e di nuova riga. Quando si lavora con le stringhe, spesso è necessario eliminare gli spazi a entrambe le estremità contemporaneamente, quindi una funzione che svolga questa azione automaticamente sarebbe molto utile:
string Trim(string Str) { StringTrimLeft(Str); StringTrimRight(Str); return(Str); }
Quando si immettono numeri reali, l'utente può spesso inserire una virgola invece di un punto. Pertanto, quando si lavora con numeri reali, è necessario fornire la possibilità di utilizzare sia il punto che la virgola come simbolo decimale. Per sostituire una stringa con un'altra, utilizziamo la funzione StringReplace():
string str="123,456"; //--- replace a comma with a dot StringReplace(str,",","."); double Value=StringToDouble(str); //--- output the results Alert(DoubleToString(Value));
Se non sostituisci "," con ".", la parte frazionaria del numero verrà troncata durante la conversione di una stringa in un numero.
In alcuni casi, potrebbe essere necessario sostituire una serie di spazi con uno spazio. Per fare ciò, devi prima sostituire i caratteri di tabulazione con uno spazio e quindi sostituire due spazi con uno finché non rimane solo spazio:
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 funzione StringReplace() restituisce il numero di sostituzioni effettuate o -1 in caso di errore. Quindi il ciclo continua con la funzione che restituisce un valore maggiore di zero fino a quando tutte le serie di spazi vengono sostituite con uno spazio che viene lasciato in ogni singolo caso. Il corpo del ciclo non contiene alcun codice. Quando controlliamo la condizione del ciclo ad ogni iterazione, chiamiamo la funzione StringReplace().
La funzione StringReplace() ci permette di sostituire sottostringhe di diversa lunghezza:
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);
Quando si esegue questo codice, la variabile str dopo la prima sostituzione avrà la stringa contenente "Programmazione per MetaTrader 5" e "Programmazione in MQL5!" dopo la seconda sostituzione.
La funzione StringFind() viene utilizzata per cercare una sottostringa. Restituisce l'indice della prima occorrenza della sottostringa in una stringa. Il primo parametro passato alla funzione è una stringa in cui viene eseguita la ricerca. Il secondo parametro determina la sottostringa di destinazione, mentre il terzo parametro (opzionale) può determinare la posizione in cui inizia la ricerca. Se il terzo parametro non è specificato, la funzione opera come se il suo valore fosse 0, cioè la ricerca inizia proprio all'inizio della stringa. Troviamo la posizione della sottostringa "5" nella stringa "Programmazione in MQL5 per 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));
Dopo l'esecuzione di questo codice, il valore della variabile Pos sarà 23. La sottostringa "5" si verifica due volte in totale, ma la funzione restituisce solo la posizione della prima occorrenza. Se conti la posizione semplicemente guardando la stringa, otterrai 24. Il fatto è che la funzione inizia a contare da zero, anziché da uno. Se la sottostringa di destinazione non viene trovata nella stringa, la funzione restituisce -1.
Di tanto in tanto, potrebbe essere necessario trovare una posizione dell'ultima occorrenza della sottostringa. A tal fine, dovremo scrivere una funzione personalizzata, StringFindRev(). Inizieremo con la ricerca della prima occorrenza della sottostringa, quindi sposteremo l'inizio della ricerca in base alla posizione trovata, ecc. in un ciclo:
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); }Proviamo ad usare questa funzione:
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);
Dopo aver eseguito questo codice, la variabile Pos avrà il valore di 40.
La funzione StringSubstr() viene utilizzata per ottenere una sottostringa di una determinata lunghezza da una determinata posizione. Ottieni la sottostringa della lunghezza di 1 dalla posizione 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);
La cifra risultante è "5".
Ora che abbiamo considerato le funzioni principali, usiamole per scrivere una funzione utile per eliminare un determinato elenco di caratteri da una stringa. La funzione riceve la stringa di origine e una stringa che rappresenta un elenco di caratteri da eliminare dalla stringa di origine.
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 funzione elimina la tabulazione e il carattere di nuova riga, nonché uno spazio e un punto e virgola ";" per impostazione predefinita.
La stessa funzione per l'eliminazione all'estremità destra:
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)); }
Questa funzione elimina anche la tabulazione e il carattere di nuova riga, nonché uno spazio e un punto e virgola ";" per impostazione predefinita. Può rivelarsi utile durante la lettura di file CSV. All'interno di questi file, potrebbero esserci molti separatori di campo (di solito punti e virgola ";") all'estremità destra di una stringa.
Lettere maiuscole e minuscole, ad es "А" e "а" non sono visti come diversi nel significato dagli esseri umani, mentre i computer li trattano come due caratteri completamente diversi. Se scrivi "eurusd" invece di "EURUSD" quando richiedi i dati di mercato utilizzando la funzione SymbolInfoDouble(), la funzione non restituirà il valore richiesto. È molto probabile che ciò accada quando si immette il nome del simbolo nella finestra delle proprietà. Per cambiare il caso in MQL5, puoi usare la funzione StringToLower() (per cambiare in minuscolo) e la funzione StringToUpper() (per cambiare in maiuscolo):
string str="EuRuSd"; string str1=str; string str2=str; //--- change the case of strings StringToUpper(str1); StringToLower(str2); //--- output the results Alert(str1," ",str2);
A seguito dell'esecuzione di questo codice, la variabile str1 memorizzerà la stringa che contiene "EURUSD", mentre la variabile str2 avrà la stringa contenente "eurusd".
Se ciò di cui hai bisogno è confrontare le stringhe senza prendere in considerazione il loro caso, la funzione StringCompare() sarà la soluzione migliore. I primi due parametri della funzione sono le stringhe per il confronto. Il terzo parametro determina se le stringhe devono essere confrontate, tenendo conto (vero) o meno (falso) del fatto che siano maiuscole o minuscole:
int Result=StringCompare("eurusd","EURUSD",false); Alert(Result);
Se la funzione restituisce 0, le stringhe sono identiche. La funzione può restituire -1 se la prima stringa è minore della seconda, oppure 1 se la prima stringa è maggiore della seconda. "Maggiore" e "minore" indicano lo stato della stringa quando è ordinata alfabeticamente. La lettera "b" è maggiore della lettera "a":
int Result=StringCompare("a","b",true); Alert(Result);
In questo caso, la funzione restituirà -1.
Ora, prima di proseguire con altre funzioni, è necessario fare una breve digressione teorica.
Le corde viste da umani e computer
Che cosa sia una stringa per un umano è abbastanza chiaro: è un testo fatto di caratteri. Il computer, rispetto a un essere umano, ha una struttura un po' più semplice, si occupa solo di numeri. Il computer vede le immagini, le stringhe e tutto il resto come numeri. Una stringa è un array di numeri in cui un carattere corrisponde a un numero, ovvero un codice, un altro carattere a un altro codice, ecc. Questi codici sono chiamati codici ASCII (abbreviazione di American Standard Code for Information Interchange). Più avanti useremo il termine ASCII, che implica un ASCII esteso che contiene 256 codici. Quindi, possiamo dire che l'"alfabeto" del computer è composto da 256 caratteri. Proprio come ci sono diversi alfabeti per diversi popoli e lingue, il computer ha vari set di caratteri - code page. Gli utenti di computer in Russia utilizzano principalmente Windows-1251, una codifica dei caratteri che include caratteri latini e cirillici, nonché numeri, segni di punteggiatura e alcuni altri simboli. La Fig. 1 mostra la tabella codici di Windows-1251:
Fig. 1. Pagina codici di Windows-1251.
I primi 32 caratteri non vengono visualizzati, quelli sono caratteri di controllo. Non vengono visualizzati come tali ma influenzano la visualizzazione di altri caratteri, ad es. tab (codice 9), avanzamento riga (codice 10), ecc.
La codifica utilizzata per rappresentare i testi nelle lingue dell'Europa centrale è Windows-1250 (Fig. 2):
Fig. 2. Pagina codici di Windows-1250.
Si prega di notare che a partire dal codice 192, dove la pagina codici 1251 presenta lettere dell'alfabeto russo, la pagina codici 1250 ha lettere che contengono segni diacritici (lettere con segni diacritici che determinano lievi cambiamenti nel valore del suono) nelle lingue europee.
256 caratteri sono un numero molto piccolo. Le difficoltà sorgono se un testo deve essere scritto in più lingue, ad esempio russo e francese (ha un gran numero di segni diacritici) o inglese e arabo (i caratteri sono molto diversi dai caratteri di altre lingue). C'è anche la scrittura geroglifica, come in cinese e giapponese, che ha migliaia di caratteri e le difficoltà in questo caso sono ancora più evidenti. Potrebbe essere necessario codificare i caratteri non inclusi nella loro tabella codici utilizzando un altro modo. Chi di voi ha familiarità con l'HTML, dovrebbe conoscere la possibilità di inserire caratteri non standard in una pagina HTML, ad esempio il codice À è usato per visualizzare À e Á per renderizzare À, ecc.
Di recente è diventato comune utilizzare la codifica Unicode in cui un carattere non è codificato in un singolo byte (numero da 0 a 255), ma in due byte, per un totale di 65536 caratteri. Questo set di caratteri include lettere di tutti gli alfabeti esistenti nel mondo e anche i geroglifici più comuni come mostrato in Fig. 3 (i caratteri appropriati dovrebbero essere ancora installati sul tuo computer):
Fig. 3. Lettere di diversi alfabeti e geroglifici.
Le stringhe in MQL5 sono codificate utilizzando Unicode. In altre parole, un carattere in una stringa può essere rappresentato da un numero compreso tra 0 e 65535. I caratteri con codici da 0 a 127 sono gli stessi in ASCII e Unicode. I file di testo possono contenere testi codificati utilizzando ASCII o Unicode e di conseguenza la funzionalità MQL5 per lavorare con le stringhe in ASCII e Unicode è diversa.
Conversione di una stringa in un array e di nuovo in stringa
Quando si lavora con le stringhe, le funzioni StringLen(), StringFind(), StringSubst() e StringReplace() di solito sono sufficienti per risolvere la maggior parte delle attività pratiche. Ma potrebbero esserci compiti che sono molto più facili da risolvere lavorando con stringhe come numeri, come la crittografia, la compressione dei dati, il calcolo dei valori di controllo. Sebbene le attività di quel tipo non vengano affrontate quotidianamente, è possibile che un giorno tu debba risolverle. Esistono anche attività più importanti che richiedono la conversione di una stringa in un array, ad esempio il passaggio di parametri di stringa alle funzioni API (Application Programming Interfaces) di Windows.
Per convertire una stringa in un array Unicode, usiamo la funzione StringToShortArray() e per convertirla in un array ASCII - la funzione 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");
Se gli array ottenuti utilizzando le funzioni StringToShortArray() e StringToCharArray() nell'esempio precedente sono identici, verrà visualizzata una finestra con il messaggio "Identico" e se ci sono differenze, il messaggio sarà "Diverso". Per la stringa "MetaTrader 5", gli array sono identici perché la stringa è composta da caratteri con codici carattere fino a 127.
È tutto un po' diverso con i codici dei caratteri superiori a 127. I risultati dell'operazione della funzione StringToShortArray() saranno sempre gli stessi ovunque, mentre i risultati dell'operazione della funzione StringToCharArray() dipenderanno dalle impostazioni internazionali del sistema operativo.
In Windows 7, la lingua del sistema può essere selezionata in Pannello di controllo - Regione e lingua - Cambia lingua di visualizzazione.
Dai un'occhiata al seguente esempio. Nella tabella codici 1251, il codice 192 corrisponde alla lettera "А" (prima lettera dell'alfabeto russo), mentre lo stesso codice nella codifica 1250 corrisponde alla lettera "Ŕ" (una delle lettere più conosciute dell'alfabeto ceco) . Quando si utilizza la funzione StringToShortArray(), la lettera "А" avrà sempre il codice 1040, mentre la lettera "Ŕ" il codice 340. Se il sistema è impostato sulla lingua russa, quando si utilizza la funzione StringToCharArray() la lettera "А" corrisponderà al codice 192 (corretto), mentre la lettera "Ŕ" corrisponderà al codice 82 (latino "R"). Se invece il sistema è impostato sulla lingua ceca, la lettera "А" corrisponderà al codice 63 (punto interrogativo) e la lettera "Ŕ" corrisponderà al codice 192 (corretto). I caratteri che contengono segni diacritici vengono sostituiti con caratteri latini simili, mentre i caratteri meno comuni vengono sostituiti con un punto interrogativo.
Si prega di notare la dimensione della stringa e degli array risultanti:
int StrLen=StringLen(str); int shaLen=ArraySize(sha); int chaLen=ArraySize(cha); //--- output the lengths Alert(StringFormat("%i, %i, %i",StrLen,shaLen,chaLen));
Il numero di elementi negli array è maggiore del numero di caratteri nella stringa di uno. Ciò ha a che fare con il fatto che la fine della stringa è contrassegnata dal carattere con codice 0. Questo carattere non viene visualizzato nella stringa ma è significativo per il computer che indica la fine della stringa visualizzata. Non sempre lo scambio dati avviene con una velocità di un byte (carattere) alla volta nella misura corrispondente alla lunghezza della stringa, ma il carattere con codice 0 permette comunque di determinare la fine della stringa. Lo stesso zero può anche causare problemi, ad esempio un certo carattere può essere convertito nel carattere con codice 0 durante la crittografia o durante l'applicazione di un algoritmo di compressione. In questo caso, se si converte inversamente un array in una stringa, la stringa non sarà completa. Compiti di questo tipo richiedono l'uso di trucchi speciali, ma questo esula dallo scopo di questo articolo.
La conversione inversa di un array in una stringa è possibile utilizzando le funzioni ShortArrayToString() e 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);
Come risultato del codice sopra, la variabile str1 memorizzerà la stringa "Unicode" e str2 memorizzerà la stringa "ASCII".
Ci sono altre due funzioni simili: ShortToString() e CharToString(). Convertono una singola variabile di tipo short o char in una stringa composta da un carattere. La funzione CharToString() ha un grande valore pratico. Un oggetto grafico che consente di visualizzare diversi simboli, OBJ_ARROW, è ancorato all'asse dei prezzi verticalmente e all'asse del tempo orizzontalmente in modo che i simboli si spostino mentre si scorre il grafico. L'utilizzo di OBJ_LABEL insieme al font Wingdings ci permette di visualizzare sullo schermo diversi simboli ancorati alle coordinate permettendoci così di creare vari pannelli informativi. Troviamo il simbolo richiesto nella tabella dei simboli di Wingdings, convertiamo il suo codice in una stringa che viene ulteriormente visualizzata utilizzando l'oggetto grafico 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
Come risultato di questo codice, vedrai l'icona di una campana nel grafico. La campana rimarrà al suo posto mentre scorri il grafico.
Altre due funzioni per lavorare con i codici carattere sono StringGetCharacter() e StringSetCharacter(). Funzionano con codici Unicode. La funzione StringGetCharacter() consente di ottenere il codice del carattere in una determinata posizione nella stringa:
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));
Dopo l'esecuzione di questo codice, la variabile uch1 memorizzerà il valore di 76 e uch2 memorizzerà 53.
La funzione StringSetCharacter() consente di modificare il codice del carattere in una determinata posizione, nonché di aggiungere un carattere alla fine di una stringa:
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);
Quando si esegue questo codice, la variabile str invece di "MQ5" memorizzerà prima "MQL" e poi "MQL5".
Chiamare le funzioni API
Alcune funzioni API utilizzano parametri stringa come variabili. Ad esempio, la funzione per applicazioni di terze parti WinExec utilizza un array di tipo uchar come primo parametro:
#import "kernel32.dll" int WinExec(uchar &Path[],int Flag); #import
Proviamo a eseguire notepad.exe (Blocco note), un programma Windows standard. Converti il percorso del blocco note in un array del tipo uchar:
string PathName="C:\\WINDOWS\\notepad.exe"; uchar ucha[]; StringToCharArray(PathName,ucha); int x=WinExec(ucha,1);
Questa operazione di funzione dovrebbe comportare l'apertura dell'editor di testo del Blocco note.
Un altro esempio di utilizzo di parametri stringa nelle funzioni API è la funzione MessageBoxW che stampa un messaggio nella finestra utilizzando Unicode. Per questo motivo, passeremo array di tipo ushort come parametri:
#import "user32.dll" int MessageBoxW(int hWnd,ushort &szText[],ushort &szCaption[],int nType); #import
Ora usa questa funzione per stampare un messaggio nella finestra:
ushort arr[]; ushort capt[]; //--- convert StringToShortArray("Programming in MQL5 for MetaTrader 5.",arr); StringToShortArray("Message",capt); //--- print the message MessageBoxW(0,arr,capt,0);
Come risultato di questo codice, sarai in grado di vedere una finestra con il seguente messaggio: "Programmazione in MQL5 per MetaTrader 5".
Va notato che l'uso di array di tipo ushort come nell'esempio precedente non è necessario e puoi semplicemente passare delle stringhe come parametri della funzione:
#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); }
Il risultato di questo codice sarà lo stesso di sopra. Tuttavia non sarà possibile utilizzare array di tipo uchar come parametri della funzione, per stampare il messaggio corretto:
#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); }
Il codice verrà eseguito senza errori e apparirà una finestra pop-up, tuttavia il messaggio sarà distorto.
Per i casi in cui è necessario stampare una stringa nella codifica ASCII (es. se si dispone già di un array di tipo uchar), esiste una funzione simile, MessageBoxA. Per visualizzare correttamente il messaggio, solo gli array di tipo uchar devono essere passati alla funzione come parametri di stringa. Ora importa questa funzione e chiamala per stampare il messaggio:
#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); }
E di nuovo riceviamo il messaggio corretto "Programmazione in MQL5 per MetaTrader 5".
Fondamentalmente, ci sono 2 opzioni per molte delle funzioni WinAPI che funzionano con le stringhe: l'opzione per lavorare con le stringhe ASCII e l'opzione per lavorare con le stringhe Unicode.
Per poter chiamare le funzioni, abilitare l'uso delle DLL nelle impostazioni del terminale (Terminale - Menu principale - Strumenti - Opzioni - Expert Advisors - Consenti importazioni DLL) o selezionare "Consenti importazioni DLL" nella scheda Dipendenze della finestra delle proprietà quando si esegue uno script, un Expert Advisor o un indicatore. Specificare la proprietà dello script appropriata in modo da abilitare l'apertura della finestra delle proprietà per lo script:
#property script_show_inputs
Ingresso parametro illimitato
L'utente inserisce i parametri nella finestra delle proprietà, separandoli con un punto e virgola:
input string Lots="0.1; 0.2; 0.3; 0.5";
Dobbiamo convertire questa stringa in un array di variabili di tipo double.
In MQL5, una stringa può essere divisa utilizzando la funzione StringSplit(). Il primo parametro passato alla funzione è una stringa, il secondo parametro è il codice ASCII del separatore e il terzo parametro passato è un array che memorizzerà i risultati dell'operazione della funzione. Esiste un modo molto semplice per determinare il codice ASCII: è necessario racchiudere il carattere richiesto tra virgolette singole:
int Code='A'; Alert(IntegerToString(Code));
Per effetto di questo codice, la variabile Code memorizzerà il valore 65, che è il codice ASCII del carattere latino "A".
Esprimiamo la soluzione a questo problema come una funzione separata in modo da usarla facilmente quando necessario. Il primo parametro passato alla funzione sarà una stringa e il secondo parametro sarà un array restituito per riferimento. Il codice della funzione è fornito di seguito con commenti dettagliati e non richiede ulteriori spiegazioni:
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); }
Conversione di stringhe in varie variabili
La funzione ParamsToArray() ha utilizzato la funzione standard StringToDouble() per convertire la stringa nella variabile di tipo double. La stessa funzione viene utilizzata per la conversione al tipo float. Esistono funzioni standard che vengono utilizzate per le conversioni in altri tipi di variabili.
La funzione StringToInteger() converte una stringa in una variabile intera:
string Str="12345.678"; //--- convert the string to an integer long Val=StringToInteger(Str); //--- inverse convert and output the results Alert(IntegerToString(Val));
Come risultato di questo codice, la variabile Val memorizzerà il valore di 12345. La parte frazionaria viene semplicemente troncata.
La funzione StringToTime() converte un'espressione di stringa dell'ora nel valore numerico pertinente. Se non si specifica l'ora, il valore predefinito sarà "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 funzione StringToColor() consente di convertire un nome di colore (colore web standard) nel valore numerico pertinente o di convertire una stringa di componenti RGB:
string Str1="clrYellow"; string Str2="255,255,0"; color Color1=StringToColor(Str1); color Color2=StringToColor(Str2);
Esiste un altro modo per convertire le stringhe in datetime e tipo di colore. Può essere utilizzato quando si assegnano determinati valori alle variabili:
datetime DateTime=D'2012.11.02 22:00'; color Color=C'255,255,0';
"D" è scritto prima dell'espressione stringa di date e la data stessa è racchiusa tra virgolette singole. L'espressione stringa di colore è preceduta dalla lettera "С" e le componenti RGB sono racchiuse tra virgolette singole e separate da una virgola.
Abilitazione delle notifiche
L'utente immette una serie di caratteri che abilitano un certo tipo di notifica. Questo metodo può essere utilizzato per abilitare varie combinazioni di notifiche. La notifica di avviso corrisponde a "а", la notifica sonora a "s", la notifica e-mail a "e" e la notifica push a "p". Inoltre, puoi aggiungere 1 o 0 alla stringa per indicare la barra su cui vengono controllati i segnali (può essere utile negli indicatori). Il codice è espresso come una funzione il cui primo parametro è una stringa seguita dalla variabile Shift (numero della barra) restituita per riferimento e variabili di tipo bool corrispondenti a diversi metodi di notifica. Il codice è fornito di commenti dettagliati:
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 }
Ora, invece di cinque variabili nella finestra delle proprietà, ne basterà una sola.
Buffer di stringa
Dobbiamo ancora parlare di tre funzioni standard: StringInit(), StringFill() e StringBufferLen().
La funzione StringInit() riempie una stringa con caratteri identici nel numero specificato:
string str; StringInit(str,10,'|'); Alert(str);
Dopo l'esecuzione di questo codice, la variabile str memorizzerà la stringa contenente "||||||||||". Il carattere viene specificato utilizzando il suo codice ASCII, ovvero il carattere deve essere racchiuso tra virgolette singole.
La funzione StringFill() riempie una stringa con caratteri identici senza modificare la dimensione della stringa. Continuando con l'esempio precedente:
StringFill(str,'/'); Alert(str);
Successivamente, la variabile str memorizzerà la stringa contenente "//////////".
Proviamo ora a riempire una stringa con un carattere con codice 0 (fine della stringa):
StringFill(str,0);Controlla la dimensione della stringa:
int Length=StringLen(str); Alert(IntegerToString(Length));
La dimensione è uguale a 0 e il carattere con codice 0 si trova nel punto iniziale della stringa. Controlla la dimensione del buffer:
int BLength=StringBufferLen(str); Alert(IntegerToString(BLength));
La dimensione del buffer è diversa da 0 e supera la dimensione della stringa iniziale. La memoria allocata alla stringa è più che sufficiente. Ora, quando si assegna un valore alla stringa all'interno dell'intervallo di dimensioni del buffer, non sarà necessaria la riallocazione della memoria e il valore verrà assegnato molto rapidamente. Per garantire che la dimensione del buffer non venga ridotta, il nuovo valore dovrebbe essere aggiunto alla stringa, anziché assegnato ad essa:
str+="a";
La lunghezza della stringa è ora 1, mentre la dimensione del buffer è rimasta la stessa. In questo modo è possibile velocizzare un po' l'elaborazione delle stringhe. Una stringa può essere cancellata inserendo il carattere con codice 0 all'inizio della stringa:
StringSetCharacter(str,0,0);
Conclusione
Si potrebbe pensare che l'argomento dell'articolo sia di minore importanza, poco pertinente allo scopo principale del linguaggio MQL5, ovvero lo sviluppo di Expert Advisor e indicatori. Tuttavia, quello che abbiamo ottenuto è un articolo piuttosto ampio ispirato da un'ampia gamma di funzionalità per lavorare con le stringhe offerte dal linguaggio. In molti casi quando si programmano Expert Advisor e indicatori non si avrà a che fare con le stringhe, ma in qualche caso esse possono essere necessarie. Dopo aver letto questo articolo, sei pronto per utilizzare le stringhe, come e dove necessario, senza perdere tempo a studiarne le funzioni. Sarai in grado di fare facilmente ciò che è richiesto.
Ricapitoliamo le informazioni fornite nell'articolo, classificando le funzioni in base al loro scopo, importanza e frequenza di utilizzo.
- StringLen(), StringFind(), StringSubstr(), StringReplace() e StringSplit() sono funzioni chiave essenziali utilizzate per determinare la lunghezza della stringa, la ricerca di sottostringhe, per ottenere e sostituire una sottostringa, nonché per dividere una stringa.
- StringTrimLeft(), StringTrinRight(), StringToLower() e StringToUpper() sono funzioni ausiliarie molto utili che vengono utilizzate per eliminare gli spazi alle estremità e modificare le maiuscole.
- ColorToString(), DoubleToString(), EnumToString(), IntegerToString(), TimeToString() e StringFormat() sono funzioni che convertono le variabili numeriche in una stringa.
- StringToColor(), StringToDouble(), StringToInteger(), StringToTime() e StringCompare() sono funzioni che convertono una stringa in una variabile numerica.
- StringAdd() e StringConcatenate() sono funzioni che è possibile utilizzare per sommare e combinare stringhe in modo efficiente in termini di spazio.
- ShortToString(), ShortArrayToString(), StringToShortArray(), nonché CharToString(), CharArrayToString() e StringToCharArray() sono funzioni per lavorare con le stringhe come array che possono essere utili quando si ha a che fare con attività che richiedono manipolazioni di stringhe molto complesse. Dall'elenco di cui sopra, possiamo evidenziare due funzioni particolarmente importanti:
- CharToString() viene utilizzato per lavorare con oggetti grafici insieme al carattere Wingdings,
- CharArrayToString() viene utilizzato per preparare un parametro stringa quando si chiamano funzioni API.
- StringSetCharacter(), StringGetCharacter(), StringInit(), StringFill() e StringBufferLen() sono funzioni secondarie.
File allegati
- IncStrFunctions.mqh contiene le funzioni Trim(), StringFindRev(), TrimL(), TrimR(), ParamsToArray() e NotifyOnOff().
- eMultiLanguageMessage.mq5 è un esempio di Expert Advisor con messaggi in diverse lingue.
Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/585
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso