How do I fix the mql4 error "array out of range"? - mql4

I am trying to add an indicator code. While everything compiles just fine, the terminal shows the error, "array out of range".
This is the code that reads the price data from the .csv file and draws it as an indicator on the current chart.
The .csv file contains three months' price data in the form of 1 minute period.
#property indicator_buffers 1
#property indicator_color1 White
double ExtMapBuffer1[];
bool Calculated=false;
extern datetime endDateTime=D'2021.03.31 05:59:00';
int init()
{
SetIndexStyle(0,DRAW_LINE,0,1);
SetIndexBuffer(0,ExtMapBuffer1);
return(0);
}
int start()
{
int i,counted_bars=IndicatorCounted();
if (!Calculated)
{
double PriceArray[24*60*30*1]; **//issue1**
string lastDT = endDateTime;
if (!ReadCSVToArray(PriceArray,lastDT,fileName,"","\n")) Print("Reading file error: ",GetLastError());
int bars=ArraySize(PriceArray);
int firstBar = iBarShift(symbolName,PERIOD_M1,endDateTime);
ExtMapBuffer1[bars+firstBar-1]=PriceArray[0]; **//error1: array out of range**
for (i=2;i<=bars;i++)
{
ExtMapBuffer1[bars+firstBar-i]=PriceArray[i-1];
}
for (i=firstBar-1;i>=0;i--)
{
ExtMapBuffer1[i]=0;
}
Calculated=true;
}
return(0);
}
issue1: If I set the size of PriceArray as a big value for 3 month's data, such as 246030*3, I could meet the compile error: "local variables is larger than 512KB"
error1: If the size of PriceArray is small, the compiling is fine but running error.
Any help is appreciated.

To correctly read a csv's of variable or unknown length, you should use the first dimension of the array for your rows and the second dimension for your columns. You would therefore have an array statement of string data[1][5]; for a csv which contained date/O/H/L/C for example.
You can then resize your array as you loop through reading your csv file as follows:
int handle=FileOpen(FileName,FILE_CSV|FILE_READ,",");
if(handle==INVALID_HANDLE) Print("Error opening file ",GetLastError());
else
{
int row=0;
while(!FileIsEnding(handle))
{
if(row>0) ArrayResize(data,row+1);
//carry out array reading here
data[row][0]=FileReadString(handle); //date
data[row][1]=FileReadString(handle); //open
data[row][2]=FileReadString(handle); //high
data[row][3]=FileReadString(handle); //low
data[row][4]=FileReadString(handle); //close
row++;
}
FileClose(handle);
}
Note, you can not resize the 2nd dimension of a multi dimensional array so this dimension must match the structure of your csv file.

Related

String to int conversion not working swift

I am trying to do some operation on an array of digits. i wish to combine them and do something. i know reduce operation also works but i am not sure why this is not working.
var digits = [7,2,8,5,0,9,1,2,9,5,3,6,6,7,3,2,8,4,3,7]
var strDigits = ""
for i in digits
{
strDigits += String(i)
}
print(strDigits)
if let number = Int(strDigits) {
print(number)
}
else{
print("didnt work")
}
this will print didnt work. if i reduce the elements in array by 1 it starts working again and print the number. why is the limitation that string cant be cast to int if the string is too long?
When you concat all the numbers to string, the number then becomes too big for Int64 too handle, whose upper limit is 9223372036854775807, whereas your number is 72850912953667328447.
Edited for Martin's correction.

Random number generator function that doesn't repeat itself

Does swift by default has a random number generator that returns the same number only once?
For example it picks a number in range 1,2,3,4,5. Return that random number (lets say 3). In the next loop, it picks only from 1,2,4,5 and so on.
EDIT:
This is what I ended up using. It returns an array of integers from 0-5 and was tested in playground. Note that this is meant to be used when you are picking from a large set of Integers and not just 6.
func generateRandomArray() -> [Int]{
var randomImages: [Int] = [Int]()
var newRandomNumber = Int(arc4random_uniform(UInt32(6)))
while (randomImages.count < 6) {
if (randomImages.contains(newRandomNumber) == false){
randomImages.append(newRandomNumber)
}
newRandomNumber = Int(arc4random_uniform(UInt32(6)))
}
return randomImages
}
This kind of generator is not called a "random number" generator, but usually
a "Shuffle" or "Permute".
You have to tell it how many items there are first. Otherwise what you are proposing doesn't make any sense!
see answer here: How do I shuffle an array in Swift?
You can do this trick, Add the range of numbers from which you want to get the random result..to an NSMutableArray or NSMutableSet(to make sure there is only 1 of it).
Iterate through the array-
for(int i=0;i<myMutableArray .count;i++){
int randomIndex = arc4random_uniform(myMutableArray.count);
int myNumber = [[myMutableArray objectAtIndex:randomIndex]intValue]; // edited
NSLog(#"My random number-%i",myNumber);//this is your generated random number
[myMutableArray removeObjectAtIndex:randomIndex];
}
I guess this would do the tric, But if you do rmember NSMutableArray cannot take Primitive data type, just Objects like NSNumber.
EDIT
this line is not written and is justifying that why i am converting the NSNumber back to an interger because while adding the integer in the Array it has to be converted to a NSNumber|
[ myMutableArray addObject:[NSNumber numberWithInt:2]];
So in the for loop when i am getting the object from myMutableArray i am getting an NSNumber and to simplify it i casted that Object (NSNumber object) back to an integer.
From Apple's documentation:
A set stores distinct values of the same type in a collection with no
defined ordering.
This seems to be exactly what you are after, so making an array seems a bit ill-advised...
var values : Set<Int> = []
var value : Int {
return Int(arc4random() % 6 + 1)
}
while values.count < 6 {
values.insert(value)
}
And you probably want to have a look at those values somewhere down the line:
for value in values {
println(value)
}
Just store the last random number in a variable and check the next random number against it in a while loop. While the new random number is the same as the last random number, generate a new random number. Once the new random number generated is not the same as the last random number the while loop ends and we update the last random number.
var lastRandomNumber = 0
var newRandomNumber = 0
func gernerateRandomNumber() {
newRandomNumber = Int(arc4random_uniform(5)+1)
while newRandomNumber == lastRandomNumber {
newRandomNumber = Int(arc4random_uniform(5)+1)
}
lastRandomNumber = newRandomNumber
}

Invalid rank specifier

I am trying to create a dungeon crawler with a tile-based map. However, I get an error when creating the array of tiles. (Right now, Tile is a class with nothing but an empty constructor.)
class Map
{
Tile[][] Tiles;
static const int DefaultWidth = 640, DefaultHeight = 480;
Random rnd;
public Map(int? Width, int? Height, int? seed)
{
Tiles = new Tile[((Width == null) ? DefaultWidth : (int)Width)]
//This line gives the error "invalid rank specifier: expected ',' or ']'" after the first bracket
[((Height == null) ? DefaultHeight : (int)Height)];
Generate();
}
void Generate()
{
}
}
Why am I getting this error?
In C#, the right way to instantiate a 2D array is to use a comma instead:
int[,] array = new [3,2];
You can still make arrays such as int[][], but you'll need to use a for loop to create every individual array inside it (which can be of different lengths), and this is known as a jagged array. I would recommend, however, to use the comma syntax as it is idiomatic in C# and is the expected way to do things.

D: What will s refer to in foreach(ref s; sections[0..$/2+1])

What are the indices these two foreach loops will iterate over:
struct Section{}
Section[] sections;
// assuming we have 10 sections
foreach(ref s; sections[0..$/2+1]) {
// do something
}
foreach_reverse(ref s; sections[$/2..$])
{
// do something
}
the first will iterate over 0-sections.length/2+1=6 (exclusive) and the second will iterate 10-5
the $ in the index refers to the length of the array
and the array[a..b] notation expands to array.opSlice(a,b) that returns a partial view of the array
In D, an empty struct has a size 1. The rationale is the same as in C++: see here for a relevant question and the rationale. So, your array will contain dummy 1-byte elements.
Let us check this behavior:
import std.stdio;
struct Section{}
Section[] sections = new Section [10];
void main () {
foreach(ref s; sections[0..$/2+1]) {
writeln (&s);
}
}
To me, this prints:
42208C
42208D
42208E
42208F
422090
422091
which are consecutive addresses in memory.

How to get the length of an array?

How to get the length of a string array like
str 30 name[];//dynamic array
I used the following for getting the length,but it showing the error as "the variable is not of the type CLASS."
int len=name.get_length();
It sounds like you might be happier using the Array collection class.
http://msdn.microsoft.com/en-us/library/array.aspx
static void TestArray(Args _args)
{
Array strArray = new Array(Types::String);
;
strArray.value(1, 'abc');
strArray.value(2, 'def');
info(strfmt("%1", strArray.lastIndex()));
}
You need the dimOf function. Take a look to the reference:
http://msdn.microsoft.com/en-us/library/aa597117.aspx
Sorry, there is no build-in function to return the string array size. Since you are in full control what you put in the array, there need not be any!
The built-in function dimof returns the allocated size of the array, which is only of practical value for a fixed size array like str 30 name[20], where dimof(name) returns 20.
A clean way to remain in control, is to use a setter function:
static void TestArray(Args _args)
{
str 30 name[];
int n = 0;
int i;
void nameSet(int _i, str 30 _name)
{
n = max(n,_i);
name[_i] = _name;
}
;
nameSet(2,'abc');
nameSet(4,'def');
for (i = 1; i <= n; i++)
info(name[i]);
}
There is no upper bound index limit, so accessing name[7] is perfectly valid and in this case returns a blank value. This may be used to your advantage, if you always use all holes and never stores a blank:
static void TestArray(Args _args)
{
str 30 name[];
int i;
name[1] = 'abc';
name[2] = 'def';
for (i = 1; name[i]; i++)
info(name[i]);
}
Beware that accessing a higher index (in this case higher than 2) may in fact increase the allocated size of the array.

Resources