エラー、バグ、質問 - ページ 1438

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

そして、配列のサイズの 問題が解決されるとき、やはり最初に呼び出すときにpr_openとpr_closeがどんな値を持っているかを確認するべきだと思います。


追記:ここでは初期化されていません。

...
int            buf_lup[], buf_ldn[];
...
void OnTick()
{
   int      lup, ldn, sup, sdn;
   int      sum_up, sum_dn;
   double   pr_open, pr_close;

.........

      ldn = 0;
      sup = 0;
      sdn = 0;
      sum_up = 0;
      sum_dn = 0;

.........

               buf_ldn[ldn] = (int)((pr_open - pr_close) / Point()); // ОШИБКА тут
               sum_dn += buf_ldn[ldn++];

........
}

で、何かが割り当てられていることは、コード上ではわからない。

もしかしたら、この中のどこかに初期化が隠されているかもしれませんが。

.........

の行を隠すことができます。

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

その通り )))何の問題もないんです。

一般に、動的配列の サイズを常に把握するのは、ちょっと不便ですよね...。重さを知る必要がある。それじゃ、何のために?

要は、何個の要素が入るか事前に分からないのであれば、保証された大きさの静的配列を宣言して(余裕を持って、どんな場合でも収まるように)メモリを浪費する必要はない、ということです。つまり、新しいデータを追加する必要があるときに、動的に配列のサイズを大きくするのです。
 
Сергей Таболин:

これは原理的に理解できることです。ただひとつわからないのは、なぜこの配列が自動的にインクリメントされないのか、ということです。

なぜ、そのようにできなかったのでしょうか。私の考えではない ))))まさに、ダイナミックアレイを 使おうとしたのですが...。

さらに、インデックスを保存しなければならないので...。良くないな...。

ダイナミックに拡大できないなんて、誰が言ったの?

ここで、あなたをサポートします

ArrayResize

Устанавливает новый размер в первом измерении массива



int  ArrayResize( 
   void&  array[],              // массив, переданный по ссылке 
   int    new_size,             // новый размер массива 
   int    reserve_size=0        // резервное значение размера (избыточное) 
   );
 

Параметры

array[]

[out]  Массив для изменения размеров.

new_size

[in]  Новый размер для первого измерения.

reserve_size=0

[in]  Необязательный параметр. Размер для дополнительного резерва.

Возвращаемое значение

При успешном выполнении функция возвращает количество всех элементов, содержащихся в массиве после изменения размера; в противном случае возвращает -1 и массив не меняет размеры.

Примечание

Функция может быть применена только к динамическим массивам. При этом необходимо иметь ввиду, что нельзя изменять размер для динамических массивов, назначенных в качестве индикаторных буферов функцией SetIndexBuffer(). Для индикаторных буферов все операции по изменению размера производит исполняющая подсистема терминала.

Общее число элементов в массиве не может превышать 2147483647.

При частом распределении памяти рекомендуется использовать третий параметр, задающий резерв для уменьшения количества физического распределения памяти. Все последующие вызовы функции ArrayResize не приводят к физическому перераспределению памяти, а только меняется размер первого измерения массива в пределах зарезервированной памяти. Следует помнить, что третий параметр будет использоваться только тогда, когда будет происходить физическое распределение памяти, например:



ArrayResize(arr,1000,1000); 
for(int i=1;i<3000;i++) 
   ArrayResize(arr,i,1000);
 

В данном случае произойдёт 2 перераспределения памяти, один раз до входа в цикл на 2000 элементов, при этом размерность массива будет установлена в 1000 и второй при i равной 2000. Если третий параметр опустить, то произойдёт 2000 физических перераспределения памяти и это замедлит выполнение программы.

ヘルプの使い方のヘルプをやるべきだ ))))))))))))))))))))))))))

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

これは原理的に理解できることです。ただひとつわからないのは、なぜこの配列が自動的にインクリメントされないのか、ということです。

int arr[];

arr[] = 1;
arr[] = 9;
arr[] = 3;
....

なぜ、そのようにできなかったのでしょうか。私の考えではない ))))まさに、ダイナミックアレイを 使おうとしたのですが...。

さらに、インデックスを保存しなければならないので...。良くないな...。

このコードで何をしようとしたのか理解できません。

ここでは、動的配列がどのようなもので、どのように使うのか、その例を少し紹介します。

   // динамический массив строк, в который поместим считанные из файла "FileName.txt" строки,
   // количество строк в файле нам неизвестно
   string Strings[];
   ArrayResize(Strings, 0, 20);   // сейчас это массив нулевой длины
   
   // открываем текстовый файл для чтения
   int hFile = FileOpen("FileName.txt", FILE_READ|FILE_TXT);
   
   if(hFile != INVALID_HANDLE)
   {
      // каретку в начало файла
      FileSeek(hFile, 0, SEEK_SET);
      
      // вспомагательные переменные
      string sString;
      int nTotalStrings = 0;
      
      // читаем файл построчно
      while(!FileIsEnding(hFile) && !IsStopped())
      {
         // считываем очередную строку
         sString = FileReadString(hFile);
         
         // добавляем считанную строку в массив, предварительно увеличив его размер на 1
         if(sString != "")
         {
            nTotalStrings++;
            ArrayResize(Strings, nTotalStrings, 20);
            Strings[nTotalStrings-1] = sString;
         }
      }
      
      // уходя, гасите свет
      FileClose(hFile);
   }
   
   // выведем считанные строки в журнал для проверки
   for(int i = 0; i < ArraySize(Strings); i++)
      Print(Strings[i]);
 
Сергей Таболин:

なぜ、この配列が自動的にインクリメントされないのか理解できません。

なぜなら、言語開発者はSyakhで育ったので、MQLがハードコアなSIライクからポップなPHP/JSライクに移行するのを著しく妨げてしまうからです。MQLは、コーダーにその重要性を感じさせます。シャベルを手に、選ばれしプロフェッショナルの一員になることを楽しんでください。
 
Сергей Таболин:

これは原理的に、動的配列に 通常充填する方法の簡単な例である。長いことCで書いてないので覚えていませんが、phpでは配列はこうやって埋めるんですねー。すべてが論理的で理解しやすい。配列に要素を追加する(arr[] = x)と、配列は自動的に展開され、その要素は配列の末尾に追加されます。しかも、自分で伸ばす必要もないし、要素のインデックスを自分で指定する必要もない。しかし、ここでは絶対に無駄な動きをしなければならない。

その差は歴然としている...。

私見ですが、はっきり言っておかしいと思います ))))

それなら、シャベルを持って、まさにそのように動作する動的配列の実装を自分で書けばいいじゃないか。))しかし、MKLが許可しない割り当てのために[]をオーバーロードするのは、十分なハードコアとは言えません。))
 
Сергей Таболин:

これは原理的に、動的配列に 通常充填する方法の簡単な例である。長いことCで書いてないので覚えていませんが、phpでは配列はこうやって埋めるんですねー。すべてが論理的で理解しやすい。配列に要素を追加する(arr[] = x)と、配列は自動的に展開され、その要素は配列の末尾に追加されます。しかも、自分で伸ばす必要もないし、要素のインデックスを自分で指定する必要もない。しかし、ここでは絶対に無駄な動きをしなければならない。

その差は歴然としている...。

はっきり言っておかしいと思う ))))

OOPを使い、似たような構文を実装することを、誰が妨げているのでしょうか?

#property strict

/*
enum TestEnum
{
  zero,
  one,
  two,
  three,
  four,
  five,
  six,
  seven,
  eight,
  nine,
  ten,
  eleven,
  twelve,
  thirteen,
  fourteen,
  fitteen
};
*/

template <typename T>
class RubbArray
{
  private:
    T data[];
    
  protected:
    void add(T d)
    {
      int n = ArraySize(data);
      ArrayResize(data, n + 1);
      data[n] = d;
    }
    
  public:
    
    T operator[](int i) const
    {
      return data[i];
    }
    
    RubbArray *operator<<(T d)
    {
      add(d);
      return GetPointer(this);
    }

    T operator=(T d)
    {
      add(d);
      return d;
    }

    void operator=(const RubbArray &d)
    {
      int i, n = d.size();
      ArrayResize(data, n);
      for(i = 0; i < n; i++)
      {
        data[i] = d[i];
      }
    }

    T operator>>(int i)
    {
      T d = this[i];
      ArrayCopy(data, data, i, i + 1);
      ArrayResize(data, ArraySize(data) - 1);
      return d;
    }
    
    int size() const
    {
      return ArraySize(data);
    }
    
    void print() const
    {
      int i, n = ArraySize(data);
      string s;
      for(i = 0; i < n; i++)
      {
        s += (string)data[i] + ",";
      }
      Print(s);
    }
};

void OnStart()
{
  //RubbArray<TestEnum> d;
  RubbArray<double> d, d2;
  d << 5 << 7;
  d = 10;
  d << 15;
  d.print();
  Print(d[1]);
  double x = d >> 1;
  d2 = d;
  d2.print();
}
 
Alexander Puzanov:
言語開発者はSyakhで育ったので、MQLがハードコアなSIスタイルからポップなPHP/JSライクに移行するのをひどく妨げています。MQLは、コーダーにその重要性を感じさせます。だから、シャベルを持って、選ばれたプロフェッショナルの一員であることを楽しんでください。
私見ですが、単純な配列はプログラマが意識せずに「サイズを調整」してはいけないと思います。そのような動作が必要な場合は、対応するクラスを記述する必要があります。そして、"スマート "アレイを問題なく使用できるようになります。また、配列が最初に属する単純構造 体は、「独立した決定権」を持ってはならない。
 
4人の人がすでにあなたに言っています-そんなに欲しいのなら、シャベルを持ってクラスを書きなさいと。))
 
Сергей Таболин:

"プログラマーが知らないうちに "は通用しない。配列の最後に要素を追加する」(arr[] = x)という命令を出すのはプログラマです。そして、アレイには「独立した決定権」がない。プログラマーのコマンドを実行することによってのみ、そのサイズが大きくなり、プログラマーはそのサイズを把握することから解放されるのである。)))

私の経験では、もしプログラマがインデックス20で10個のアイテムを含む配列に何かを書き込んだとしたら、それはプログラマが間違いを犯したことを意味する可能性が高く、プログラムはエラーを発生させるべきですが、配列のサイズを 大きくしてはならず、それによって疑わしい行為を隠蔽することができます。

これらの「サイズをいじる配列」はすべて、利便性よりも潜在的なエラーを隠してしまうことの方がはるかに問題なのです。さらに、配列のサイズを把握する必要がないことも、修正困難なバグにつながる危険な行為である可能性があります。