English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Fundamentos básicos da programação MQL5: strings

Fundamentos básicos da programação MQL5: strings

MetaTrader 5Exemplos | 18 março 2014, 14:26
8 123 1
Dmitry Fedoseev
Dmitry Fedoseev

Introdução

Strings, ou melhor, variáveis de string, são utilizadas para armazenar dados de caractere, ou seja, texto:

string str="Any text";

A linguagem MQL5 oferece uma ampla variedade de funcionalidades fáceis de usar para trabalhar com strings. Na programação de Expert Advisors e indicadores, as strings são utilizadas principalmente para gerar mensagens de informações. Nos indicadores, elas podem ser mensagens relativas ao preenchimento de determinadas condições (por exemplo, sinais de negociação), enquanto que nos Expert Advisors elas podem relatar resultados de atividade de negociação. Quando executado, um Expert Advisor, script ou indicador poderá verificar os parâmetros estabelecidos pelo usuário e reproduzir uma notificação caso esses parâmetros sejam inválidos. Além de notificações, às vezes, você poderá ver mensagens de lembretes que apresentam recomendações sobre configurações de parâmetro. De forma ampla, durante a programação em MQL5, as strings, antes de mais nada, oferecem facilidade aos usuários.

Além disso, as strings são essenciais ao se trabalhar com arquivos. A leitura e escrita de dados a partir de arquivos são realizadas com o uso de variáveis de string. Claramente, é possível optar por outra maneira de trabalhar com arquivos, um método binário que oferece a possibilidade de leitura e escrita de variáveis numéricas e arrays. Entretanto, se a quantidade de dados não é tão grande, é melhor utilizar arquivos de texto e strings. Nesse caso, a operação do programa é mais clara para o usuário e o processo de desenvolvimento de programa é mais fácil, fornecendo um controle de dados imediato. Os dados de arquivo de texto têm o mesmo aspecto dos dados de dentro do programa.

A utilização de strings pode ampliar significativamente os recursos do programa associados à entrada de dados (parâmetro) em casos em que o número de parâmetros requerido não é conhecido com antecedência (por exemplo, tamanhos de lote para desenvolvimentos médios). Nesse caso, os valores podem ser escritos em uma única string separados por um separador, como ponto e vírgula:

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

Então, ao inicializar o Expert Advisor, a string é dividida e um array de valores numéricos é preenchido. Infelizmente, é impossível analisar esses parâmetros de string na otimização, ou seja, para estabelecer o valor inicial e final juntamente com o valor do passo. Em alguns casos, talvez seja preferível utilizar um maior número de variáveis numéricas na janela de propriedades. Porém, visto que elas podem ter número praticamente ilimitado, podemos encontrar um problema de conveniência e propósito (se a possibilidade de otimização é requerida).

Haverão outros casos em que a otimização de um parâmetro é notoriamente não requerida, por exemplo, na habilitação de notificações. A linguagem MQL5 suporta diversos métodos de notificação do usuário: sons, pop-up, notificações por e-mail e notificações do tipo push. Você pode criar um interruptor do tipo booleano para cada uma dessas notificações na janela de propriedades (ele irá requerer no mínimo quatro variáveis) ou reduzir o número de variáveis para uma variável de string.

Se você precisar habilitar notificações sonoras, deverá escrever "s" (som). Se você também precisar de notificações por e-mail, adicionará "e". Assim, você pode habilitar qualquer combinação de notificações utilizando apenas uma variável. Para um Expert Advisor, o número de parâmetros externos tem pouca importância. É apenas uma questão de facilidade para o usuário.

Por outro lado, ao desenvolver indicadores você deve procurar reduzir o número de parâmetros externos. É muito provável que o indicador seja chamado a partir de um Expert Advisor ou de outro indicador com a utilização das funções iCustom() ou IndicatorCreate() cujo número de parâmetros é limitado (iCustom() apenas possui 64 parâmetros e o tamanho do array de parâmetros da função IndicatorCreate() é 64 elementos). Assim, o uso de strings pode ser de grande valor prático.

Este artigo analisará todas as funções MQL5 padrão para trabalhar com strings e também criaremos algumas funções práticas personalizadas.

 

Declarando uma variável de string

Como qualquer outro tipo de variáveis, as variáveis de string podem ser declaradas:

string str;
ou um valor pode ser designado a elas durante a declaração (inicializadas a um valor):
string str="Any text";

Não há restrições em relação ao comprimento da string. Uma string longa pode, por conveniência, ser dividida em diversas substrings:

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

Quando inicializada dessa forma, a variável str conterá a string contendo "Uma string longa pode ser dividida em diversas substrings".

Passando um pouco adiante aqui, devemos notar que o valor de uma variável de string declarada sem parâmetros não é idêntico ao de uma string vazia:

string str="";

Você pode perceber isso sozinho:

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

Ao executar esse código, uma janela alertando "falso" aparecerá. Uma variável de string não inicializada possui o valor NULL (nulo), que não é o mesmo que uma string vazia "". Você deve se lembrar disso! Ao trabalhar com strings, muito frequentemente temos que verificar se uma string está vazia ou não. Assim, você deve observar a regra de inicializar todas as strings com uma string vazia "" ou verificar se elas não são iguais "" e não são iguais a NULL:

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

O primeiro método é mais recomendável visto que simplifica a condição de verificação. 

Você pode fazer o mesmo ao verificar o tamanho de uma variável. Para determinar o tamanho, utilizamos a função StringLen():

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


Concatenação de strings

A operação principal e mais comum que você fará ao trabalhar com strings é a concatenação delas, ou seja, construir frases utilizando palavras. A concatenação é implementada com o uso do sinal "+":

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

Após a execução desse código, a variável str4 conterá "Programação em MQL5", enquanto que a variável str5 conterá "Programação para MetaTrader 5". O exemplo acima demonstrou como você pode concatenar duas strings, com a string resultante sendo atribuída a outra variável.

Uma string adicional é muito frequentemente concatenada com a string principal: 

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

Após a execução desse código, a string str1 conterá "Programação em MQL5 para MetaTrader 5". O exemplo acima demonstrou como você pode concatenar strings com a string str1 principal, com os resultados atribuídos à última. As mesmas operações podem ser escritas de forma muito mais simples:

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

O sinal "+" à esquerda de "=" significa que a expressão à direita de "=" é anexada à variável str1.

Você também pode adicionar uma string ao início da string principal. Isso pode ser implementado da maneira demostrada do segundo ao último exemplo: a string principal é adicionada à string adicional e a string resultante é atribuída à variável principal:

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

A seguinte frase: "Programação em MQL5 para MetaTrader 5" agora será a variável str3. Você pode implementar o mesmo utilizando uma string simples: 

str3=str1+" "+str2+" "+str3;
Em alguns casos você pode realizar a concatenação utilizando "," (vírgula). Isso é possível ao chamar as funções Alert(), Print() ou Comment():
Print(str1," ",str2," ",str3);

Os resultados finais, nesse caso, serão idênticos a quando se utiliza o sinal "+":

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

O símbolo "," na realidade não concatena strings. A vírgula é um separador de parâmetros em todas as funções. Isso também é verdadeiro para as funções Alert(), Print() e Comment(). Essas funções têm um parâmetro obrigatório e diversos parâmetros opcionais. Os parâmetros estão em efeito transferidos para a função em que estão concatenados. O número máximo de parâmetros é 64.

Podemos perceber algo similar ao gravar uma string em um arquivo utilizando a função FileWrite(). Entretanto, se você abrir um arquivo no modo FILE_CSV (com separadores de campo), as vírgulas serão substituídas pelo caractere separador especificado durante a abertura do arquivo (se o separador não estiver especificado, a tabulação é utilizada como padrão). Ao abrir um arquivo no modo FILE_TXT sem especificar o separador, os resultados de usar o sinal "+" e "," serão os mesmos:

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

Após executar esse código, o arquivo 1.txt conterá "1    2    3", enquanto que o arquivo 2.txt conterá "123" (os arquivos foram abertos no modo FILE_CSV). 3.txt e 4.txt terão conteúdo idêntico: "123" (aberto no modo FILE_TXT). As operações de arquivo não são o foco deste artigo. Dessa forma, se algo do último exemplo não parece claro para você, não se preocupe, visto que isso não afetará a sua compreensão em relação ao material apresentado a seguir neste artigo. Apenas perceba que o uso de "+" e "," nem sempre produz o mesmo efeito ao lidar-se com adição de strings.

Além do sinal "+", a linguagem MQL5 fornece funções especiais para adição de strings: StringAdd() e StringConcatenate(). De acordo com a descrição dessas funções na Referência MQL5, elas permitem adicionarmos strings de maneira mais rápida e eficiente em relação ao espaço (em termos de memória de trabalho ocupada). A função StringAdd() permite adicionarmos uma string a outra:

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

Após a execução desse código, a variável str1 terá a string contendo "Programação em MQL5 para MetaTrader 5".

A função StringConcatenate() permite que você combine diversas strings simultaneamente. O primeiro parâmetro passado à função é a variável da string à qual as strings listadas posteriormente serão adicionadas. O número máximo de parâmetros que você pode transferir à função é 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);

Após a execução desse código, a variável str1 também conterá "Programação em MQL5 para MetaTrader 5".

 

Conversão de diversas variáveis para uma string

Ao gerar uma string de mensagem, muito frequentemente temos que adicionar valores de variáveis numéricas. Para converter valores de variáveis inteiras (char, uchar, bool, short, ushort, int, uint, color, long, ulong, datetime) para uma string, usamos a função IntegerToString():

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

Ao converter uma variável do tipo boleana, uma string retornada conterá tanto "0" (falso) ou "1" (verdadeiro). Similarmente, se você converter as variáveis de tipo data e hora ou cor, uma string retornada conterá uma expressão numérica de cor ou data (por ex., "65535" para a cor amarela de clrYellow ou "1325376000" para a data da seguinte forma: 2012.01.01 00:00).

Para converter variáveis reais (duplas, flutuantes) em uma string, usamos a função DoubleToString() . O segundo parâmetro desta função determina a precisão (o número de locais decimais):

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

Após a execução desse código, a variável str1 conterá a string "1.23", enquanto que a variável str2 conterá a string "1.235". O encurtamento para o número de dígitos especificado é feito com a utilização das regras matemáticas de arredondamento.

A função TimeToString() é utilizada para converter data e hora para uma string de formato padrão (prontamente compreensível por seres humanos):

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

Após a execução desse código, a variável str1 conterá a string com uma expressão numérica de horário (o número de segundos transcorridos desde 1 de janeiro de 1970), enquanto que a variável str2 conterá o horário formatado, por exemplo "2012.11.02 22:00" (ano, mês, dia, hora, minuto).

Ao chamar a função TimeToString(), você tem a opção de especificar o formato de data e hora. As opções disponíveis são:

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

A linguagem MQL5 oferece um excelente recurso útil para criar enumerações que são exibidas na janela de propriedades do programa como listas suspensas de opções. Os valores dessas variáveis também podem ser convertidos para uma string com o uso da função EnumToString(). O código de script abaixo demonstra a operação dessa função:

//+------------------------------------------------------------------+
//| 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);
  } 
Há uma possibilidade similar que permite que você converta variáveis de cor: Você pode converter o valor de cor para o nome da cor utilizando a função ColorToString():
color ColorValue=clrRed;
string str=ColorToString(ColorValue,true);

Após executar esse código, a variável str armazenará a string contendo "clrRed". Se o segundo parâmetro é configurado para falso, a função retornará a string com valores de componentes RGB (vermelho, verde e azul):

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

Nesse caso, a string armazenada na variável str será "255,0,0". Se a cor que você deseja não é padrão (não está definida na paleta de cores hexadecimais e consequentemente, não tem nome), a função ColorToString() pode ser usada para retornar a string com valores de componentes independentemente do valor do segundo parâmetro.

Há ainda outro método para conversão de variáveis utilizando conversão de tipos:

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

Quando uma variável do tipo bool é convertida dessa forma, o valor da string será "verdadeiro" ou "falso": 

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

A conversão de variáveis de tipo dupla ou flutuante deve ter a maior precisão possível, permitindo que você apenas elimine zeros na parte fracionária: 

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

Após a execução desse código, a variável str1 armazenará o valor de string "0.1" e a variável str2 conterá o valor de string "0.123".

 

Saída de caractere especial

Ao inicializar uma variável de string a um valor, a string atribuível deve ser escrita entre aspas duplas para que o compilador possa diferenciar a string do código do programa. Para ser capaz de colocar as aspas dentro da string, você precisa especificar o fato de que as aspas não são utilizadas aqui para a sua finalidade comum (como caracteres separando uma string de um código) e sim como parte de uma string. Para implementar isso, insira uma barra invertida "\" imediatamente antes da aspa:

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

Porque a barra invertida também é considerada um dos caracteres especiais, outra barra invertida deve ser inserida na frente para implementar a saída da barra invertida em uma string:

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

Após executar esse código, o único caractere que a string conterá será "\".

Uma string também pode conter um caractere tab horizontal representado por "\t":

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

Nesse caso, a variável str terá a string contendo "Column-1        Column-2        Column-3".

Um texto também pode ser representado com quebras de linha, dividido em diversas linhas com o uso de "\n":

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

Aqui, como resultado da execução da função Alert() você terá três linhas de texto.

Ao representar utilizando as funções Alert() e MessageBox(), bem como quando gravando em um arquivo, você pode usar tanto "\t" como "\n". Entretanto, ao representar em um comentário de gráfico (a função Comment()), apenas "\n" é aplicado como caractere de embalagem, enquanto que o caractere tab "\t" é ignorado. Quando a saída é feita utilizando a função Print(), "\n" é aplicado como antes (cada parte de uma string é emitida em uma linha separada do diário) e "\t" é substituído por um espaço como no arquivo de registro que armazena todas as mensagens de saída utilizando a função Print().

 

Formatação de strings de forma padronizada

Ao formatar uma string para saída, pode ser que você precise incluir valores de diversas variáveis numéricas nela. Isso pode ser obtido através da adição de strings e conversão de variáveis numéricas para strings. Entretanto, nesse caso, a string do código que constrói uma mensagem será muito longa e difícil de compreender e editar, caso seja necessário modificar o programa:

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

A mesma tarefa pode ser resolvida de forma muito mais fácil com o uso da função StringFormat(). O primeiro parâmetro transferido para essa função é um modelo de mensagem, com locais indicados para a inserção de variáveis e formato de saída estabelecido. Após, segue a enumeração de todas as variáveis na ordem em que aparecem no modelo: 

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

Os locais para a inserção de variáveis estão marcados com "%" seguidos por "i", os quais, no exemplo acima, indicam que as variáveis devem ser emitidas como inteiros. Ou melhor, "i" significa caracteres de variáveis inteiras (char, short, int, color), enquanto que usamos "u" para variáveis inteiras não assinadas (uchar, bool, ushort, uint). Para variáveis do tipo de dados long, ulong e datetime, você deve especificar adicionalmente o tamanho da variável inserindo "I64" antes do 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);
Como resultado desse código, você verá uma janela pop-up com valores de variável.

O formato de números reais é indicado por "f":
double Percents=5.5;
//--- real number as a string
string str=StringFormat("Percents = %f",Percents);
//--- output the results
Alert(str);

Após executar esse código, a variável str armazenará a seguinte string: "Percents = 5.500000". A precisão de saída padrão é de seis casas decimais. Você pode definir o número requerido de casas decimais:

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

Para esse fim, insira um ponto indicando um símbolo decimal imediatamente seguido pelo número de casas decimais, por exemplo, 2, como no exemplo acima. Nesse caso, a variável str conterá a string a seguir: "Percents = 5.50". Essa opção de formatação é completamente idêntica à função DoubleToString().

Você pode especificar o comprimento total de um número escrevendo "0" e um número que determina o comprimento do número em questão imediatamente após "%" e então especificar o número de casas decimais (se necessário):

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

Aqui, temos um comprimento total de 6 dígitos, um dos quais será utilizado para o ponto decimal e dois outros representarão duas casas decimais. Assim, a string armazenada na variável str será "Percents = 005.50".

Se você precisa fazer a saída do sinal de percentagem "%" em uma mensagem, você precisa escrevê-lo duas vezes seguidas, ou seja, "%%", visto que um deles será utilizado para indicar locais para inserção de valores:

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

Nesse caso, a variável str conterá "Percents = 005.50%".

Você também pode determinar o comprimento de um número ao gerar variáveis inteiras:

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

Após a execução desse código, a variável str armazenará a seguinte string: "Variable = 00123".

Se o número de dígitos especificados for menor que o número de dígitos do número, a saída ainda assim será correta:

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

Aqui, a variável str conterá a seguinte string: "Variable = 123", ou seja, o número de saída terá 3 dígitos apesar do fato de que o comprimento especificado é 2.

Os números reais podem ser gerados com o uso de notação científica (mantissa de seis casas decimais e expoente) para a qual utilizamos o caractere "e":

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

Após executar esse código, a variável str conterá "1.234560e+002". Você também poderá utilizar "E" maiúsculo, cujo efeito é similar a "e" minúsculo, sendo que o "E" maiúsculo substitui o "e" minúsculo em uma string formatada.

Há ainda outra maneira de formatar números reais - usando "g", por meio do qual apenas 6 dígitos (excluindo qualquer ponto decimal) podem ser gerados. Se o comprimento da parte inteira de um número exceder seis dígitos, o número será gerado com o uso de notação científica:

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

No exemplo acima, a variável str1 conterá "12.3457" e a variável str2 conterá "1.23457e+006". O efeito será o mesmo se, em vez disso, você utilizar "G" maiúsculo, sendo que a única diferença é que, na saída, o "g" minúsculo será substituído pelo "G" maiúsculo.

A função StringFormat() permite que você transforme os formatos de representação de números, ou seja, que você converta números do sistema decimal para o sistema octal ou hexadecimal. Para converter um número para o sistema octal, você precisa utilizar o caractere "o":

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

Após a execução desse código, a variável str armazenará a seguinte string: "Variable = 21" (8*2+1=17).

"x" ou "X" é usado para converter um número para o sistema hexadecimal. Nesse caso, se você usar "x" minúsculo, um número do sistema hexadecimal consistirá em letras minúsculas, ou letras maiúsculas, caso o "X" maiúsculo seja usado:

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

Após executar esse código, a variável str conterá "Variable = ff0000".

De forma similar, você pode converter um número do sistema hexadecimal de volta para o sistema decimal utilizando o caractere "d":

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

Após a execução desse código, a string que a variável str irá armazenar será "Variable = 255".

O caractere "s" pode ser usado para gerar variáveis de string:

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

Assim que você executar o código acima, a string que contém "Variable = text" será armazenada na variável str.

Às vezes pode ser que você precise alinhar os números ao gerar eles em uma coluna, devido ao fato de que os números negativos são deslocados por causa do sinal "-". Para alinhar números positivos com negativos, você deve adicionar um espaço no início da string, imediatamente após "%". Nesse caso, os números negativos serão gerados sem um espaço, ao contrário dos números positivos, os quais terão um espaço no início:

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

Após a execução desse código, a variável str1 conterá "Variable1= 01" (a string com um espaço), enquanto que a variável str2 armazenará a string a seguir: "Variable2=-01".

Há mais duas funções similares à StringFormat(). PrintFormat() e printf(), as quais são absolutamente idênticas em termos de ação. A única diferença que elas têm em relação à função StringFormat() é que elas geram texto para o diário de forma similar à função Print().

Na realidade, a função StringFormat() oferece muito mais funcionalidade, enquanto que o material apresentado acima representa o mínimo requerido para solucionar a maioria dos problemas relativos à formatação de números para saída.
 

Mensagens em diferentes idiomas

A função StringFormat() fornece a possibilidade de melhorar o seu programa com um recurso muito útil que proporciona a representação de mensagens em diferentes idiomas, dependendo do idioma da interface configurado no terminal.

Você pode descobrir qual idioma de interface está configurado chamando a função TerminalInfoString() com o identificador TERMINAL_LANGUAGE. Ao executar um programa, preparamos uma string de formato dependendo do idioma da interface e então utilizamos ela no programa. Segue abaixo um modelo de um Expert Advisor com o recurso acima implementado:

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

O Expert Advisor calcula a soma de dois números aleatórios e gera a mensagem de acordo com suas ações, por exemplo "1 mais 2 é igual a 3".

Isso é tudo a respeito da saída de strings. Agora vamos passar a manipulações de string mais complexas e interessantes.

 

Funções-chave para trabalhar com strings

Se uma string é inserida através da janela de propriedades do programa ou lida a partir de um arquivo, ela poderá conter espaços desnecessários. Eles poderão aparecer devido a uma eventual falta de cuidado do usuário ou por conveniência. Assim, antes de usar a string de qualquer maneira, é recomendável apagar os espaços das extremidades esquerda e direita. Para isso, a MQL5 oferece duas funções - StringTrimLeft() (apaga espaços na extremidade esquerda) e StringTrimRight() (apaga espaços na extremidade direita). Além dos espaços, essas funções também removem tab e caracteres de nova linha. Ao trabalhar com strings, geralmente, precisamos apagar espaços nas duas extremidades de uma vez só, de forma que uma função que implementa isso será muito útil:

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

Ao inserir números reais, o usuário frequentemente poderá colocar uma vírgula em vez de ponto. Assim, ao trabalhar com números reais, você deve oferecer a possibilidade de usar tanto o ponto como a vírgula como símbolo decimal. Para substituir uma string por outra, utilizamos a função StringReplace():

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

Se você não substituir "," por ".", a parte fracionária do número será cortada na conversão de uma string para um número.

Em alguns casos, poderá ser requerido que você substitua uma série de espaços por um espaço. Para fazer isso, você primeiramente deve substituir os caracteres tab com um espaço e então substituir dois espaços por um até que reste apenas espaço:

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

A função StringReplace() retorna o número de substituições realizadas ou -1 em caso de erro. O circuito continua com a função retornando um valor maior que zero até que todas as séries de espaços sejam substituídas por um espaço que é deixado em cada caso único. O corpo do circuito não contém código algum. Ao verificar a condição do circuito a cada iteração, chamamos a função StringReplace().

A função StringReplace() permite substituirmos substrings de comprimentos diferentes:

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

Ao executar esse código, a variável str após a primeira substituição terá a string contendo "Programação para MetaTrader 5", e "Programação em MQL5!" após a segunda substituição.

A função StringFind() é usada para procurar uma substring. Ela retorna o índice da primeira ocorrência da substring em uma string. O primeiro parâmetro transferido à função é uma string em que a busca é realizada. O segundo parâmetro determina a substring alvo, enquanto que o terceiro parâmetro (opcional) pode determinar a posição em que a busca inicia. Se o terceiro parâmetro não é especificado, a função opera como se o seu valor fosse 0, ou seja, a busca inicia logo no início da string. Vamos encontrar a posição da substring "5" na string "Programação em MQL5 para 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));

Após a execução desse código, a variável Pos será 23. A substring "5" ocorre duas vezes no total, mas a função apenas retorna a posição da primeira ocorrência. Se você contar a posição apenas olhando para a string, você obterá 24. O detalhe é que a função começa a contar de zero e não de um. Se a substring alvo não é encontrada na string, a função retorna -1.

De vez em quando, você poderá precisar encontrar a posição da última ocorrência da substring. Para fazer isso, temos que escrever uma função personalizada, StringFindRev(). Começaremos procurando a primeira ocorrência da substring e então alternaremos o início da busca de acordo com a posição encontrada, etc. em um circuito:

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);
  }
Vamos tentar usar essa função:
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);

Após executar esse código, a variável Pos terá o valor 40.

A função StringSubstr() é usada para obter uma substring de um determinado tamanho a partir de uma determinada posição. Obtenha a substring de comprimento 1 da posição 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);

O valor resultante é "5".

Agora que consideramos as funções principais, vamos utilizá-las para escrever uma função útil para apagar uma determinada lista de caracteres de uma string. A função recebe a string fonte e uma string que representa uma lista de caracteres a serem apagados da string fonte.

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

A função apaga tab e caractere de nova linha, bem como um espaço e ponto e vírgula ";" de forma padrão.

A mesma função para apagar na extremidade direita:

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

Essa função também apaga tab e caractere de nova linha, bem como um espaço e ponto e vírgula ";" de forma padrão. Isso pode ser útil durante a leitura de arquivos CSV. Dentro desses arquivos, poderá haver muitos separadores de campo (geralmente ponto e vírgula ";") na extremidade direita de uma string.

Letras maiúsculas e minúsculas, por exemplo "А" e "а" não são vistas como possuindo diferentes significados para humanos, enquanto que os computadores as tratam como dois caracteres completamente diferentes. Se você escrever "eurusd" em vez de "EURUSD" ao solicitar os dados do mercado utilizando a função SymbolInfoDouble(), ela não retornará o valor requerido. A probabilidade disso acontecer durante a inserção do nome do símbolo na janela de propriedades é muito grande. Para mudar as letras em MQL5, você pode usar a função StringToLower() (para alterar para letras minúsculas) e a função StringToUpper() (para alterar para letras maiúsculas):

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

Após a execução desse código, a variável str1 armazenará a string que contém "EURUSD", enquanto que a variável str2 terá a string contendo "eurusd".

Se o que você precisa é comparar as strings sem levar em consideração o formato das letras, a função StringCompare() será a mais adequada. Os dois primeiros parâmetros da função são as strings para comparação. O terceiro parâmetro determina se as strings devem ser comparadas, levando (verdadeiro) ou não (falso) o formato das letras em consideração:

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

Se a função retorna 0, as strings são idênticas. A função poderá retornar -1 se a primeira string é menor que a segunda ou 1 se a primeira string é maior que a segunda. "Maior" e "menor" significa o estado da string ao ser organizada alfabeticamente. A letra "b" é maior que a letra "a":

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

Nesse caso, a função retornará -1.

Agora, antes de continuarmos com as outras funções, é necessário fazer uma breve digressão teórica.
  

Strings vistas por homens e computadores

O que uma string é para um homem é muito claro - é um texto feito de caracteres. Um computador, comparado com um ser humano, é um tanto mais simples em sua estrutura, apenas lidando com números. O computador vê as imagens, strings e todo o resto como números. Uma string é um array de números em que um caractere corresponde a um número, ou melhor, a um código, outro caractere a outro código, etc. Esses códigos são chamados de códigos ASCII (acrônimo para Código Padrão Americano para o Intercâmbio de Informação). Mais abaixo usaremos o termo ASCII, referindo-se ao ASCII estendido que contém 256 códigos. Dessa forma, podemos dizer que o "alfabeto" do computador consiste em 256 caracteres. Assim, como há diferentes alfabetos para diferentes povos e idiomas, o computador possui diversos conjuntos de caracteres - páginas de códigos. Os usuários de computadores na Rússia, em sua maioria, utilizam o Windows-1251, uma codificação de caracteres que inclui caracteres do alfabeto latino e cirílico, bem como números, sinais de pontuação e alguns outros símbolos. A Figura 1 exibe a página de códigos Windows-1251:


Figura 1. Página de códigos Windows-1251

Os 32 primeiros caracteres, que são os caracteres de controle, não são exibidos. Eles não são exibidos como tal, mas afetam a exibição dos outros caracteres, por exemplo, tab (código 9), avanço de linha (código 10), etc.

A codificação usada para representar textos nos idiomas da Europa Central é Windows-1250 (Figura 2):


Figura 2. Página de códigos Windows-1250

Por favor, note que iniciando com o código 192 onde a página de códigos 1251 apresenta letras do alfabeto russo, a página de códigos 1250 apresenta letras que contêm diacríticos (letras com sinais diacríticos que determinam pequenas mudanças fonéticas) em idiomas europeus.

256 caracteres é um número muito pequeno. As dificuldades surgem quando um texto precisa ser escrito em diversos idiomas, por exemplo russo e francês (que tem um grande número de sinais diacríticos) ou inglês e árabe (os caracteres são muito diferentes dos caracteres de outros idiomas). Também há o sistema de escrita hieroglífico, como o chinês e japonês, que apresenta milhares de caracteres e as dificuldades nesse caso são ainda mais evidentes. Você poderá precisar codificar caracteres não inclusos nas páginas de códigos deles de alguma outra forma. Aqueles que estão familiarizados com HTML devem conhecer a possibilidade inserir caracteres não padronizados em uma página HTML. Por exemplo, código À é utilizado para exibir À e Á para representar Á, etc.

Recentemente, tornou-se comum utilizar a codificação Unicode na qual um caractere é codificado não em um único byte, mas dois bytes, totalizando assim 65536 caracteres. Esse conjunto de caracteres inclui letras de todos os alfabetos existentes no mundo e até mesmo os hieróglifos mais comuns, conforme exibido na Figura 3 (as fontes adequadas ainda devem estar instaladas em seu computador):

Figura 3. Letras de diferentes alfabetos e hieróglifos.

Figura 3. Letras de diferentes alfabetos e hieróglifos

As strings em MQL5 são codificadas com o uso de Unicode. Em outras palavras, um caractere de uma string pode ser representado por um número de 0 a 65535. Os caracteres com códigos de 0 a 127 são os mesmos em ASCII e Unicode. Os arquivos de texto podem conter textos codificados com o uso de ASCII ou Unicode e, consequentemente, a funcionalidade MQL5 para trabalhar com strings em ASCII e Unicode é diferente.

 

Converter uma string para um array e novamente para string

Ao trabalhar com strings, em geral, as funções StringLen(), StringFind(), StringSubst() e StringReplace() são suficientes para solucionar a maioria das tarefas práticas. Mas poderá haver tarefas que são muito mais facilmente resolvidas ao se trabalhar com strings como números, tal como codificação, compressão de dados, cálculo de valores de verificação. Embora não se lide com tarefas desse tipo diariamente, é possível que algum dia você precise solucioná-las. Também há tarefas mais importantes que requerem que uma string seja convertida para um array, tal como a transferência de parâmetros de string às funções Windows API (Interface de Programação de Aplicativos).

Para converter uma string para um array Unicode, usamos a função StringToShortArray() e para converter para um array ASCII, a função 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 os arrays obtidos com o uso das funções StringToShortArray() e StringToCharArray() do exemplo acima forem idênticos, uma janela surgirá com a mensagem "Idênticos" e, se houver diferenças, a mensagem dirá "Diferentes". Para a string "MetaTrader 5", os arrays são idênticos porque a string consiste em caracteres com códigos de caractere até 127.

Tudo é um pouco diferente para códigos de caractere superiores a 127. Os resultados da operação da função StringToShortArray() sempre serão os mesmos em todos os locais, enquanto que os resultados da operação da função StringToCharArray() dependerá das configurações regionais do sistema operacional.

No Windows 7, o idioma do sistema pode ser selecionado em Painel de Controle - Região e Idioma - Alterar idioma de exibição.

Observe o exemplo a seguir. Na página de códigos 1251, o código 192 corresponde à letra "А" (a primeira letra do alfabeto russo), enquanto que o mesmo código na codificação 1250 corresponde à letra "Ŕ" (uma das letras mais conhecidas do alfabeto tcheco). Durante o uso da função StringToShortArray(), a letra "А" sempre terá o código 1040, enquanto que a letra "Ŕ" terá o código 340. Se o sistema está configurado para o idioma russo, então durante o uso da função StringToCharArray(), a letra "А" corresponderá ao código 192 (correto), enquanto que a letra "Ŕ" corresponderá ao código 82 ("R" latino). Entretanto, se o sistema está configurado para o idioma tcheco, a letra "А" corresponderá ao código 63 (ponto de interrogação) e a letra "Ŕ" corresponderá ao código 192 (correto). Os caracteres que contêm diacríticos são substituídos por caracteres latinos similares, enquanto que caracteres mais incomuns são substituídos por um ponto de interrogação.

Por favor, observe o tamanho da string e dos arrays resultantes:

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

O número de elementos nos arrays é maior que o número de caracteres na string por um. Isso está relacionado ao fato de que o final da string está marcado pelo caractere com código 0. Esse caractere não é exibido pela string, mas é significativo para o computador, indicando o final da string exibida. A troca de dados não é sempre realizada a uma taxa de um byte (caractere) por vez na quantidade correspondente ao comprimento da string, mas o caractere com código 0 permite que você determine o final da string em qualquer caso. O mesmo zero também poderá causar problemas. Por exemplo, um determinado caractere pode ser convertido para o caractere com código 0 quando se codifica ou quando se aplica um algoritmo de compressão. Nesse caso, se você converte inversamente um array para uma string, a string não será completa. Tarefas desse tipo requerem o uso de truques especiais, mas isso vai além do escopo deste artigo.

A conversão inversa de array para uma string é possível com o uso das funções 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);

Como resultado do código acima, a variável str1 armazenará a string "Unicode" e a str2 armazenará a string "ASCII".

Há mais duas funções similares: ShortToString() e CharToString(). Elas convertem uma única variável do tipo short ou char para uma string que consiste em um caractere. A função CharToString() possui grande valor prático. Um objeto gráfico que permite que você exiba diferentes símbolos, OBJ_ARROW, é fixada verticalmente ao eixo de preço e horizontalmente ao eixo de hora, de forma que os símbolos são deslocados à medida que você passa pelo gráfico. O uso de OBJ_LABEL juntamente com a fonte Wingdings permite exibirmos diferente símbolos fixados às coordenadas na tela, permitindo assim criarmos diversos painéis de informações. Encontramos o símbolo requerido na tabela de símbolos Wingdings, convertemos o seu código para uma string que é posteriormente exibida com o uso do objeto gráfico 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

Como resultado desse código, você verá um ícone de um sino no gráfico. O sino permanecerá em seu local enquanto você desliza sobre o gráfico.

StringGetCharacter() e StringSetCharacter() são mais duas funções para trabalhar com códigos de caracteres. Elas funcionam com códigos Unicode. A função StringGetCharacter() permite que você obtenha o código do caractere em uma determinada posição da string:

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

Após a execução desse código, a variável uch1 armazenará o valor 76 e a uch2 armazenará 53.

A função StringSetCharacter() permite que você altere o código do caractere em uma posição determinada, bem como adicione um caractere ao final de uma string:

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

Ao executar esse código, a variável str, em vez de "MQ5", primeiramente armazenará "MQL" e depois "MQL5".

 

Chamada de funções API

Algumas funções API utilizam parâmetros de string como suas variáveis. Por exemplo, a função WinExec para aplicativos de terceiros utiliza um array do tipo uchar como seu primeiro parâmetro:

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

Vamos tentar executar notepad.exe (bloco de notas), um programa padrão do Windows. Converta o caminho para o bloco de notas para um array do tipo uchar:

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

A operação dessa função deve resultar na abertura do editor de texto do bloco de notas.

Outro exemplo do uso de parâmetros de string nas funções API é a função MessageBoxW fque exibe uma mensagem na janela com o uso de Unicode. Por essa razão, transferiremos arrays do tipo ushort como os seus parâmetros:

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

Agora utilize essa função para exibir uma mensagem na janela:

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

Como resultado desse código, você poderá ver uma janela com a seguinte mensagem: "Programação em MQL5 para MetaTrader 5".

Deve-se destacar que o uso de arrays do tipo ushort no exemplo acima não é necessário e que você pode simplesmente transferir strings como os parâmetros da função:

#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);
  }

O resultado desse código será o mesmo apresentado acima. Entretanto, você não poderá usar arrays do tipo uchar como parâmetros da função para exibir a mensagem correta:

#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);
  }

O código será executado livre de erros e uma janela pop-up aparecerá, apesar de que a mensagem estará distorcida.

Para casos em que é necessário representar uma string na codificação ASCII (por exemplo, se você já tem um array do tipo uchar), há uma função similar, a MessageBoxA. Para exibir a mensagem corretamente, apenas arrays do tipo uchar devem ser transferidos à função como parâmetros de string. Agora importe e chame essa função para imprimir a mensagem:

#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 novamente obtemos a mensagem correta "Programação em MQL5 para MetaTrader 5".

Basicamente, há 2 opções para muitas das funções WinAPI que funcionam com strings - a opção para trabalhar com strings ASCII e a opção para trabalhar com strings Unicode.

Para ser capaz de chamar as funções, habilite o uso de DLLs nas configurações do terminal (Terminal - Menu Principal - Ferramentas - Opções - Expert Advisors - Permitir importação de DLL) ou marque "Permitir importação de DLL" na aba de Dependências da janela de propriedades ao executar um script, Expert Advisor ou indicador. Especifique a propriedade de script adequada para habilitar a abertura da janela de propriedades do script:

#property script_show_inputs

 

Entrada ilimitada de parâmetros

O usuário insere parâmetros na janela de propriedades, separando eles com ponto e vírgula:

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

Precisamos converter essa string para um array de variáveis de tipo dupla.

Em MQL5, uma string pode ser dividida com o uso da função StringSplit(). O primeiro parâmetro transferido à função é uma string, o segundo parâmetro é o código ASCII do separador e o terceiro parâmetro é um array que armazenará os resultados da operação da função. Há uma forma muito simples de determinar o código ASCII - você precisa inserir o caractere requerido entre aspas simples:

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

Como resultado desse código, a variável Code armazenará o valor 65, que é o código ASCII do caractere latino "A".

Vamos expressar a solução para esse problema como uma função separada para que possa ser utilizada facilmente quando necessário. O primeiro parâmetro transferido à função será uma string e o segundo parâmetro será um array retornado por referência. O código da função é fornecido abaixo com comentários detalhados e não requer explicações adicionais:

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

 

Converter strings para diversas variáveis

A função ParamsToArray() usou a função padrão StringToDouble() para converter a string para a variável de tipo dupla. A mesma função é usada para conversão para o tipo flutuante. Há funções padrão que são usadas para conversões para outros tipos de variáveis.

A função StringToInteger() converte uma string para uma variável inteira:

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

Como resultado desse código, a variável Val armazenará o valor 12345. A parte fracionária é cortada de forma simples.

A função StringToTime() converte uma string de expressão de hora para o valor numérico relevante. Se você não especificar a hora, o valor padrão será "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);

A função StringToColor() permite que você converta um nome de cor (cores hexadecimais padrão) para o valor numérico relevante, ou converta uma string de componentes RGB:

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

Há outra forma de converter strings para o tipo datetime (data e hora) e color (cor). Ela poderá ser usada ao se atribuir determinados valores a variáveis:

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

"D" é escrito antes da string de expressão de data e a data em si é inclusa entre aspas simples. A string de expressão de cor é precedida pela letra "С" e os componentes RGB são inclusos entre aspas simples e separados por uma vírgula.

 

Habilitar notificações

O usuário insere uma série de caracteres que habilita um determinado tipo de notificação. Esse método pode ser usado para que diversas combinações de notificações sejam habilitadas. A notificação de alerta corresponde a "а"; notificação sonora, a "s"; notificação de e-mail, a "e"; e notificação do tipo push, a "p". Além disso, você pode adicionar 1 ou 0 à string para indicar a barra em que os sinais são verificados (isso pode ser útil nos indicadores). O código é expresso como uma função cujo primeiro parâmetro é uma string seguida pela variável Shift (número da barra) retornada por referência e variáveis do tipo bool que correspondem a diferentes métodos de notificação. O código é fornecido com comentários detalhados:

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
  }

Agora, em vez de cinco variáveis na janela de propriedades, uma variável única será suficiente. 

 

Buffer de string

Ainda temos que analisar três funções padrão: StringInit(), StringFill() e StringBufferLen().

A função StringInit() preenche uma string com caracteres idênticos no número especificado:

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

Após a execução desse código, a variável str armazenará a string contendo "||||||||||". O caractere é especificado com o uso de seu código ASCII, ou seja, o caractere precisa ser inserido entre aspas simples.

A função StringFill() preenche uma string com caracteres idênticos sem alterar o tamanho da string. A continuação do exemplo anterior:

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

Após isso, a variável str armazenará a string contendo "//////////".

Agora vamos tentar preencher uma string com um caractere com código 0 (fim da string):

StringFill(str,0); 
Verifique o tamanho da string:
int Length=StringLen(str);
Alert(IntegerToString(Length)); 

O tamanho é igual a 0 e o caractere com código 0 está no ponto inicial da string. Verifique o tamanho do buffer:

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

O tamanho do buffer é diferente de 0 e excede o tamanho da string inicial. A memória alocada para a string é mais que suficiente. Agora, durante a atribuição de um valor para a string dentro do limite de tamanho do buffer, a realocação de memória não será requerida e o valor será atribuído muito rapidamente. Para assegurar que o tamanho do buffer não seja reduzido, o novo valor deverá ser adicionado à string, e não atribuído a ela:

str+="a"; 

Agora o comprimento da string é 1, enquanto que o tamanho do buffer permaneceu o mesmo. Dessa forma você pode acelerar um pouco o processamento das strings. É possível limpar uma string com a inserção do caractere com código 0 no início dela:

StringSetCharacter(str,0,0); 

 

Conclusão

Alguns poderiam pensar que o assunto deste artigo é de menor importância, apenas levemente relevante para o objetivo principal da linguagem MQL5, ou seja, o desenvolvimento de Expert Advisors e de indicadores. Entretanto, o que temos aqui é um artigo bem abrangente, inspirado pela ampla variedade de funcionalidades para trabalho com strings que a linguagem oferece. Não é improvável que, muitas vezes, durante a programação de Expert Advisors e de indicadores, você não precise lidar com strings, ainda que isso possa ser necessário algum dia. Após a leitura deste artigo, você está totalmente preparado para usar strings, como e quando necessário, sem perder tempo estudando as funções. Você será capaz de fazer facilmente o que é requerido.

Vamos recapitular as informações apresentadas no artigo, classificando as funções de acordo com a sua finalidade, importância e frequência de uso.

  1. StringLen(), StringFind(), StringSubstr(), StringReplace() e StringSplit() são funções-chave essenciais que são utilizadas para determinar o comprimento da string, buscar substring, obter e substituir uma substring bem como dividir uma string.
     
  2. StringTrimLeft(), StringTrinRight(), StringToLower() e StringToUpper() são funções auxiliares muito úteis que são usadas para apagar espaços nas extremidades e para alternar entre letras maiúsculas e minúsculas.
     
  3. ColorToString(), DoubleToString(), EnumToString(), IntegerToString(), TimeToString() e StringFormat() são funções que convertem variáveis numéricas para uma string.
     
  4. StringToColor(), StringToDouble(), StringToInteger(), StringToTime() e StringCompare() são funções que convertem uma string para uma variável numérica.
     
  5. StringAdd() e StringConcatenate() são funções que você pode usar para adicionar e combinar strings de forma eficiente em relação ao espaço.
     
  6. ShortToString(), ShortArrayToString(), StringToShortArray(), bem como CharToString(), CharArrayToString() e StringToCharArray() são funções para trabalhar com strings como arrays que podem ser úteis ao lidar com tarefas que requerem manipulações de string muito complexas. Da lista acima, podemos destacar duas funções que são especialmente importantes: 

    • CharToString() é usada para trabalhar com objetos gráficos juntamente com a fonte Wingdings,
    • CharArrayToString() é usada para preparar um parâmetro de string durante a chamada das funções API.

  7. StringSetCharacter(), StringGetCharacter(), StringInit(), StringFill() e StringBufferLen() são funções secundárias.

 

Arquivos anexos

  1. IncStrFunctions.mqh contém as funções Trim(), StringFindRev(), TrimL(), TrimR(), ParamsToArray() e NotifyOnOff().
  2. eMultiLanguageMessage.mq5 é um exemplo de um Expert Advisor que apresenta mensagens em diferentes idiomas.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/585

Arquivos anexados |
Últimos Comentários | Ir para discussão (1)
Mouzinho Lazaro
Mouzinho Lazaro | 25 mar 2023 em 10:20
Aqui fala se Português?
Como testar um robô de negociação antes da compra Como testar um robô de negociação antes da compra
A compra de um robô de negociação no Mercado MQL5 apresenta uma vantagem distinta em relação a todas as outras opções similares - um sistema automatizado oferecido pode ser inteiramente testado diretamente no terminal MetaTrader 5. Antes da compra, um Expert Advisor pode e deve ser cuidadosamente executado em todos os modos não favoráveis no Strategy Tester integrado para que você entenda completamente o sistema.
Aprendizagem de máquina: como as máquinas de vetores de suporte podem ser utilizadas nas negociações Aprendizagem de máquina: como as máquinas de vetores de suporte podem ser utilizadas nas negociações
As máquinas de vetores de suporte foram por muito tempo usadas em campos como de bioinformática e aplicava matemática para avaliar conjuntos de dados e extrair padrões úteis que podem ser usados para classificar dados. Este artigo visa em como é uma máquina de vetor de suporte, como trabalha e por que pode ser tão útil na extração de padrões complexos. Podemos investigar como elas podem ser aplicadas ao mercado e potencialmente usadas para aconselhar sobre negócios. Usando a Ferramenta de aprendizado da máquina de vetor de suporte, o artigo fornece exemplos trabalhados que permitem que os leitores experimentem com seus próprios negócios.
Fundamentos básicos da programação MQL5: Tempo Fundamentos básicos da programação MQL5: Tempo
Este artigo foca nas funções padrões do MQL5 para trabalhar com o tempo, bem como técnicas de programação e funções praticamente úteis para trabalhar com o tempo que são necessárias ao criar Expert Advisors e indicadores. Atenção particular é dedicada à teoria geral da medição de tempo. Este artigo deve ser de interesse principalmente para programadores MQL5 novatos.
Alterar os parâmetros do Expert Advisor instantaneamente a partir do painel de usuário Alterar os parâmetros do Expert Advisor instantaneamente a partir do painel de usuário
Este artigo fornece um pequeno exemplo demonstrando a implementação de um Expert Advisor em que os parâmetros podem ser controlados a partir do painel de usuário. Quando mudar os parâmetros para "rápidos", o Expert Advisor escreve os valores obtidos a partir do painel de informações para um arquivo para ler futuramente o arquivo e exibe de acordo no painel. Este artigo pode ser relevante para aqueles que negociam em modo manual ou semi-automático.