MQL4 ve MQL5 ile ilgili herhangi bir acemi sorusu, algoritmalar ve kodlar hakkında yardım ve tartışma - sayfa 599

 
Nikolay Gaylis :

Merhaba!

Lütfen bana imleci nasıl hareket ettireceğimi söyleyin, örneğin bir metin belgesinde 7. satıra, bu konumdan zaten bir alt dize çıkarmak için ...

Hangisi daha hızlı olacak - tek satırlı birçok metin dosyası mı yoksa çok satırlı bir dosya mı?

Bir satırda kaç bayt olduğunu bilmeniz ve işaretçiyi dosyanın başlangıcından itibaren bu tür 6 değerle hareket ettirmeniz gerekir.

FileSeek - Файловые операции - Справочник MQL4
FileSeek - Файловые операции - Справочник MQL4
  • docs.mql4.com
Если выставить позицию за "правую границу" файла (больше, чем размер файла), то последующая запись в файл будет будет произведена не с конца файла, а с выставленной позиции. При этом между предыдущим концом файла и выставленной позицией будут записаны неопределенные значения...
 
Nikolay Gaylis :

Merhaba!

Hangisi daha hızlı olacak - tek satırlı birçok metin dosyası mı yoksa çok satırlı bir dosya mı?

Algoritmanın özel uygulamasına ve çözülmesi gereken soruna bağlıdır. Belki senin durumunda ilk seçenek daha hızlı olacak, ama senin yerinde olsam performansı düşünmezdim.

Nicholas Gaylis'in fotoğrafı.

Lütfen bana imleci nasıl hareket ettireceğimi söyleyin, örneğin bir metin belgesinde 7. satıra, bu konumdan zaten bir alt dize çıkarmak için ...

Standart belgeleri okuyun. " Dosya İşlemleri " bölümü. Örneğin, doğrudan belgelerden bir örnek olan FileReadString'i kullanarak bir dosyayı satır satır okuyabilirsiniz:

 //--- покажем окно входных параметров при запуске скрипта 
#property script_show_inputs 
//--- параметры для чтения данных 
input string InpFileName= "Trend.bin" ; // имя файла 
input string InpDirectoryName= "Data" ; // имя директории 
//+------------------------------------------------------------------+ 
//| Script program start function                                    | 
//+------------------------------------------------------------------+ 
void OnStart () 
  { 
//--- откроем файл 
   ResetLastError (); 
   int file_handle= FileOpen (InpDirectoryName+ "//" +InpFileName, FILE_READ | FILE_BIN | FILE_ANSI );
     if (file_handle!= INVALID_HANDLE ) 
     { 
       PrintFormat ( "Файл %s открыт для чтения" ,InpFileName); 
       PrintFormat ( "Путь к файлу: %s\\Files\\" , TerminalInfoString ( TERMINAL_DATA_PATH ));
       //--- вспомогательные переменные 
       int     str_size; 
       string str; 
       //--- прочитаем данные из файла 
       while (! FileIsEnding (file_handle)) 
        { 
         //--- узнаем сколько символов использовано для записи времени 
         str_size= FileReadInteger (file_handle, INT_VALUE ); 
         //--- прочитаем строку 
         str= FileReadString (file_handle,str_size); 
         //--- распечатаем строку 
         PrintFormat (str); 
        } 
       //--- закроем файл 
       FileClose (file_handle); 
       PrintFormat ( "Данные прочитаны, файл %s закрыт" ,InpFileName); 
     } 
   else 
       PrintFormat ( "Не удалось открыть файл %s, Код ошибки = %d" ,InpFileName, GetLastError ());
   }
 

Grafikteki fare düğmesini tıklamanın değerini fiyatın değerine nasıl dönüştüreceğimi ya da tam tersini söyle.

 int OnInit ()
  {
   ChartGetInteger ( 0 , CHART_EVENT_MOUSE_MOVE , true );
   

   return ( INIT_SUCCEEDED );
  }
//-------------------------------------------------------
void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
   int klik = CHARTEVENT_CLICK;
   Print("ID: ",id," Lparam(X): ",lparam," Dparam(Y): ",dparam," Sparam: ",sparam);
   if(id==klik)sto = true;
   si = lparam;
   Print("'",sparam,"klik ","si = ",si);
   
  }
 
 
Galim_V :

Grafikteki fare düğmesini tıklamanın değerini fiyatın değerine nasıl dönüştüreceğimi ya da tam tersini söyle.

ChartXYToTimePrice işlevini kullanın. Belgelerin "Grafik İşlemleri" bölümüne bakın.

 
Vasiliy Sokolov :

ChartXYToTimePrice işlevini kullanın. Belgelerin "Grafik İşlemleri" bölümüne bakın.

Sayesinde.

 
Vasiliy Sokolov :

Böylece CArrayObj ile işleri batırdılar. Bunun yerine: CArrayObj test_objects; Yazdılar: CArrayObj* test_objects , ancak bunun için bir yıkıcı yapmayı unuttular ; Belki de bellek modeli, CArrayObj ile çalışacak şekilde yanlış yapılandırılmıştır. Belki de sadece işaretçiler ile abarttılar. Teşhis kesindir: gerekli olmayanişaretçilerin kullanılması genellikle sızıntılara yol açar.

Bazı sınıflarda bir fonksiyon var. İçinde, bir dizi CArrayObj nesnesi ilan ediyorum. Buna global sınıf nesneleri ekliyorum. İşlev sona erdi, nesne dizisinin kendisine gerek yok. Nesneler, elbette gereklidir.

CArrayObj *test_objects işaretçisi olarak bir dizi oluşturursam, günlükte silinmemiş nesneler alıyorum ve bu da sonunda bellek yetersiz hatasına yol açacaktır.

Bu CArrayObj test_objects gibi bir dizi bildirirsem, ona nesneler eklersem, işlevin sonunda ortaya çıkar ve nesneler erişilemez hale gelir, çünkü nesneler içeren dizi silinmiş gibiydi ...

 
Juer :

Bu CArrayObj test_objects gibi bir dizi bildirirsem, ona nesneler eklersem, işlevin sonunda ortaya çıkar ve nesneler erişilemez hale gelir, çünkü nesneler içeren dizi silinmiş gibi görünüyor ...

Bu doğru, çünkü bu durumda, işlevin adres alanına değil, yığına CArrayObj test_objects tahsis ediyorsunuz. Bir işlev çıktığında, CArrayObj test_nesneleriniz de dahil olmak üzere işlevin adres alanının üzerine yazılır.

Jüri :

İşlev sona erdi, nesnelerin dizisine gerek yok. Elbette nesnelere ihtiyaç vardır.

Bir kez ve herkes için unutmayın - eğer CArrayObj içindeki nesnelere ihtiyacınız varsa, o zaman CArrayObj'nin kendisine de ihtiyaç vardır. CarrayObj gerekli sarma. O olmadan hiçbir şey, nokta.

Jüri :

CArrayObj *test_objects işaretçisi olarak bir dizi oluşturursam, günlükte silinmemiş nesneler alıyorum ve bu da sonunda bellek yetersiz hatasına yol açacaktır.

Bu durumda, öbek üzerindeki bazı CArrayObj nesnesine bir işaretçi oluşturulur. Yığın, programın adres alanının, ilgili yeni ve silme operatörlerini kullanarak belleğin manuel olarak ayrıldığı ve silindiği bir bellek bölümüdür. Bu, yeni yazarsanız, bir yerde silmenin ayna ikizi olması gerektiği anlamına gelir. Ayrıca, yeni ve silme, programın farklı bölümlerinde, örneğin farklı yöntemlerde bulunabilir:

CArrayObj* foo_create()
{
   //-- Выделили память в куче, под объект CArrayObj и создали его
   CArrayObj* obj_array = new CArrayObj();
   //-- Заполняем obj_array полезной нагрузкой
  obj_array.Add( new CItem());
  ...
  ...

   //-- Выходим из функции. При этом объект CArrayObj и память под него не затирается.
   //-- Он по-прежнему доступен по указателю. Единственный указатель, который ведет
   //-- к нему это obj_array. Возвращаем его вызвавшей функции
   return obj_array;
}

void foo_analize()
{
   //-- Получили указатель obj_array из foo_create
   //-- здесь он будет под именем obj_analize
   CArrayObj* obj_analize = foo_create();
   //-- Проанализировали объекты внутри obj_analize
   ...
   ...
   ...
   //-- Здесь объект obj_analize и его элементы больше не нужены
   //-- Удаляем объект и все его элементы. Отдельно удалять элементы
   //-- не нужно. CArrayObj сделает все автоматически.
   delete obj_analize;
}

Foo_analize çağrıldıktan sonra nesnelere hala ihtiyaç duyuluyorsa, silme operatörü, nesnelerin ihtiyaç duyulacağının garanti edildiği başka bir konuma taşınabilir. Böyle genel bir yer, örneğin program kapanmadan önce çağrılan OnDeinit olabilir.

Ana şeyi unutmayın, eğer yeni bir operatör varsa, bunun için her zaman bir silme operatörü olmalıdır . Aksi takdirde, bellek sızıntıları olacaktır. Aynı nesne üzerinde çalışan yeni ve silme operatörlerinin aynı "yakındaki" yöntemde bulunması gerekmez. Sil, öbek üzerinde tahsis edilen nesneye bir referansı olduğu sürece, belleğin tahsis edildiği yerden uzakta herhangi bir yerde olabilir.

** Yukarıdakilerin doğru olmasına rağmen, bu tür yapılardan kaçınmanın daha iyi olduğunu not ediyorum, çünkü her zaman açık olmayan silme operatörünü nerede ve hangi koşullar altında arayacağınıza her zaman çok dikkatli bakmanız gerekir. Bunun yerine, sadece nasıl kullanılacağını öğrenmeniz gerekir . Sınıf, yeni ve silme operatörlerini kullanmadan öbek üzerindeki nesneleri otomatik olarak ayırmanıza ve silmenize olanak tanır:

 class CMyCalculation
{
private :
   //-- Содержит объекты, над которыми нужно провести некоторые мат. операции
   CArrayObj m_obj_array;
   void CreateObj();
public :
   void Calc();
};
//-- Считает массив объектов CArrayObj
void CMyCalculation::Calc()
{
  //-- Если объектов нет, создаем их
  if (m_obj_array.Total() == 0 )
     CreateObj();
  //-- Рассчитываем нужные нам значения на данных
  for ( int i = 0 ; i < m_obj_array.Total(); i++)
  {
     CItem* item = m_obj_array.At(i);
     //-- обсчитывает item как нам нужно
     ...
     ...
  }
}
//-- Создает массив объектов CItem
void CMyCalculation::CreateObj()
{
   m_obj_array.Add( new CItem());
   m_obj_array.Add( new CItem());
   ...
   ...
}

Bu sınıf açıkça işaretçiler içermez. Yani hem new hem de delete kullanmanıza gerek yok. Programdan çıktıktan sonra sınıf, tüm CItem ve CArrayObj nesnelerini otomatik olarak yayınlayacak ve bu da geliştiricinin ömrünü büyük ölçüde basitleştirecektir.

 
Vasiliy Sokolov :

Bu doğru, çünkü bu durumda, işlevin adres alanına değil, yığına CArrayObj test_objects tahsis ediyorsunuz. Bir işlev çıktığında, CArrayObj test_nesneleriniz de dahil olmak üzere işlevin adres alanının üzerine yazılır.

Bir kez ve herkes için unutmayın - eğer CArrayObj içindeki nesnelere ihtiyacınız varsa, o zaman CArrayObj'nin kendisine de ihtiyaç vardır. CarrayObj gerekli sarma. O olmadan hiçbir şey, nokta.

Bu durumda, öbek üzerindeki bazı CArrayObj nesnesine bir işaretçi oluşturulur. Yığın, programın adres alanının, ilgili yeni ve silme operatörlerini kullanarak belleğin manuel olarak ayrıldığı ve silindiği bir bellek bölümüdür. Bu, yeni yazarsanız, bir yerde silmenin ayna ikizi olması gerektiği anlamına gelir. Ayrıca, yeni ve silme, programın farklı bölümlerinde, örneğin farklı yöntemlerde bulunabilir:

Foo_analize çağrıldıktan sonra nesnelere hala ihtiyaç duyuluyorsa, silme operatörü, nesnelerin ihtiyaç duyulacağının garanti edildiği başka bir konuma taşınabilir. Böyle genel bir yer, örneğin program kapanmadan önce çağrılan OnDeinit olabilir.

Ana şeyi unutmayın, eğer yeni bir operatör varsa, bunun için her zaman bir silme operatörü olmalıdır . Aksi takdirde, bellek sızıntıları olacaktır. Aynı nesne üzerinde çalışan yeni ve silme operatörlerinin aynı "yakındaki" yöntemde bulunması gerekmez. Sil, öbek üzerinde tahsis edilen nesneye bir referansı olduğu sürece, belleğin tahsis edildiği yerden uzakta herhangi bir yerde olabilir.

** Yukarıdakilerin doğru olmasına rağmen, bu tür yapılardan kaçınmanın daha iyi olduğunu not ediyorum, çünkü her zaman açık olmayan silme operatörünü nerede ve hangi koşullar altında arayacağınıza her zaman çok dikkatli bakmanız gerekir. Bunun yerine, sadece nasıl kullanılacağını öğrenmeniz gerekir . Sınıf, yeni ve silme operatörlerini kullanmadan öbek üzerindeki nesneleri otomatik olarak ayırmanıza ve silmenize olanak tanır:

Bu sınıf açıkça işaretçiler içermez. Böylece hem new hem de delete kullanmanıza gerek kalmaz. Programdan çıktıktan sonra sınıf, tüm CItem ve CArrayObj nesnelerini otomatik olarak yayınlayacak ve bu da geliştiricinin ömrünü büyük ölçüde basitleştirecektir.

Teşekkür ederim. Sadece özel soruma bir cevap bulamadım. Bir işaretçi bildirirsem, silmeyi nereye koymalıyım. İşlevde bildirilen CArrayObj nesnesini tekrar ediyorum... Deinit()'te onu nasıl silebilirim?

Ama önce sorunu şu şekilde çözdüm. İşlev sona ermeden önce:


CClass func()
  {
   CArrayObj test_objects;
   test_objects.Add(m_object1);
   test_objects.Add(m_object2);
   ....

   for ( int i= 0 ;i<test_objects.Total();i++)
     {
      test_objects.Detach(i);
     }
   return ..
  }
 
Juer :

Teşekkür ederim. Sadece özel soruma bir cevap bulamadım. Bir işaretçi bildirirsem, silmeyi nereye koymalıyım. İşlevde bildirilen CArrayObj nesnesini tekrar ediyorum... Deinit()'te onu nasıl silebilirim?

Burası bir telepat kulübü değil. Kodunuzu eklemediniz, bu nedenle silme işlemini nereye yapacağınızı düşünün.

CClass func()
  {
   CArrayObj test_objects;
   test_objects.Add(m_object1);
   test_objects.Add(m_object2);
   ....

   for ( int i= 0 ;i<test_objects.Total();i++)
     {
      test_objects.Detach(i);
     }
   return ..
  }

Doğru değil.

 
Merhaba. Yardım edin lütfen göstergeyi fiyat 400 puana ulaşınca mesaj atsın diye kurdum ama bu şartlara gelince bana çok mesaj geliyor. Sadece bir tane gönderilecek şekilde nasıl yapabilirim. Teşekkür ederim!
 #property indicator_chart_window
extern int     font_size = 10 ;
extern color   ColorBull = DodgerBlue;
extern color   ColorBeer = Red;
extern string font_name = "rs" ;
//+------------------------------------------------------------------+

int start()
 {
   double k=( WindowPriceMax ()- WindowPriceMin ())/ 20 ;
   for ( int i= WindowFirstVisibleBar (); i>= 0 ; i--)
   {
       double rs = ( NormalizeDouble ( Open [i], Digits )- NormalizeDouble ( Close [i], Digits ))/ Point ;
       if (rs< 0 ) drawtext(i, High [i]+k, DoubleToStr (rs*(- 1 ), 0 ), ColorBull);
       if (rs> 0 ) drawtext(i, Low [i]- Point , DoubleToStr (rs, 0 ), ColorBeer);
   }
   if (rs<- 400 ) 
   {
     SendNotification ( "Появился сигнал1: " + Symbol () + ", " + IntegerToString ( Period ()));
     Print ( "Сигнал отправлен!" );
   }
   if (rs> 400 )
   {
     SendNotification ( "Появился сигнал2: " + Symbol () + ", " + IntegerToString ( Period ()));
     Print ( "Сигнал отправлен!" );
   }
   
}
//+------------------------------------------------------------------+
int deinit()
{
   ObjectsDeleteAll ( 0 , OBJ_TEXT );
   return ( 0 );  
}
//+------------------------------------------------------------------+
int drawtext( int n, double Y1, string l, color c)
 {
   string Name= TimeToStr ( Time [n], TIME_DATE | TIME_MINUTES );
   ObjectDelete (Name);
   ObjectCreate (Name, OBJ_TEXT , 0 , Time [n],Y1, 0 , 0 , 0 , 0 );
   ObjectSetText (Name, l,font_size,font_name);
   ObjectSet     (Name, OBJPROP_COLOR , c);
 }
//+------------------------------------------------------------------+