![MQL5 Programlama Temelleri: Dizeler](https://c.mql5.com/i/articles/overlay.png)
MQL5 Programlama Temelleri: Dizeler
Giriş
Dizeler veya daha doğrusu dize değişkenleri, karakter verilerini, yani metni, saklamak için kullanılır:
string str="Any text";
MQL5 dili, dizeler ile çalışılması için geniş bir kullanıcı dostu fonksiyonellik yelpazesi sunar. Dizeler, Uzman Danışmanların ve göstergelerin programlanmasında, çoğunlukla bilgi mesajlarını oluşturmak için kullanılır. Bunlar, göstergelerde belirli koşulların (örneğin alım satım sinyalleri) yerine getirilmesiyle ilgili mesajlar olabilirken Uzman Danışmanlarda alım satım faaliyeti sonuçlarını rapor edebilir. Bir Uzman Danışman, betik veya gösterge, çalıştırıldığında, kullanıcının ayarladığı parametreleri kontrol edebilir ve parametre setinin geçersiz olması durumunda bir bildirim yazdırabilir. Bildirimlerin yanı sıra, zaman zaman parametre ayarlarıyla ilgili önerilerde bulunan anlık mesajlar da görebilirsiniz. Genel olarak konuşursak, MQL5'te programlama yaparken, dizeler her şeyden önce kullanıcı dostu özellik sunar.
Dizeler, dosyalar ile çalışırken de çok önemlidir. Dosyalardan veri yazma ve okuma işlemi, dize değişkenleri kullanılarak gerçekleştirilir. Açık bir şekilde, dosyalar ile çalışmanın başka bir yolu olan sayısal değişkenleri ve dizileri okuma ve yazmayı sağlayan ikili bir yöntemi seçebilirsiniz. Ancak veri miktarı çok büyük değilse, metin dosyaları ve dizeleri kullanmak daha iyidir. Bu durumda, program çalışması kullanıcı için daha anlaşılırdır ve program geliştirme süreci daha basittir ve anında veri kontrolü sağlanır. Metin dosyası verileri program içindeki veriler ile aynı görünür.
Dizelerin kullanılması, gerekli sayıda parametrenin önceden bilinmediği durumlarda (örneğin derlemelerin ortalamasını elde etmek için lot boyutları) veri (parametre) girişiyle ilgili program özelliklerini büyük ölçüde genişletebilir. Böyle bir durumda değerler, tek bir dizede noktalı virgül gibi bir ayırıcı ile ayrılmış şekilde yazılabilir:
input string Lots="0.1; 0.2; 0.3; 0.5";
Bu durumda dize, Uzman Danışman başlatılırken bölünür ve sayısal değerlerin bir dizisi doldurulur. Ne yazık ki, optimizasyonda bu tür dize parametrelerinin üzerinden geçmek, yani ilk ve son değeri adım değeri ile birlikte ayarlamak imkansızdır. Bazı durumlarda, özellikler penceresinde büyük sayıda sayısal değişken kullanılması belki daha fazla tercih edilebilir. Ancak bunları sayıları neredeyse sınırsız olabileceği için, bir kolaylık ve amaç sorunuyla (optimizasyon olasılığının gerekli olup olmadığına dair) karşı karşıya kalabiliriz.
Bir parametrenin optimizasyonunun gerekli olmadığının bilindiği, örneğin bildirimleri etkinleştirme gibi başka durumlar da olabilir. MQL5 birçok kullanıcı bildirim yöntemini destekler: sesli bildirimler, açılır bildirimler, e-posta bildirimleri ve anlık bildirimler. Bu bildirimlerin her biri için özellikler penceresinde bir bool tipi anahtar oluşturabilir (en az dört değişken gerektirir) veya değişken sayısını bir dize değişkenine düşürebilirsiniz.
Sesli bildirimleri etkinleştirmeniz gerekiyorsa "s" (ses) yazarsınız. E-posta bildirimlerine de ihtiyacınız varsa, "e" eklersiniz. Böylece, yalnızca bir değişken kullanarak bildirimlerin herhangi bir kombinasyonunu etkinleştirebilirsiniz. Bir Uzman Danışman için harici parametrelerin sayısının pek de önemi yoktur. Bu sadece bir kullanıcı dostu olma meselesidir.
Diğer yandan, göstergeler geliştirirken harici parametrelerin sayısını düşürmeye çalışmalısınız. Parametre sayısı sınırlı (iCustom() yalnızca 64 parametreye sahiptir ve IndicatorCreate() fonksiyonunun parametre dizisi sayısı 64 öğedir) iCustom() veya IndicatorCreate() fonksiyonlarını kullanarak göstergenin bir Uzman Danışmandan veya başka bir göstergeden çağrılması çok olasıdır. Dolayısıyla, dizelerin kullanımı büyük pratik öneme sahip olabilir.
Bu makale, dizeler ile çalışmak için tüm standart MQL5 fonksiyonlarını gözden geçirecektir ve buna ek olarak birkaç kullanışlı özel fonksiyon oluşturacağız.
Bir Dize Değişkenini Bildirme
Diğer tüm değişken türleri gibi, dize değişkenleri de bildirilebilir:
string str;
veya bildirildikten sonra bunlara bir değer atanabilir (bir değere başlatılabilir): string str="Any text";
Dizenin uzunluğuna dair herhangi bir kısıtlama yoktur. Kolaylık sağlamak için uzun bir dize birkaç alt dizeye bölünebilir:
string str= "A long string can be " "split into several " "substrings"; //--- output the results Alert(str);
Bu şekilde başlatıldığında, str değişkeni "Uzun bir dize birkaç alt dizeye bölünebilir" ifadesini içeren dizeye sahip olacaktır.
Biraz ileri gidersek, parametresiz olarak bildirilen bir dize değişkeninin değerinin boş bir dize ile aynı olmadığını belirtmeliyiz:
string str="";
Kendiniz bakın:
string str1; string str2=""; //--- output the comparison results Alert(str1==str2);
Bu kodu çalıştırırken, uyarıcı "false" penceresi açılacaktır. Başlatılmamış dize değişkeninde, boş bir "" dize ile aynı olmayan NULL (BOŞ) değeri vardır. Bunu aklınızda tutmalısınız! Dizeler ile çalışırken, genellikle bir dizenin boş olup olmadığını kontrol etmemiz gerekir. Bu nedenle, tüm dizeleri boş bir "" dizesiyle başlatma kuralına bağlı kalmalı veya bunların "" öğesiyle eşit olmadıklarını ve BOŞ öğesiyle eşit olmadıklarını kontrol etmelisiniz:
if(str!="" && str!=NULL) { //--- some operation with a string }
İlk yöntem, kontrol koşulunu basitleştirmesinden ötürü daha çok tavsiye edilir.
Bir değişkenin boyutunu kontrol ederken de aynı işlemi yapabilirsiniz. Boyutu belirlemek için StringLen() fonksiyonunu kullanırız:
if(StringLen(str)!=0) { //--- some operation with a string }
Birleştirme Dizeleri
Dizeler ile çalışırken gerçekleştireceğiniz temel ve en yaygın işlem bunları birleştirmektir, diğer bir deyişle sözcükleri kullanarak cümleler oluşturmaktır. Birleştirme "+" işareti kullanılarak gerçekleştirilir:
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);
Bu kodun çalıştırılmasının ardından str4 değişkeni "MQL5'te Programlama" ifadesini içerirken str5 değişkeni "MetaTrader 5 için Programlama" ifadesini içerecektir. Yukarıdaki örnek iki dizeyi nasıl birleştirebileceğinizi göstermiştir, burada ortaya çıkan dize başka bir değişkene atanır.
Ek bir dize genellikle ana dizeyle birleştirilir:
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);
Bu kodu çalıştırdıktan sonra, str1 dizesi "MetaTrader 5 için MQL5'te Programlama" ifadesini içerecektir. Yukarıdaki örnek, ana str1 dizesi ile dizeleri nasıl birleştirebileceğinizi göstermiştir, burada sonuç ikinci dizeye atanmıştır. Aynı işlemler çok daha basit bir şekilde yazılabilir:
str1+=str2; str1+=str3;veya
str1+=str2+str3;
"=" öğesinin solundaki "+" işareti, "=" öğesinin sağındaki ifadenin str1 değişkenine eklendiği anlamına gelir.
Ana dizenin başına da bir dize ekleyebilirsiniz. Bu, ikinci ila son örnekte gösterildiği gibi uygulanabilir: ana dize ek dizeye eklenir ve ortaya çıkan dize ana değişkene atanır:
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şağıdaki ifade: "MetaTrader 5 için MQL5'te programlama" artık str3 değişkeninde yer alacaktır. Bunu tek bir dize kullanarak da uygulayabilirsiniz:
str3=str1+" "+str2+" "+str3;Bazı durumlarda birleştirme işlemi "," (virgül) kullanılarak yapılabilir. Bu, Alert(), Print() veya Comment() fonksiyonlarını çağırırken mümkündür:
Print(str1," ",str2," ",str3);
Bu durumda nihai sonuçlar "+" işaretinin kullanılması ile aynı olacaktır:
Print(str1+" "+str2+" "+str3);
"," sembolü aslında dizeleri birleştirmez. Virgül, tüm fonksiyonlardaki parametrelerin ayırıcısıdır. Bu Alert(), Print() ve Comment() fonksiyonları için de doğrudur. Bu fonksiyonlarda zorunlu parametreye ve birçok isteğe bağlı parametre bulunur. Parametreler aslında birleştirildikleri fonksiyona aktarılır. Maksimum parametre sayısı 64'tür.
FileWrite() fonksiyonunu kullanarak bir dizeyi bir dosyaya yazarken de benzer bir şey görebiliriz. Ancak, bir dosyayı FILE_CSV modunda (alan ayırıcılar ile) açarsanız, virgüller dosya açılırken belirtilen ayırıcı karakter ile değiştirilir (ayırıcı belirtilmemişse varsayılan olarak sekme kullanılır). Bir dosyayı ayırıcı belirtmeden FILE_TXT modunda açarken, "+" işareti ve "," öğesi kullanmanın sonuçları aynı olacaktır:
//--- 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);
Bu kodu çalıştırdıktan sonra, 1.txt dosyası "1 2 3" ifadesini içerirken 2.txt dosyası ise "123" ifadesini içerecektir (dosyalar FILE_CSV modunda açılmıştır). 3.txt ve 4.txt dosyasında aynı içerik olacaktır: "123" (FILE_TXT modunda açılmıştır). Bu makale, dosya işlemlerine odaklanmamaktadır. Bu nedenle, son örnekte anlamadığınız herhangi bir şey varsa, bu makalede daha ayrıntılı olarak belirtilen materyali anlamanızı etkilemeyeceği için dikkate almayın. "+" ve "," kullanmanın, dizelerin eklenmesini ele alırken her zaman aynı etkiyi yaratmadığını unutmayın.
MQL5, "+" işaretine ek olarak, dizelerin eklenmesi için de özel fonksiyonlar sağlar: StringAdd() ve StringConcatenate(). Bu fonksiyonlar, MQL5 Referansındaki açıklamasına göre, dizeleri daha fazla alan verimli (dolu çalışan bellek açısından) ve daha hızlı bir şekilde eklememize olanak sağlar. StringAdd() fonksiyonu, bir dizeyi başka bir dizeye eklememize olanak sağlar:
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);
Bu kodu çalıştırdıktan sonra, str1 değişkeninde "MetaTrader 5 için MQL5'te Programlama" ifadesini içeren dize yer alacaktır.
StringConcatenate() fonksiyonu, birkaç dizeyi eş zamanlı olarak birleştirmenize olanak sağlar. Fonksiyona aktarılan ilk parametre, listelenen diğer dizelerin ekleneceği dize değişkenidir. Fonksiyona aktarabileceğiniz maksimum parametre sayısı 64'tür:
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);
Bu kodu çalıştırdıktan sonra str1 değişkeni "MetaTrader 5 için MQL5'te Programlama" ifadesini de içerecektir.
Çeşitli Değişkenleri Bir Dizeye Dönüştürme
Bir mesaj dizesi oluştururken, genelde sayısal değişkenlerin değerlerini eklememiz gerekir. Tamsayı değişkenlerini (char, uchar, bool, short, ushort, int, uint, color, long, ulong, datetime) bir dizeye dönüştürmek için IntegerToString() fonksiyonunu kullanırız:
int x=1; string str="x = "+IntegerToString(x);
Bir bool türü değişkeni dönüştürürken, döndürülen bir dize "0" (false) veya "1" (true) değerini içerecektir. Benzer şekilde, color (renk) veya datetime (tarih/saat) türünde değişkenlerini dönüştürürseniz, döndürülen bir dize, renk veya tarihin sayısal bir ifadesini içerecektir (örneğin clrYellow sarı rengi için "65535" veya aşağıdaki tarih için "1325376000": 2012.01.01 00:00).
Real (gerçek) değişkenleri (double, float) bir dizeye dönüştürmek için DoubleToString() fonksiyonunu kullanırız. Bu fonksiyonun ikinci parametresi hassasiyeti (ondalık basamak sayısı) belirler:
double x=1.23456; string str1="x = "+DoubleToString(x,2); string str2="x = "+DoubleToString(x,3);
Bu kodu çalıştırdıktan sonra str1 değişkeni "1,23" dizesini içerirken str2 değişkeni "1,235" dizesini içerecektir. Belirtilen basamak sayısına kesme işlemi, matematiksel yuvarlama kuralları ile gerçekleştirilir.
TimeToString() fonksiyonu, tarihi ve saati, standart bir biçim dizesine (insanlar tarafından kolayca anlaşılabilir) dönüştürmek için kullanılır:
datetime tm=TimeCurrent(); // Current time string str1=IntegerToString(tm); string str2=TimeToString(tm);
Bu kodu çalıştırdıktan sonra str1 değişkeni, sayısal bir zaman ifadesine (1 Ocak 1970'den bu yana geçen saniye sayısı) sahip dizeyi içerirken str2 değişkeni ise biçimlendirilmiş zamanı, örneğin "2012.11.02 22:00" (yıl, ay, gün, saat, dakika) içerecektir.
TimeToString() fonksiyonunu çağırırken, tarih ve saat biçimini belirtme seçeneğiniz vardır. Kullanılabilir seçenekler şunlardır:
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, program özellikleri penceresinde açılır seçenekler listesi şeklinde görüntülenen numaralandırmaları oluşturmak için harika bir kullanışlı özellik sunar. Bu tür değişkenlerin değerleri, EnumToString() fonksiyonu kullanılarak bir dizeye dönüştürülebilir. Aşağıda, bu fonksiyonun çalışmasını gösteren betik kodu yer almaktadır:
//+------------------------------------------------------------------+ //| 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); }Renk değişkenlerini dönüştürmenize olanak sağlayan benzer bir imkan vardır. ColorToString() fonksiyonunu kullanarak renk değerini rengin adına dönüştürebilirsiniz:
color ColorValue=clrRed; string str=ColorToString(ColorValue,true);
Bu kodu çalıştırdıktan sonra, str değişkeni "clrRed" içeren diziyi saklayacaktır. İkinci parametre false olarak ayarlanırsa, fonksiyon dizeyi RGB (kırmızı, yeşil ve mavi) bileşenlerinin değerleriyle döndürür:
color ColorValue=clrRed; string str=ColorToString(ColorValue,false);
Bu durumda, str değişkeninde saklanan dize "255,0,0" olacaktır. Ele aldığınız renk standart bir renk değilse (web renk paletinde tanımlanmadıysa ve dolayısıyla bir adı yoksa), ColorToString() fonksiyonu, ikinci parametre değerine bakılmaksızın dizeyi bileşenlerin değerleriyle döndürmek için kullanılabilir.
Ancak, type casting (tür kalıbı) kullanarak değişkenleri dönüştürmek yöntemi de vardır:
int x=123; string str=(string)x;
Bir bool türündeki değişken bu şekilde dönüştürüldüğünde, dize değeri "true" veya "false" olacaktır:
bool x=true; string str=(string)x;
Double ve float türündeki değişkenleri dönüştürmek, mümkün olduğunca kesin hassas ve kesirli kısımda yalnızca sıfırlar bırakılmasını sağlamalıdır:
double x1=0.1; double x2=0.123; string str1=(string)x1; string str2=(string)x2;
Bu kodu çalıştırdıktan sonra, str1 değişkeni "0,1" dize değerini saklayacak ve str2 değişkeni "0,123" dize değerini içerecektir.
Özel Karakter Çıktısı
Bir dize değişkenini bir değere başlatırken, atanabilir dize çift tırnak işareti içinde yazılmalıdır, böylece derleyici dizeyi program kodundan ayırt edebilir. Tırnak işaretlerini dizenin içine koyabilmek için, işaretlerin burada olağan amaçlarıyla (bir dizeyi koddan ayıran karakterler olarak) değil, bir dizenin parçası olarak kullanıldığını belirtmeniz gerekir. Bunu gerçekleştirmek için, tırnak işaretinin hemen önüne bir ters eğik çizgi "\" koyun:
string str1="Simple text"; string str2="\"Text in quotes\""; //--- output the results Alert(str1); Alert(str2);
Ters eğik çizgi aynı zamanda bir özel karakter olarak kabul edildiğinden, bir dizede ters eğik çizginin çıktısını uygulamak için bunun önüne başka bir ters eğik çizgi konmalıdır:
string str="\\"; Alert(str);
Bu kodu çalıştırdıktan sonra, dizenin içereceği tek karakter "\" olacaktır.
Bir dize, "\t" ile temsil edilen yatay bir sekme karakteri de içerebilir:
string str="Column-1\tColumn-2\tColumn-3"; Alert(str);
Bu durumda, str değişkeninde "Sütun-1 Sütun-2 Sütun-3" ifadesini içeren dize olacaktır.
Bir metin, "\n" ifadesi kullanılarak birkaç satıra bölünerek satır sonları ile de yazdırılabilir:
string str="Line-1\nLine-2\nLine-3"; Alert(str);
Alert() fonksiyonunu yürütmenin sonucunda burada üç satırlık metniniz olacak.
Alert() ve MessageBox() fonksiyonlarını kullanarak yazdırırken ve bir dosyaya yazarken hem "\t" hem de "\n" ifadelerini kullanabilirsiniz. Ancak, bir grafik yorumuna yazdırırken (Comment() fonksiyonu), kaydırma karakteri olarak yalnızca "\n" uygulanır ve "\t" sekme karakteri yok sayılır. Print() fonksiyonu kullanılarak çıktı oluşturulduğunda, "\n" daha önceki gibi uygulanır (bir dizenin her parçası günlüğün ayrı bir satırında çıkarılır) ve "\t" Print() fonksiyonunu kullanarak tüm mesajların çıktısını saklayan günlük dosyasındaki gibi bir boşlukla değiştirilir.
Dizeleri Model Tabanlı Biçimlendirme
Çıktı için bir dize biçimlendirirken, buna birkaç sayısal değişkenin değerlerini dahil etmeniz gerekebilir. Bu işlem, dizeleri ekleyerek ve sayısal değişkenleri dizelere dönüştürerek yapılabilir. Ancak bu durumda, bir mesaj oluşturan kod dizisi çok uzun olacak ve bunun anlaşılması ve programda herhangi bir değişiklik yapılması gerektiğinde düzenlenmesi zor olacaktır:
//--- 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);
Aynı iş, StringFormat() fonksiyonu kullanılarak çok daha kolay bir şekilde yapılabilir. Bu fonksiyona aktarılan ilk parametre, değişkenleri eklemek ve çıktı biçimini ayarlamak için belirtilen yerleri içeren bir mesaj şablonudur. Bundan sonra, şablonda göründükleri sırayla tüm değişkenlerin numaralandırılması gelir:
//--- 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);
Değişkenlerin yerleştirileceği yerler "%" ve daha sonra "i" ile işaretlenir; yukarıdaki örnekte bu, değişkenlerin tamsayı olarak çıkarılması gerektiğini belirtir. Veya bunun yerine, "i" karakter tamsayı değişkenlerini (char, short, int, color) temsil ederken "u" işaretsiz tamsayı değişkenleri (uchar, bool, ushort, uint) için kullanılır. long, ulong ve datetime veri türündeki değişkenler için, değişkenin boyutunu da türün önüne "I64" koyarak belirtmelisiniz:
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);Bu kodun sonucunda değişken değerlerini içeren bir açılır pencere göreceksiniz.
Gerçek sayıların biçimi "f" ile gösterilir:
double Percents=5.5; //--- real number as a string string str=StringFormat("Percents = %f",Percents); //--- output the results Alert(str);
Bu kodu çalıştırdıktan sonra, str değişkeni dizeyi aşağıdaki şekilde saklayacaktır: "Yüzde = 5,500000". Varsayılan çıktı hassasiyeti altı ondalık basamaklıdır. Gerekli ondalık basamak sayısını ayarlayabilirsiniz:
string str=StringFormat("Percents = %.2f",Percents);
Bunun için, bir ondalık sembolünü belirten bir nokta ve hemen ardından ondalık basamak sayısını, örneğin yukarıdaki örnekteki 2, ekleyin. Bu durumda, str değişkeni dizeyi aşağıdaki şekilde içerecektir: "Yüzde = 5,50". Bu biçimlendirme seçeneği, DoubleToString() fonksiyonu ile tamamen aynıdır.
Bir sayının toplam uzunluğunu "%" işaretinden hemen sonra "0" ve elimizdeki sayının uzunluğunu belirleyen bir sayı yazarak belirtebilir ve ardından (gerekirse) ondalık basamak sayısını belirtebilirsiniz:
string str=StringFormat("Percents = %06.2f",Percents);
Burada, biri ondalık noktası için kullanılacak ve ikisi iki ondalık basamağı temsil edecek 6 basamaklık toplam uzunluğumuz var. Bu nedenle, str değişkeninde saklanan dize "Yüzde = 005,50" olacaktır.
Bir mesajda "%" yüzde işareti çıktısını almanız gerekiyorsa, bunu iki kez arka arkaya yazmanız gerekir, yani "%%", çünkü bunlardan biri değerlerin girileceği yerleri belirtmek için kullanılacaktır:
string str=StringFormat("Percents = %06.2f%%",Percents);
Bu durumda, str değişkeni "Yüzde = %005,50" ifadesini içerecektir.
Tamsayı değişkenlerinin çıktısını alırken bir sayının uzunluğunu da belirleyebilirsiniz:
int Variable=123; //--- integer as a string with a set output length string str=StringFormat("Variable = %05i",Variable); //--- output the results Alert(str);
Bu kodu çalıştırdıktan sonra, str değişkeni aşağıdaki dizeyi saklayacaktır: "Değişken = 00123".
Belirtilen basamak sayısı, sayıdaki basamak sayısından daha az bile çıktı doğru şekilde yapılacaktır:
string str=StringFormat("Variable = %02i",Variable);
Burada str değişkeni dizeyi aşağıdaki gibi içerecektir: "Değişken = 123", diğer bir deyişle belirtilen uzunluk 2 olmasına rağmen çıktı sayısı 3 basamaklı olacaktır.
Gerçek sayılar, "e" karakterini kullandığımız bilimsel gösterim (altı ondalık basamak ve kuvvetten oluşan mantis) kullanılarak çıktılanabilir:
double Variable=123.456; //--- real number as a string in scientific notation string str=StringFormat("Variable = %e",Variable); //--- output the results Alert(str);
Bu kodu çalıştırdıktan sonra str değişkeni "1,234560e+002" değerini alacaktır. Biçimlendirilmiş bir dizede "e" küçük harfine benzeyen "E" büyük harfini kullanabilirsiniz, "E" büyük harfi "e" küçük harfinin yerini alacaktır.
Gerçek sayıları biçimlendirmenin başka bir yolu daha vardır: "g" kullanmak; bu sayede yalnızca altı basamak (herhangi bir ondalık noktası hariç) çıktılanabilir. Bir sayının tamsayı kısmının uzunluğu altı basamağı geçerse, sayı bilimsel gösterim yoluyla çıktılanacaktır:
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);
Yukarıdaki örnekte, str1 değişkeni "12,3457" ifadesini içerecek ve str2 değişkeni "1,23457e+006" ifadesini içerecektir. Bunun yerine "G" büyük harfini kullansanız da etki aynı olacaktır, tek fark çıktıda "g" küçük harfinin "G" büyük harfi ile değiştirilecek olmasıdır.
StringFormat() fonksiyonu, sayı gösterim biçimlerini dönüştürmenize, diğer bir deyişle, ondalık sistemin sayılarını sekizli veya on altılı sisteme dönüştürmenize olanak sağlar. Bir sayıyı sekizli sisteme dönüştürmek için "o" karakterini kullanmanız gerekir:
int Variable=17; //--- real number as a string in the octal system string str=StringFormat("Variable = %o",Variable); //--- output the results Alert(str);
Bu kodu çalıştırdıktan sonra, str değişkeni dizeyi aşağıdaki şekilde saklayacaktır: "Değişken = 21" (8*2+1=17).
Bir sayıyı onaltılık sisteme dönüştürmek için "x" veya "X" kullanılır. Bu durumda bir onaltılık sistem numarası, "x" küçük harfini kullanırsanız küçük harflerden veya "X" büyük harfi kullanırsanız büyük harflerden oluşacaktır:
color Variable=clrBlue; //--- real number as a string in the hexadecimal system string str=StringFormat("Variable = %x",Variable); //--- output the results Alert(str);
Bu kodu çalıştırdıktan sonra str değişkeni "Değişken = ff0000" ifadesini içerecektir.
Benzer şekilde, bir dizi onaltılık sistemi "d" karakterini kullanarak yeniden ondalık sisteme dönüştürebilirsiniz:
int Variable=0x0000ff; //--- real number as a string in the decimal system string str=StringFormat("Variable = %d",Variable); //--- output the results Alert(str);
Bu kodu çalıştırdıktan sonra, str değişkeninin saklayacağı dize "Değişken = 255" olacaktır.
"s" karakteri, dize değişkenlerinin çıktısını almak için kullanılabilir:
string Variable="text"; //--- output the string variable string str=StringFormat("Variable = %s",Variable); //--- output the results Alert(str);
Yukarıdaki kodu çalıştırdığınızda, "Değişken = metin" içeren dize str değişkeninde saklanacaktır.
Negatif sayıların "-" işareti nedeniyle kaydığı gerçeği göz önüne alındığında, bazen sayıları bir sütuna çıkarırken hizalamanız gerekebilir. Pozitif sayıları negatifler ile hizalamak için, dizenin başına "%" işaretinden hemen sonra bir boşluk eklemelisiniz. Bu durumda negatif sayılar, başında boşluk olacak pozitif sayıların aksine, boşluksuz olarak çıktılanacaktır:
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);
Bu kodu çalıştırdıktan sonra, str1 değişkeni "Variable1= 01" (boşluklu dize) içerirken str2 değişkeni dizeyi aşağıdaki şekilde saklayacaktır: "Variable2=-01".
StringFormat() fonksiyonuna benzer iki fonksiyon daha vardır. Bunlar, eylem açısından kesinlikle aynı olan PrintFormat() ve printf() fonksiyonlarıdır. StringFormat() fonksiyonundan tek farkları, metni günlüğe Print() fonksiyonuna benzer bir şekilde yazdırmalarıdır.
Aslında, StringFormat() fonksiyonu çok daha fazla fonksiyonellik sunarken, yukarıda sağlanan materyal, çıktı için sayıları biçimlendirmeye dair sorunların büyük bir kısmını çözmek için gerekli minimum değeri temsil eder.
Farklı Dillerdeki Mesajlar
StringFormat() fonksiyonu, terminalde ayarlanan arayüz diline bağlı olarak mesajların farklı dillerde yazdırılmasını sağlayan oldukça kullanışlı bir özellik ile size programınızı geliştirme olanağı sağlar.
Hangi arayüz dilinin ayarlandığını TERMINAL_LANGUAGE tanımlayıcısı ile TerminalInfoString() fonksiyonunu çağırarak öğrenebilirsiniz. Bir programı çalıştırırken, arayüz diline göre bir biçim dizesi hazırlarız ve ardından bunu programda kullanırız. Aşağıda, yukarıdaki özelliğin uygulandığı bir Uzman Danışman şablonu yer almaktadır:
//--- 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"); }
Uzman Danışman, rastgele iki sayının toplamını hesaplar ve bunların eylemleriyle ilgili mesajın çıktısını sağlar, örneğin "1 artı 2 3 eder".
Dizelerin çıktısı ile ilgili neredeyse hepsi bu. Şimdi biraz daha karmaşık, ancak daha ilginç dize manipülasyonlarına geçeceğiz.
Dizeler ile Çalışmak için Kilit Fonksiyonlar
Bir dize program özellikleri penceresinden girildiğinde veya bir dosyadan okunduğunda gereksiz boşluklar içerebilir. Bunların nedeni, kullanıcının olağan bir dikkatsizliği veya rahatlık olabilir. Dizeyi herhangi bir şekilde kullanmadan önce, sol ve sağ uçtaki boşlukları silmeniz önerilir. Bunun için, MQL5 iki fonksiyon sunar: StringTrimLeft() (sol uçtaki boşlukları siler) ve StringTrimRight() (sağ uçtaki boşlukları siler). Bu fonksiyonlar, boşluklara ek olarak sekme ve yeni satır karakterlerini de kaldırır. Dizeler ile çalışırken, genellikle her iki uçtaki boşlukları tek seferde silmemiz gerekir, dolayısıyla bunu sağlayan bir fonksiyon çok faydalı olacaktır:
string Trim(string Str) { StringTrimLeft(Str); StringTrimRight(Str); return(Str); }
Gerçek sayıları girerken, kullanıcı genellikle virgül yerine nokta koyabilir. Bu nedenle gerçek sayılarla çalışırken ondalık sembol olarak hem nokta hem de virgül kullanma imkanı sağlamalısınız. Bir dizeyi diğeriyle değiştirmek için StringReplace() fonksiyonunu kullanırız:
string str="123,456"; //--- replace a comma with a dot StringReplace(str,",","."); double Value=StringToDouble(str); //--- output the results Alert(DoubleToString(Value));
"." işaretini "," ile değiştirmezseniz, bir dize sayıya dönüştürülürken sayının kesirli kısmı kesilecektir.
Bazı durumlarda, bir boşluk serisini tek bir boşluk ile değiştirmeniz gerekebilir. Bunun için, ilk olarak sekme karakterlerini bir boşluk ile değiştirmeli ve ardından yalnızca bir boşluk kalana kadar iki boşluğu bir boşluk ile değiştirmelisiniz:
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);
StringReplace() fonksiyonu, bir hata durumunda yapılan değiştirme sayısını veya -1'i döndürür. Böylece döngü, tüm boşluk serileri her bir tekli durumda bir boşluk kalıncaya kadar sıfırdan büyük bir değer döndüren fonksiyonla devam eder. Döngünün gövdesi herhangi bir kod içermez. Her yinelemede döngü koşulunu kontrol ederken StringReplace() fonksiyonunu çağırırız.
StringReplace() fonksiyonu, farklı uzunluklardaki alt dizileri değiştirmemize olanak sağlar:
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);
Bu kodu çalıştırırken, ilk değiştirmeden sonraki str değişkeni "MetaTrader 5 için Programlama" ifadesini ve ikinci değiştirmeden sonra MQL5'te Programlama!" ifadesini içeren dizeye sahip olacaktır.
StringFind() fonksiyonu, bir alt dizeyi aramak için kullanılır. Bir dizede alt dizenin ilk görülmesinin indisini döndürür. Fonksiyona aktarılan ilk parametre, aramanın gerçekleştirildiği dizedir. İkinci parametre hedef alt dizeyi belirlerken üçüncü parametre (isteğe bağlı) aramanın başladığı konumu belirleyebilir. Üçüncü parametre belirtilmezse, fonksiyon, değeri 0'mış gibi çalışır, yani arama dizenin en başından başlar. "MetaTrader 5 için MQL5'te Programlama" dizesindeki "5" alt dizesinin konumunu bulalım:
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));
Bu kodu çalıştırdıktan sonra Pos değişkeni değeri 23 olacaktır. Alt dize "5" toplamda iki kez görülür, ancak fonksiyon yalnızca ilk görülme konumunu döndürür. Sadece dizeye bakarak konumu sayarsanız, 24'e ulaşırsınız. Mesele şu ki, fonksiyon bir yerine sıfırdan saymaya başlar. Hedef alt dize bu dizede bulunamazsa, fonksiyon -1 değerini döndürür.
Bazen, alt dizenin son görülmesinin konumunu bulmanız gerekebilir. Bunun için StringFindRev() adında özel bir fonksiyon yazmamız gerekecek. Alt dizenin ilk görülmesini aramaya başlayacağız, ardından aramanın başlangıcını bir döngüde bulunan konuma vb. göre kaydıracağız:
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); }Bu fonksiyonu kullanmaya çalışalım:
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);
Bu kodu çalıştırdıktan sonra Pos değişkeni 40 değerinde olacaktır.
StringSubstr() fonksiyonu, belirli bir konumdan belirli bir uzunlukta bir alt dize elde etmek için kullanılır. 1 uzunluğunda alt dizeyi 23 konumundan alma:
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);
Ortaya çıkan rakam "5" olur.
Şimdi ana fonksiyonları ele aldığımıza göre, bunları, bir dizeden belirli bir karakter listesini silmek için faydalı bir fonksiyon yazmak için kullanalım. Fonksiyon, kaynak dizeyi ve kaynak dizeden silinecek karakterlerin listesini temsil eden bir dizeyi alır.
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)); }
Fonksiyon, varsayılan olarak sekmeyi ve yeni satır karakterini ve bir boşluk ve noktalı virgül ";" öğesini siler.
Sağ uçtan silme işlemi için aynı fonksiyon:
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)); }
Bu fonksiyon ayrıca, varsayılan olarak sekmeyi ve yeni satır karakterini ve bir boşluk ve noktalı virgül ";" öğesini siler. Bu durum, CSV dosyalarını okurken faydalı olabilir. Bu dosyaların içinde, bir dizenin sağ ucunda çok sayıda alan ayırıcı (genellikle noktalı virgül ";") olabilir.
Büyük ve küçük harfler, örneğin "А" ve "а, insanlar için anlam olarak farklı görülmezken bilgisayarlar bunları tamamen farklı iki karakter olarak ele alır. SymbolInfoDouble() fonksiyonunu kullanarak piyasa verilerini talep ederken "EURUSD" yerine "eurusd" yazarsanız, fonksiyon gerekli değeri döndürmez. Sembol adını özellikler penceresine girerken bunun meydana gelmesi çok olasıdır. MQL5'te büyük/küçük harf değiştirmek için StringToLower() fonksiyonunu (küçük harfe geçmek için) ve StringToUpper() fonksiyonunu (büyük harfe geçmek için) kullanabilirsiniz:
string str="EuRuSd"; string str1=str; string str2=str; //--- change the case of strings StringToUpper(str1); StringToLower(str2); //--- output the results Alert(str1," ",str2);
Bu kodu çalıştırdıktan sonra, str1 değişkeni "EURUSD" içeren dizeyi saklarken str2 değişkeninde "eurusd" içeren dize olacaktır.
İhtiyacınız olan şey büyük/küçük harf durumlarını dikkate almadan dizeleri karşılaştırmak ise, StringCompare() fonksiyonu en uygunu olacaktır. Fonksiyonun ilk iki parametresi karşılaştırma amaçlı dizelerdir. Üçüncü parametre, dizelerin, büyük/küçük harf olma durumlarını dikkate alarak (true) mı yoksa almadan (false) mı karşılaştırılacağını belirler:
int Result=StringCompare("eurusd","EURUSD",false); Alert(Result);
Fonksiyon 0 döndürürse, dizeler aynıdır. Fonksiyon, ilk dize ikinciden küçükse -1 veya ilk dize ikinciden büyükse 1 döndürebilir. "Küçük" ve "büyük", alfabetik olarak sıralandığında dizenin durumu anlamına gelir. "b" harfi "a" harfinden büyüktür:
int Result=StringCompare("a","b",true); Alert(Result);
Bu durumda fonksiyon -1 döndürür.
Şimdi, diğer fonksiyonlara geçmeden önce, araya kısa bir teorik açıklama girmemiz gerekiyor.
İnsanlar ve Bilgisayarlar Tarafından Görüldüğü Şekliyle Dizeler
Bir insan için bir dizenin ne olduğu oldukça açıktır: karakterlerden oluşan bir metin. Bilgisayar, bir insana kıyasla, yapı olarak biraz daha basittir, sadece sayılar ile ilgilenir. Bilgisayar görüntüleri, dizeleri ve diğer her şeyi sayı olarak görür. Bir dize, bir karakterin bir sayıya, daha doğrusu bir koda, başka bir karakterin başka bir koda vb. karşılık geldiği bir sayı dizisidir. Bu kodlar ASCII (Bilgi Değişimi İçin Amerikan Standardının kısaltması) kodları olarak adlandırılır. Aşağıda, 256 kod içeren genişletilmiş ASCII anlamına gelen ASCII terimini kullanacağız. Dolayısıyla bilgisayar "alfabesinin" 256 karakterden oluştuğunu söyleyebiliriz. Tıpkı farklı halklar ve diller için farklı alfabeler olduğu gibi, bilgisayarın da çeşitli karakter kümeleri vardır: kod sayfaları. Rusya'daki bilgisayar kullanıcıları çoğunlukla Latin ve Kiril karakterlerini ve sayıları, noktalama işaretlerini ve diğer bazı sembolleri içeren bir karakter kodlaması olan Windows-1251'i kullanır. Şekil 1 Windows-1251 kod sayfasını gösterir:
Şekil 1. Windows-1251 kod sayfası.
İlk 32 karakter görüntülenmez, bunlar kontrol karakterleridir. Bunlar görüntülenmez, ancak diğer karakterlerin görüntülenmesini etkiler, örneğin sekme (kod 9), satır besleme (kod 10), vb.
Orta Avrupa dillerinde metinleri temsil etmek için kullanılan kodlama Windows-1250'dir (Şekil 2):
Şekil 2. Windows-1250 kod sayfası.
Lütfen, kod sayfası 1251'in Rus alfabesinin harflerini içerdiği kod 192'den başlandığında kod sayfası 1250'nin Avrupa dillerinde aksan işaretleri (ses değerindeki küçük değişiklikleri belirleyen aksan işaretli harfler) içeren harflere sahip olduğunu unutmayın.
256 karakter çok küçük bir sayıdır. Zorluk, bir metnin birkaç dilde yazılması gerektiğinde ortaya çıkar, örneğin Rusça ve Fransızca (çok sayıda aksan işareti vardır) veya İngilizce ve Arapça (karakterler diğer dillerdeki karakterlerden çok farklıdır). Çince ve Japoncada olduğu gibi binlerce karakter içeren hiyeroglif yazıları da vardır ve bu durumda zorluklar daha da belirgin hale gelir. Kod sayfalarında yer almayan karakterleri başka bir şekilde kodlamanız gerekebilir. HTML'ye aşina olanlarınız, bir HTML sayfasına standart olmayan karakterler ekleme imkanını bilecektir, örneğin À kodu À ve Á öğesini görüntülemek; Á öğesini dönüştürmek vb. için kullanılır.
Yakın zamanda, bir karakterin tek bir baytta (0'dan 255'e kadar bir sayı) değil, iki baytta kodlandığı ve böylece toplam 65536 karaktere ulaştığı Unicode kodlamasını kullanmak yaygınlaşmıştır. Bu karakter seti, dünyada var olan tüm alfabelerin harflerini ve hatta Şekil 3'te gösterildiği gibi en yaygın hiyeroglifleri içerir (yine de uygun yazı tipleri bilgisayarınızda yüklü olmalıdır):
Şekil 3. Farklı alfabelerin ve hiyerogliflerin harfleri.
MQL5'teki dizeler Unicode kullanılarak kodlanır. Diğer bir deyişle, bir dizedeki bir karakter, 0 ile 65535 arasında bir sayı ile temsil edilebilir. 0'dan 127'ye kadar kodlu karakterler ASCII ve Unicode'da aynıdır. Metin dosyaları, ASCII veya Unicode kullanılarak kodlanmış metinler içerebilir ve bunun sonucunda, ASCII ve Unicode'da dizeler ile çalışmak için MQL5 fonksiyonu farklıdır.
Bir Dizeyi Diziye Dönüştürme ve Dizeye Geri Dönüştürme
Dizeler ile çalışırken, StringLen(), StringFind(), StringSubst() ve StringReplace() fonksiyonları pratik görevlerin çoğunu çözmek için genellikle yeterli olmaktadır. Ancak şifreleme, veri sıkıştırma, kontrol değerlerinin hesaplanması gibi sayı cinsinden dizeler ile çalışarak çok daha kolay çözülen görevler olabilir. Bu tür görevler günlük olarak ele alınmasa da bir gün bunları çözmeniz gerekebilir. Bir dizenin bir diziye dönüştürülmesini gerektiren daha önemli görevler de vardır: örneğin dize parametrelerini Windows API (Uygulama Programlama Arayüzleri) fonksiyonlarına aktarmak.
Bir dizeyi bir Unicode dizisine dönüştürmek için StringToShortArray() fonksiyonunu ve bir ASCII dizisine dönüştürmek için StringToCharArray() fonksiyonunu kullanırız:
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");
Yukarıdaki örnekte StringToShortArray() ve StringToCharArray() fonksiyonları kullanılarak elde edilen diziler aynıysa, "Aynı" mesajını içeren bir pencere açılır ve farklılık varsa, "Farklı" mesajı okunur. "MetaTrader 5" dizesi için diziler aynıdır, çünkü dize, 127'ye kadar karakter kodlarına sahip karakterlerden oluşur.
127'nin üzerindeki karakter kodlarında ise biraz farklıdır. StringToShortArray() fonksiyonu işleminin sonuçları her yerde her zaman aynı olurken StringToCharArray() fonksiyonu işleminin sonuçları işletim sisteminin bölgesel ayarlarına bağlı olacaktır.
Windows 7'de, sistem dili Denetim Masası - Bölge ve Dil - Ekran dilini değiştir bölümünden seçilebilir.
Aşağıdaki örneğe bir göz atın. Kod sayfası 1251'de kod 192 "А" harfine (Rus alfabesinin ilk harfi) karşılık gelirken 1250 kodlamasında aynı kod "Ŕ" harfine (Çek alfabesinin en bilinen harflerinden biri) karşılık gelir. StringToShortArray() fonksiyonunu kullanırken, "А" harfinin kodu her zaman 1040, "Ŕ" harfinin kodu her zaman 340 olacaktır. Sistem Rus diline ayarlanmışsa, StringToCharArray() fonksiyonunu kullanırken "А" harfi kod 192'ye (doğru) karşılık gelirken "Ŕ" harfi kod 82'ye (Latin "R") karşılık gelecektir. Ancak sistem Çek diline ayarlanmışsa, "А" harfi kod 63'e (soru işareti) ve "Ŕ" harfi kod 192'ye (doğru) karşılık gelecektir. Aksan işareti içeren karakterler benzer Latin karakterleri ile değiştirilirken çok yaygın olmayan karakterler bir soru işareti ile değiştirilir.
Lütfen dizenin boyutunu ve elde edilen dizileri belirtin:
int StrLen=StringLen(str); int shaLen=ArraySize(sha); int chaLen=ArraySize(cha); //--- output the lengths Alert(StringFormat("%i, %i, %i",StrLen,shaLen,chaLen));
Dizilerdeki öğe sayısı, dizedeki karakter sayısından bir sayı fazladır. Bunun nedeni, dizenin sonunun 0 kodlu karakter ile işaretlenmesidir. Bu karakter dizede gösterilmez, ancak görüntülenen dizinin sonunu belirttiğinden bilgisayar için anlamlıdır. Veri alışverişi, her zaman dize uzunluğuna karşılık gelen miktarda tek seferde bir bayt (karakter) oranında yapılmaz, ancak kod 0 olan karakter her durumda dize sonunu belirlemenizi sağlar. Aynı sıfır sorunlara da neden olabilir, örneğin şifreleme yaparken veya bir sıkıştırma algoritması uygularken belirli bir karakter kod 0 karakterine dönüştürülebilir. Bu durumda, bir diziyi bir dizeye ters dönüştürürseniz dize eksik olacaktır. Bu tür görevler, özel hilelerin kullanılmasını gerektirmekle birlikte bu makalenin kapsamı dışındadır.
Bir diziyi bir dizeye ters dönüştürme, ShortArrayToString() ve CharArrayToString() fonksiyonları kullanılarak mümkündür:
//--- 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);
Yukarıdaki kodun sonucunda, str1 değişkeni "Unicode" dizesini saklayacak ve str2 "ASCII" dizesini saklayacaktır.
İki benzer fonksiyon daha vardır: ShortToString() ve CharToString(). Bunlar, short veya char türünde tek bir değişkeni bir karakterden oluşan bir dizeye dönüştürür. CharToString() fonksiyonu büyük bir pratik öneme sahiptir. Farklı sembolleri görüntülemenizi sağlayan bir grafik nesnesi, OBJ_ARROW, fiyat eksenine dikey ve zaman eksenine yatay olarak sabitlenir, böylece semboller siz grafikte gezinirken kayar. OBJ_LABEL ile Wingdings yazı tipinin kullanılması, ekranda koordinatlara bağlı farklı sembolleri görüntülemenizi sağlayarak çeşitli bilgi panelleri oluşturmamıza olanak sağlar. Gerekli sembolü Wingdings sembol tablosunda buluruz ve bunun kodunu OBJ_LABEL grafik nesnesi kullanılarak daha fazla görüntülenen bir dizeye dönüştürürüz:
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
Bu kodun sonucunda, grafikte bir zil simgesi göreceksiniz. Siz grafikte gezinirken zil yerinde kalacaktır.
Karakter kodları ile çalışmak için iki fonksiyon daha vardır: StringGetCharacter() ve StringSetCharacter(). Bunlar, Unicode kodları ile çalışırlar. StringGetCharacter() fonksiyonu, dizede belirli bir konumdaki karakterin kodunu almanızı sağlar:
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));
Bu kodu çalıştırdıktan sonra, uch1 değişkeni 76 değerini ve uch2 53 değerini saklayacaktır.
StringSetCharacter() fonksiyonu, belirli bir konumdaki karakterin kodunu değiştirmenize ve bir dizenin sonuna bir karakter eklemenize olanak sağlar:
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);
Bu kodu çalıştırırken, str değişkeni "MQ5" yerine ilk olarak "MQL" ve ardından "MQL5" ifadesini saklayacaktır.
API Fonksiyonlarını Çağırma
Bazı API fonksiyonları, dize parametrelerini değişkenleri olarak kullanır. Örneğin, üçüncü taraf uygulamalara yönelik fonksiyon WinExec, uchar türünde bir diziyi ilk parametresi olarak kullanır:
#import "kernel32.dll" int WinExec(uchar &Path[],int Flag); #import
Standart bir Windows programı olan notepad.exe'yi (Notepad) çalıştırmayı deneyelim. Not defterine giden yolu uchar türünde bir diziye dönüştürün:
string PathName="C:\\WINDOWS\\notepad.exe"; uchar ucha[]; StringToCharArray(PathName,ucha); int x=WinExec(ucha,1);
Bu fonksiyon işlemi, Not Defteri metin düzenleyicisinin açılmasına neden olmalıdır.
API fonksiyonlarında dize parametreleri kullanmanın bir diğer örneği, Unicode kullanarak pencerede bir mesaj yazdıran MessageBoxW fonksiyonudur. Bu nedenle, ushort türünde dizileri bunun parametreleri olarak aktaracağız:
#import "user32.dll" int MessageBoxW(int hWnd,ushort &szText[],ushort &szCaption[],int nType); #import
Şimdi bu fonksiyonu pencerede bir mesaj yazdırmak için kullanın:
ushort arr[]; ushort capt[]; //--- convert StringToShortArray("Programming in MQL5 for MetaTrader 5.",arr); StringToShortArray("Message",capt); //--- print the message MessageBoxW(0,arr,capt,0);
Bu kodun sonucunda, aşağıdaki mesajı içeren bir pencere görebileceksiniz: "MetaTrader 5 için MQL5'te Programlama".
Yukarıdaki örnekte ushort türünde dizilerin kullanılmasının gerekli olmadığına ve dizeleri basitçe fonksiyon parametreleri olarak aktarabileceğinize dikkat edilmelidir:
#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); }
Bu kodun sonucu yukarıdaki ile aynı olacaktır. Ancak, doğru mesajı yazdırmak için, fonksiyon parametreleri olarak uchar türünde dizileri kullanamazsınız:
#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); }
Kod hatasız yürütülecek ve bir açılır pencere görünecektir, ancak mesaj bozulacaktır.
ASCII kodlamasında bir dize yazdırmanın gerekli olduğu durumlarda (örneğin halihazırda uchar türünde bir diziniz varsa), benzer bir fonksiyon vardır: MessageBoxA. Mesajı doğru bir şekilde görüntülemek için, fonksiyona yalnızca uchar türünde diziler dize parametreleri olarak aktarılmalıdır. Şimdi mesajı yazdırmak için bu fonksiyonu içe aktarın ve çağırın:
#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); }
Yine "MetaTrader 5 için MQL5'te Programlama" doğru mesajını alırız.
Temel olarak, dizeler ile çalışan birçok WinAPI fonksiyonu için 2 seçenek vardır: ASCII dizeleri ile çalışma seçeneği ve Unicode dizeleri ile çalışma seçeneği.
Bir betik, Uzman Danışman veya gösterge çalıştırırken fonksiyonları çağırabilmek için, terminal ayarlarında DLL'lerin kullanımını etkinleştirin (Terminal - Ana Menü - Araçlar - Seçenekler - Uzman Danışmanlar - DLL içe aktarmalarına izin ver) veya özellikler penceresinin Bağımlılıklar sekmesinde "DLL içe aktarmalarına izin ver" seçeneğini işaretleyin. Betik için özellikler penceresinin açılmasını etkinleştirmek için uygun betik özelliğini belirtin:
#property script_show_inputs
Sınırsız Parametre Girişi
Kullanıcı, parametreleri özellikler penceresine, parametreleri noktalı virgülle ayırarak girer:
input string Lots="0.1; 0.2; 0.3; 0.5";
Bu dizeyi double türünde bir değişkenler dizisine dönüştürmemiz gerekir.
MQL5'te bir dize, StringSplit() fonksiyonu kullanılarak bölünebilir. Fonksiyona aktarılan ilk parametre bir dizedir; ikinci parametre ayırıcının ASCII kodudur; ve aktarılan üçüncü parametre, fonksiyon işlem sonuçlarını saklayacak bir dizidir. ASCII kodunu belirlemenin çok basit bir yolu vardır: Gerekli karakteri tek tırnak içine almanız gerekir:
int Code='A'; Alert(IntegerToString(Code));
Bu kodun sonucunda, Code değişkeni, "A" Latin karakterinin ASCII kodu olan 65 değerini saklayacaktır.
Gerektiğinde kolayca kullanabilmemiz için bu sorunun çözümünü ayrı bir fonksiyon olarak ifade edelim. Fonksiyona aktarılan ilk parametre bir dize olacaktır ve ikinci parametre referans ile döndürülen bir dizi olacaktır. Fonksiyonun kodu aşağıda detaylı yorumlar ile birlikte verilmiştir ve daha fazla açıklama gerektirmez:
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); }
Dizeleri Çeşitli Değişkenlere Dönüştürme
ParamsToArray() fonksiyonu, dizeyi ikili türde değişkene dönüştürmek için standart StringToDouble() fonksiyonunu kullanmıştır. Aynı fonksiyon, float türüne dönüştürme için de kullanılır. Diğer değişken türlerine dönüştürme için kullanılan standart fonksiyonlar vardır.
StringToInteger() fonksiyonu bir dizeyi bir tamsayı değişkenine dönüştürür:
string Str="12345.678"; //--- convert the string to an integer long Val=StringToInteger(Str); //--- inverse convert and output the results Alert(IntegerToString(Val));
Bu kodun sonucunda Val değişkeni 12345 değerini saklayacaktır. Kesirli kısım kesilir.
StringToTime() fonksiyonu zamanın bir dize ifadesini ilgili sayısal ifadeye dönüştürür. Saati belirtmezseniz, varsayılan değer "00:00" olacaktır:
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);
StringToColor() fonksiyonu, bir renk adını (standart web rengi) ilgili sayısal değere dönüştürmenize veya bir RGB bileşenleri dizesini dönüştürmenize olanak sağlar:
string Str1="clrYellow"; string Str2="255,255,0"; color Color1=StringToColor(Str1); color Color2=StringToColor(Str2);
Dizeleri tarih/saate ve renk türüne dönüştürmenin başka bir yolu daha vardır. Bu, değişkenlere belirli değerler atarken kullanılabilir:
datetime DateTime=D'2012.11.02 22:00'; color Color=C'255,255,0';
"D", tarihin dize ifadesinin önüne yazılır ve tarihin kendisi tek tırnak içine alınır. Rengin dize ifadesinin önüne "С" harfi gelir ve RGB bileşenleri tek tırnak içine alınır ve virgül ile ayrılır.
Bildirimleri Etkinleştirme
Kullanıcı, belirli bir bildirim türünü etkinleştiren bir dizi karakter girer. Bu yöntem, çeşitli bildirim kombinasyonlarının etkinleştirilmesi için kullanılabilir. Uyarı bildirimi "а", sesli bildirim "s", e-posta bildirimi "e" ve anlık bildirim "p" öğesine karşılık gelir. Ek olarak, sinyallerin kontrol edildiği çubuğu belirtmek için dizeye 1 veya 0 ekleyebilirsiniz (göstergelerde faydalı olabilir). Kod, ilk parametresi bir dize ve ardından referans ile döndürülen Shift değişkeni (çubuk sayısı) ve farklı bildirim yöntemlerine karşılık gelen bool türündeki değişkenler olan bir fonksiyon olarak ifade edilir. Kodda ayrıntılı yorumlar sağlanmıştır:
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 }
Artık, özellikler penceresinde beş değişken yerine tek bir değişken yeterli olacaktır.
Dize Tamponu
Hala üç standart fonksiyonu gözden geçirmemiz gerekiyor: StringInit(), StringFill() ve StringBufferLen().
StringInit() fonksiyonu, bir dizeyi belirtilen sayıda aynı karakterler ile doldurur:
string str; StringInit(str,10,'|'); Alert(str);
Bu kodu çalıştırdıktan sonra, str değişkeni "||||||||||" içeren dizeyi saklayacaktır. Karakter ASCII kodu kullanılarak belirtilir, diğer bir deyişle karakterin tek tırnak içine alınması gerekir.
StringFill() fonksiyonu, bir dizeyi aynı karakterler ile dize boyutunu değiştirmeden doldurur. Önceki örneğin devamında:
StringFill(str,'/'); Alert(str);
Bunun ardından, str değişkeni "/////////" içeren dizeyi saklayacaktır.
Şimdi bir dizeyi 0 kodlu bir karakter (dizenin sonu) ile doldurmaya çalışalım:
StringFill(str,0);Dize boyutunu kontrol edin:
int Length=StringLen(str); Alert(IntegerToString(Length));
Boyut 0'a eşittir ve 0 kodlu karakter dizenin başlangıç noktasındadır. Tampon boyutunu kontrol edin:
int BLength=StringBufferLen(str); Alert(IntegerToString(BLength));
Tampon boyutu 0'dan farklıdır ve ilk dizenin boyutunu aşmaktadır. Dizeye ayrılan bellek fazlasıyla yeterlidir. Şimdi, dizeye tampon boyutu aralığında bir değer atarken belleğin yeniden tahsisi gerekmeyecek ve değer çok hızlı bir şekilde atanacaktır. Tampon boyutunun küçültülmediğinden emin olmak için, yeni değer dizeye atanmak yerine eklenmelidir:
str+="a";
Tampon boyutu aynı kalırken dize uzunluğu artık 1'dir. Bu şekilde, dizelerin işlenmesini biraz hızlandırabilirsiniz. Bir dize, dizenin başına 0 kodlu karakter eklenerek temizlenebilir:
StringSetCharacter(str,0,0);
Sonuç
Makalenin konusunun pek de önemli olmadığı, MQL5 dilinin ana amacı olan Uzman Danışmanlar ve göstergeler geliştirme ile pek de ilgili olmadığı düşünülebilir. Ancak, burada, dilin sağladığı dizelerle çalışmak için geniş bir fonksiyonellik yelpazesinden ilham alan oldukça kapsamlı bir makalemiz var. Çoğu durumda Uzman Danışmanları ve göstergeleri programlarken dizilerle uğraşmak zorunda kalmanız pek olası değildir, ancak bir gün gerekli olabilir. Bu makaleyi okuduktan sonra, fonksiyonları inceleyerek zaman kaybetmeden, gerektiği gibi ve gerektiğinde dizeleri kullanmaya hazırlıklı ve hazır olacaksınız. Gerekenleri kolaylıkla yapabileceksiniz.
Fonksiyonları amaçlarına, önemlerine ve kullanım sıklıklarına göre sınıflandırarak makalede verilen bilgileri tekrarlayalım.
- StringLen(), StringFind(), StringSubstr(), StringReplace() ve StringSplit(), dize uzunluğunu belirlemek, alt dize aramak, bir alt dizeyi bulmak ve değiştirmek ve bir dizeyi bölmek için kullanılan temel fonksiyonlardır.
- StringTrimLeft(), StringTrinRight(), StringToLower() ve StringToUpper(), uçlardaki boşlukları silmek ve büyük/küçük harf değiştirmek için kullanılan çok kullanışlı yardımcı fonksiyonlardır.
- ColorToString(), DoubleToString(), EnumToString(), IntegerToString(), TimeToString() ve StringFormat(), sayısal değişkenleri bir dizeye dönüştüren fonksiyonlardır.
- StringToColor(), StringToDouble(), StringToInteger(), StringToTime() ve StringCompare(), bir dizeyi sayısal bir değişkene dönüştüren fonksiyonlardır.
- StringAdd() ve StringConcatenate(), dizeleri alan verimli bir şekilde eklemek ve birleştirmek için kullanabileceğiniz fonksiyonlardır.
- ShortToString(), ShortArrayToString(), StringToShortArray() ve ayrıca CharToString(), CharArrayToString() ve StringToCharArray(), çok karmaşık dize manipülasyonları gerektiren görevlerle uğraşırken yararlı olabilecek diziler şeklindeki dizeler ile çalışmaya yönelik fonksiyonlardır. Yukarıdaki listeden, özellikle önemli olan iki fonksiyonu belirtebiliriz:
- CharToString(), Wingdings yazı tipiyle grafik nesneleri ile çalışmak için kullanılır;
- CharArrayToString(), API fonksiyonları çağrılırken bir dize parametresi hazırlamak için kullanılır.
- StringSetCharacter(), StringGetCharacter(), StringInit(), StringFill() ve StringBufferLen() ikincil fonksiyonlardır.
Ekli dosyalar
- IncStrFunctions.mqh Trim(), StringFindRev(), TrimL(), TrimR(), ParamsToArray() ve NotifyOnOff() fonksiyonlarını içerir.
- eMultiLanguageMessage.mq5, farklı dillerde mesajlar içeren bir Uzman Danışman örneğidir.
MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/585
![Satın Almadan Önce Bir Alım Satım Robotu Nasıl Test Edilir?](https://c.mql5.com/2/0/avatar_test_mql5_market.png)
![Makine Öğrenmesi: Destek Vektör Makineleri Ticarette Nasıl Kullanılabilir?](https://c.mql5.com/2/0/iStock_000020410350_Small.png)
![MetaTrader 4 ve MetaTrader 5 İçin Nasıl Sinyal Sağlayıcı Olunur?](https://c.mql5.com/2/0/Avatar_How_to_become_a_signal_provider.png)
!["Çalışma Sırasında" Kullanıcı Panelinden Uzman Danışman Parametrelerini Değiştirme](https://c.mql5.com/2/0/avatar__24.png)
![MQL5 - MetaTrader 5 müşteri terminalinde yerleşik ticaret stratejileri dili](https://c.mql5.com/i/registerlandings/logo-2.png)
- Ücretsiz ticaret uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Gizlilik ve Veri Koruma Politikasını ve MQL5.com Kullanım Şartlarını kabul edersiniz