初心者の方からの質問 MQL5 MT5 MetaTrader 5 - ページ 1201

 
Сергей Таболин:

1つのファイルにすべてを書き込んでいます。同じファイルに複数の構造体を書き込んだり、読み込んだりするのはうまくいく。

しかし、それは最初から最後まで配列を読み取る。3分割の方法は?構造体を書きながら、どうやって同じファイルに配列を書き込むことができたのでしょうか? 独学なのでよくわからないが、データ形式が違うということで、なんとなく疑ってしまう。

一度書き込み用にファイルを開いて、そこに3つの配列を詰め込めばなんとかなるのは認めるが、そうやって部分的に読み込むのは無理がある。

 
Alexey Viktorov:

しかし、それは最初から最後まで配列を読み取る。3分割の方法は?構造体の書き込みと配列の書き込みを同じファイルに管理する方法を教えてください。独学で、よく知りませんが、データ形式が違うというのは、何となく怪しいですよね。

書き込み用のファイルを 一度開いて、そこに3つの配列を詰め込めば何とかなるのは認めるが、部分的にそう簡単に読めない。

同じファイルに1つの構造体と3つの配列だけを書き込めば、そこから読み出すことができる、と言っています(配列を読み出すには、それぞれのサイズを指定する必要があると仮定しています)。しかし、そのようなシーケンスをいくつも書いては読むという仕掛けは、私にはうまくいきませんでした。ポインターを動かさないといけないのかもしれませんが、すでに緊張しているので......。

 
Сергей Таболин:

1つのファイルに1つの構造体と3つの配列だけを書き込んでおけば、後からそこから読み出すことができる(ただし、配列を読み出すにはそれぞれのサイズを指定する必要がある)、と申し上げました。しかし、そのようなシーケンスをいくつも書いては読むという仕掛けは、私にはうまくいきませんでした。おそらくポインターを移動させる必要があるのでしょうが、それはちょっと面倒なので...。

どのような緊張感ですか?馬力が足りない?また、書き込みが成功したと確信できるのか、読み出しに失敗した場合、どのようにそれを想定するのか。私の知る限り、.binファイルを目で見て確認することはできません。

 
Сергей Таболин:

アルチョム、例を挙げてくれないか?配列のサイズは動的であることを考慮する。

いや、まだ例はないでしょう。私自身がやっていないのですから、やった暁には記事に記載します。そして、それはすぐにはできないでしょう。実は、FileWriteStruct()を使ってファイルに書き込めるのはPOD-structだけなのです。つまり、文字列を含まない単純な構造体、動的配列、仮想関数、さらにオブジェクトや関数へのポインタなどです。

そして、それを発明し、テストすることが必要だということです。でも、演出は書きましたよ。実装を考える必要がある。

 
Artyom Trishkin:

いや、まだ例はないでしょう。私自身はまだやっていませんし、やったら記事の中で説明しますよ。そして、それはすぐにはできないでしょう。実は、FileWriteStruct()を使ってファイルに書き込めるのは、POD-structだけなのです。すなわち、文字列を含まない 単純な構造体、動的配列仮想関数、およびオブジェクトや関数へのポインタなどである。

そして、それを発明し、テストしなければならないということです。でも、演出は書きましたよ。実装はよく考える必要がある。

どう考えても、この課題は解決できないことがわかった。結局、Sergeiの例では、内部に3つのダイナミックアレイがある。構造体の中にどのように配置されても、動的な配列であることに変わりはない。

しかし、構造体の配列を作成すれば、その配列を書き込むことで問題は解決する。FileWriteArray()。これはすでにテスト済みで、ドキュメントには構造体の配列を書くことについて明確に書かれています。

 
Alexey Viktorov:

しかし、それは最初から最後まで配列を読み取る。3分割の方法は?構造体の書き込みと配列の書き込みを同じファイルに管理する方法を教えてください。独学で、知らないことだらけですが、データフォーマットが違うということで、なんとなくですが、怪しいと思います。

確かに、一度書き込み用のファイルを開いて、そこに3つの配列を詰め込めば何とかなりますが、そんなんじゃ部分的に読めなくなっちゃいますよね。

バイナリファイルでは、任意の構造体、配列、単一の変数まで、すべて1つのファイルに書き込むことができます。

BUT、読み出し時には、同じ順番でデータを読み出す必要があります。

は、すべてうまくいきます。

FileWriteArray()で書き込む場合、配列のサイズは最初のバイトに書き込まれる可能性が高いですが、テストスクリプトを作成するのは簡単です。)

 
Alexey Viktorov:

どう考えても解決不可能な問題であることが判明したのです。結局、Sergeiの例では、内部に3つのダイナミックアレイが存在することになる。構造体の中にどのような構造を構築しても、動的な配列であることに変わりはない。

また、構造体の配列を作成した場合は、その配列を書き込むことで解決します。FileWriteArray()。これは既にテスト済みで、構造体の配列を書くことについてはドキュメントに明記されています。

構造体の配列が格納されていますが、、、文字列があれば、構造体の中でuchar配列に詰めることができ、それがうまくできています。しかし、配列doubleが配列ucharに収まるわけがない。さらに、ダイナミックであること。そして、3つの配列を別々にファイルに保存して、ファイルから展開した構造体に突っ込む...。試していない。考えていないのでわからない。

 
Igor Makanu:

構造体、配列、個々の変数まで、すべて同じファイルに書き込むことができます。

しかし、読み出すときは、同じ順序でデータを読み出す必要があります。

オールマイティー

FileWriteArray()で書き込んだときのファイルダンプを見たことがないので、おそらく配列のサイズは最初のバイトに書き込まれるでしょう。)

この問題をどこで読み始めたか知らないが、念のため思い出してみよう。3つの動的配列を含む構造体をファイルに書き込まなければならない。それから、ファイルが正しく読み込まれないという質問もありました。

トレーディング、自動売買システム、ストラテジーテストに関するフォーラム

初心者からのFAQ MQL5 MT5 MetaTrader 5

セルゲイ・タボリン, 2020.03.24 18:02

聞いているんです )))

自分なりに "工夫 "したつもりです。

最初の構造体と3つの配列は問題なく読み込めました(配列のレシーバが動的でない場合、構造体の後に書き込まれたデータはすべて最初の配列に読み込まれます)。

ただし、それ以上のエントリーがある場合は

   // Проверка
   double   rdata_1[6];
   double   rdata_2[6];
   double   rdata_3[6];
   
   filehandle = FileOpen(filename,FILE_READ|FILE_COMMON|FILE_BIN);
   if(filehandle != INVALID_HANDLE)
   {
      while(!FileIsEnding(filehandle))
      {
         FileReadStruct(filehandle,rfann);
         FileReadArray(filehandle,rdata_1);
         FileReadArray(filehandle,rdata_2);
         FileReadArray(filehandle,rdata_3);
         Print("++++++++++++++++++++++++++++++");
         Print("Структура");
         Print(rfann.v_main_up+"|"+rfann.v_main_dn+"|"+rfann.v_add_up+"|"+rfann.v_add_dn+"|"+rfann.answer);
         Print("Массивы");
         Print("--- 1");
         ArrayPrint(rdata_1);
         Print("--- 2");
         ArrayPrint(rdata_2);
         Print("--- 3");
         ArrayPrint(rdata_3);
      }
   }

すごい量が出るんですよ...。

Структура
4.0|-1.0|2.8|-0.7|1
Массивы
--- 1
 1.00000  0.33225 -0.76202 -0.93263 -1.00000 -0.79174
--- 2
-0.14603  0.89562  0.91407  0.93450  0.89481  0.89829
--- 3
 0.89564  0.89217 -0.91174 -0.86623 -1.00000 -0.07680
++++++++++++++++++++++++++++++
Структура
1.839259944929932 e+277|-nan|5.295254096666168 e-315|3.0|-618173028
Массивы
--- 1
 2.10000 -2.00000 -1.40000 -0.85098 -1.00000 -0.79900
--- 2
-0.30490  0.47926  1.00000  0.70827  0.84163  0.84134
--- 3
 0.83925  0.84173  0.84760  0.84678  0.80368 -0.00063
++++++++++++++++++++++++++++++
Структура
9.384173261527221 e-276|5.298850499315376 e-315|2.955277867691187 e+299|-9.638234784517503 e-243|-1705145188
Массивы
--- 1
+0.00000 +0.00000  4.00000  2.80000  0.00000  0.00000
--- 2
 1.00000  0.22097 -0.37383 -0.73115 -0.81752 -1.00000
--- 3
-0.87753  0.46919  0.59706  0.76223  0.82610  0.84312
++++++++++++++++++++++++++++++

そこで考えたのですが、どのように書かれたかわからない1つのファイルから、構造体と3つの配列を読み取ることは可能なのでしょうか?

だから、独学で知らないことが多いと言ったのですが、部分的に読んでも ダメなんです。

また、.binファイルにすべてを追加するオプションがあるのは理解できますが、それを読むには、何がどのような順序で書かれているのかを知る必要があります。そして、mqlによるものではない可能性があります。

 

全く理解できないのですが...。

      FileSeek(filehandle,0,FILE_END);
'FILE_END' - cannot convert enum                        282     31
'FILE_END' - improper enumerator cannot be used         282     31

どうしたんですか?

 
Alexey Viktorov:

そこで考えたのですが、どのように書かれたかわからない1つのファイルから、構造体と3つの配列を読み取ることは可能なのでしょうか?

ということを書くと、10分以内に、確認しやすくなりますね...。FileWriteArray() がヘッダや先頭バイトに配列の サイズを書かないことを確認しました。

#property copyright "IgorM"
#property link      "https://www.mql5.com/ru/users/igorm"

struct SMystruct
{
   double            d_arr[];
   int               i_arr[];
   uchar             c_arr[];
   int               a;
   double            b;
};

//+------------------------------------------------------------------+
void OnStart()
{
   SMystruct mstruct;
   ArrayResize(mstruct.d_arr,5);    ArrayInitialize(mstruct.d_arr,3.1415926);
   ArrayResize(mstruct.i_arr,3);    ArrayInitialize(mstruct.i_arr,1234567890);
   ArrayResize(mstruct.c_arr,7);    ArrayInitialize(mstruct.c_arr,127);
   mstruct.a = 666;
   mstruct.b = 123.123;
//---  
   if(!SaveMStructToFile("mfile.bin",mstruct)) return;
   SMystruct read_struct;
   if(!LoadMStructInFile("mfile.bin",read_struct)) return;
   Print("1. d_arr");
   ArrayPrint(read_struct.d_arr);
   Print("2. i_arr");
   ArrayPrint(read_struct.i_arr);
   Print("2. c_arr");
   ArrayPrint(read_struct.c_arr);
   printf("mstruct.a = %i , mstruct.b = %f",read_struct.a , read_struct.b);
   
}
//+------------------------------------------------------------------+
bool SaveMStructToFile(const string fname,const SMystruct &data)
{
   int h = FileOpen(fname,FILE_WRITE | FILE_BIN | FILE_COMMON);
   if(h<0) { Print("Write IO Err #",GetLastError()); return(false); }
   FileWriteInteger(h,ArraySize(data.d_arr));   FileWriteArray(h,data.d_arr);
   FileWriteInteger(h,ArraySize(data.i_arr));   FileWriteArray(h,data.i_arr);
   FileWriteInteger(h,ArraySize(data.c_arr));   FileWriteArray(h,data.c_arr);
   FileWriteInteger(h,data.a);
   FileWriteDouble(h,data.b);
   FileClose(h);  
   return(true);
}

bool LoadMStructInFile(const string fname,SMystruct &data)
{
   int h = FileOpen(fname,FILE_READ | FILE_BIN | FILE_COMMON);
   if(h<0) { Print("Write IO Err #",GetLastError()); return(false); } 
   int amount = ArrayResize(data.d_arr,(int)FileReadInteger(h));     FileReadArray(h,data.d_arr,0,amount);
       amount = ArrayResize(data.i_arr,(int)FileReadInteger(h));     FileReadArray(h,data.i_arr,0,amount);
       amount = ArrayResize(data.c_arr,(int)FileReadInteger(h));     FileReadArray(h,data.c_arr,0,amount);
   data.a = FileReadInteger(h);
   data.b = FileReadDouble(h);
   FileClose(h); 
   return(true);
}

2020.03.25 10:18:36.058 tst (EURUSD,H1) 1. d_arr

2020.03.25 10:18:36.058 tst (EURUSD,H1) ・3.14159・3.14159・3.14159

2020.03.25 10:18:36.058 tst (EURUSD,H1) 2. i_arr

2020.03.25 10:18:36.058 tst (EURUSD,H1) 1234567890 1234567890

2020.03.25 10:18:36.058 tst (EURUSD,H1) 2. c_arr

2020.03.25 10:18:36.058 tst (EURUSD,H1) 127 127 127 127

2020.03.25 10:18:36.058 tst (EURUSD,H1) mstruct.a = 666 , mstruct.b = 123.123000

すなわち,配列の次元が動的である場合,書き込み時には配列の次元そのものを書き込み,読み込み時にはファイルから配列のサイズの値を読み込んで,構造体の配列の次元を設定することを意味する

私の例では、2つの構造体があり、1つは初期化されて書き込まれ、もう1つはファイルデータから読み込まれて初期化されています。
理由: