May 08, 2024, 03:30:15 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Passing an array?

Started by lviklund, February 24, 2006, 11:09:26 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

lviklund

How do I pass an array of strings to a function? ???

String foo[10];

//Fill the array....

sub myFunc(string in[]), int
{
  //...
  return;
}

myFunc(foo[]) ; <----------- ??? ??? ???

Parker

Leave the brackets out.

The first part is fine, but call it like
myFunc(foo);

Aurora doesn't check bounds though, so it's a good idea to pass a parameter telling how many items there are so you don't try to read unowned memory.

lviklund

Thank's Parker

You mean something like this:

int num;
num = 10;
String foo[num];

//Fill the array....

sub myFunc(string in[], int num), int
{
  //...
  return;
}

myFunc(foo, num) ;

Parker

;D Kind of.

Now the first part isn't quite right. You have to know the size of the array at compile time. If you want to use a constant, you can do that.

const num = 10;
string foo[num];

sub myFunc(string in[], int num)
{
    for (i = 0; i < num; i++)
    {
        in = num;
    }
}

myFunc(foo, num);

would work.

John S

my understanding is that in:

const num = 10;
string foo[num];


"foo" is a pointer to the first element in the array foo[] so what you are doing is using a pointer.   That's why you need to tell the function how many elements you have.  Of course you could include an extra (final) element which is null and test for it in the function.
John Siino, Advanced Engineering Services and Software

lviklund

Thank's for the answers but as usuall answers gives more questions ;).

Why:
const num = 10;

why not:
int num;
num = 10;
???
Is there any important difference?

Ionic Wind Support Team

Becuase arrays are defined by constants.  The size of an array needs to be known by the compiler at compile time, and not run time.

Ionic Wind Support Team

lviklund

Ah, I see (I think  :P)
Thank's
Lasse

Bruce Peaslee

Quote from: lviklund on February 25, 2006, 06:44:54 AM
Ah, I see (I thinkÂÃ,  :P)
Thank's
Lasse
Constants are defined immediately as the compile progresses so the compiler knows the value when it encounters the array definition.

int num=10;

is not set until the program actually executes which is too late as array dimensions are fixed when the program is compiled.

One can either create an array to hold the largest possible number of elements (which can waste space) or use a linked list.
Bruce Peaslee
"Born too loose."
iTired (There's a nap for that.)
Well, I headed for Las Vegas
Only made it out to Needles

John S

The compiler needs to know an arrays number of elements at compile time.

string foo[10];

or

const num = 10;    // complier knows num is 10
string foo[num];

For dynamic arrays (where you can vary the number of elements), you use 'new' and 'delete' to allocate and deallocate memory dynamically (on the fly) . In C++ you could write ( with floats )  :


    int num = 10;                  // a variable that compiler does not know the value
                                   // of at compile time, only at runtime is it known

    float *foo = new float[num];  // memory is allocated at runtime for pointer of len(float*num)

    if (!foo)                     // check if foo fails to be allocated
      {
       cout << "there is insufficient memory for foo \n";
      }
    else
      {
       .
       .                           // do somesthing with foo[]
       .
       delete foo;                 // always free up the memory used with new
      }


I'm reading all of Paul's stuff to see how this is written in Aurora.
John Siino, Advanced Engineering Services and Software

Parker

In Aurora that's written

int num=10;

float *foo = new(float, num);

if (foo = NULL)
    writeln("there is insufficient memory for foo\n")
else
    delete foo;


I'm not quite sure if a block if needs to be used when a block else is... in C/C++ there are no "block if"s, { statement list } is included in the definition for statement so you can do all kinds of crazy stuff ;)

John S

February 25, 2006, 12:04:32 PM #11 Last Edit: February 25, 2006, 12:07:10 PM by John S
thanks Parker,  I just found the new () function and was trying it out. my example barfed on the the if (!foo) and then on other statements using floats so I went to doubles.

I ran this and I'm getting the same numbers each time.  I know I'm reading memory.  I guess because it is uninitialized those are bits of data in memory left over from something else.  I'm going try un-commenting the assignment line after I send this post in case some bad happens.

edit:  I un-comment that assignment line, but I get an error: "...\dynamic_array.src (23) Invalid assignment"


  //  dynamic_array.src

  global sub main ()
  {
    int num = 10;                    // a variable that compiler does not know the value
                                     // of at compile time, only at runtime is it known

    double *foo = new ( double, num+1);  // memory is allocated at runtime for pointer of len(double*num)

    if ( foo = NULL )                   // check if foo fails to be allocated
      {
       writeln ("there is insufficient memory for foo");
      }
    else
      {
       writeln("there is sufficient memory for foo\n");
       writeln("a double variable is  " + numtostr( len ( double ) ) + " bytes long\n" );
       writeln("the length of foo in memory " + numtostr( len ( double ) * num ) + " bytes long\n\n" );
       double nn = 0;
       for ( int n = 0; n <= num; n++ )
         {
           nn = nn+1.0;
           foo[n] = sqrt(nn) + 1.0;   // fill foo[] a value
           writeln(numtostr( foo[n] ) + "\n" ); // show foo's values
         }
       delete foo;                     // always free up the memory used with new
      }
    while (GetKey() = "");

    return;
  }
John Siino, Advanced Engineering Services and Software

Parker

You should be getting the numbers, if not something's wrong and your computer can't decide on how long a double type should be ;)

To print the address of the pointer, try this:
writeln( "The address of foo is " + NumToStr( foo ) + "\n" );
foo contains an address, *foo contains a value. And len( double ) * num will always return 80, the size of 10 doubles.

John S

February 25, 2006, 12:18:56 PM #13 Last Edit: February 25, 2006, 12:20:57 PM by John S
 :( for some reason it wants to treat foo[] as an array of int.  When I change the assignment line to read:  foo[n] = n;  I get only two values 

??? I rewrote the code and got this scary error message:

Compiling...
dynamic_array.src
File: D:\...l\dynamic_array.src  (21) Warning: Temporary string assigned to POINTER, possible memory loss
File: D:\...l\dynamic_array.src  (22) illegal operand
Error(s) in compiling D:\...l\dynamic_array.src

edit:  I'm already suffering hair loss and hearing loss.  Now my memory too!


  //  dynamic_array.src
  global sub main ()
  {
    int num = 4;                        // a variable that compiler does not know the value
                                        // of at compile time, only at runtime is it known

    string *foo = new ( string, num + 1 ); // memory is allocated at runtime for pointer of len(string*num)

    if ( foo = NULL )                   // check if foo fails to be allocated
      {
       writeln ("there is insufficient memory for foo");
      }
    else
      {
       writeln("there is sufficient memory for foo\n");
       writeln("a string variable is  " + numtostr( len ( string ) ) + " bytes long\n" );
       writeln("the length of foo in memory " + numtostr( len ( string ) * num ) + " bytes long\n\n" );
       for ( int n = 0; n <= num; n++ )
         {
           foo[n] = numtostr( n );     // fill foo[] a value
           writeln( foo[n] + "\n" );   // show foo's values
         }
       delete foo;                     // always free up the memory used with new
      }
    while (GetKey() = "");

    return;
  }

John Siino, Advanced Engineering Services and Software

Bruce Peaslee

February 25, 2006, 12:19:44 PM #14 Last Edit: February 25, 2006, 12:22:42 PM by peaslee
Try this:

// ÂÃ, dynamic_array.src

ÂÃ, global sub main ()
ÂÃ, {
ÂÃ,  ÂÃ, int num = 10; ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ, // a variable that compiler does not know the value
ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  // of at compile time, only at runtime is it known

ÂÃ,  ÂÃ, double *foo = new ( double, num+1); ÂÃ, // memory is allocated at runtime for pointer of len(double*num)

ÂÃ,  ÂÃ, if ( foo = NULL ) ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  // check if foo fails to be allocated
ÂÃ,  ÂÃ,  ÂÃ, {
ÂÃ,  ÂÃ,  ÂÃ,  writeln ("there is insufficient memory for foo");
ÂÃ,  ÂÃ,  ÂÃ, }
ÂÃ,  ÂÃ, else
ÂÃ,  ÂÃ,  ÂÃ, {
ÂÃ,  ÂÃ,  ÂÃ,  writeln("there is sufficient memory for foo\n");
ÂÃ,  ÂÃ,  ÂÃ,  writeln("a double variable is ÂÃ, " + numtostr( len ( double ) ) + " bytes long\n" );
ÂÃ,  ÂÃ,  ÂÃ,  writeln("the length of foo in memory " + numtostr( len ( double ) * num ) + " bytes long\n\n" );
ÂÃ,  ÂÃ,  ÂÃ,  double nn = 0;
ÂÃ,  ÂÃ,  ÂÃ,  for ( int n = 0; n <= num; n++ )
ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  {
ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  nn = nn+1.0;
ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  *foo[n] = sqrt(nn); ÂÃ,  // fill foo[] a value
ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  writeln(numtostr(nn)+" ÂÃ, "+numtostr( *foo[n],4 ) + "\n" ); // show foo's values
ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  }
ÂÃ,  ÂÃ,  ÂÃ,  delete foo; ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  // always free up the memory used with new
ÂÃ,  ÂÃ,  ÂÃ, }
ÂÃ,  ÂÃ, while (GetKey() = "");

ÂÃ,  ÂÃ, return;
ÂÃ, }
Bruce Peaslee
"Born too loose."
iTired (There's a nap for that.)
Well, I headed for Las Vegas
Only made it out to Needles

John S

February 25, 2006, 12:41:28 PM #15 Last Edit: February 25, 2006, 12:47:07 PM by John S
Thanks Peaslee, that did the trick.  I tweaked your code a little:


//  dynamic_array.src
global sub main ()
{
   int num = 4;                    // a variable that compiler does not know the value
                                    // of at compile time, only at runtime is it known

   double *foo = new ( double, num+1);  // memory is allocated at runtime for pointer of len(double*num)

   if ( foo = NULL )                   // check if foo fails to be allocated
     {
      writeln ("there is insufficient memory for foo");
     }
   else
     {
      writeln("there is sufficient memory for foo\n");
      writeln("a double variable is  " + numtostr( len ( double ) ) + " bytes long\n" );
      writeln("the length of foo in memory should be " + numtostr( len ( double ) * num ) + " bytes long\n\n" );
      writeln("the length of foo in memory is " + numtostr( foo ) + " bytes long\n\n" );

      for ( int n = 0; n <= num; n++ )
        {
          *foo[n] = 10^n;            // fill foo[] a value
          writeln(numtostr(n)+"  "+numtostr( *foo[n],4 ) + "\n" ); // show foo's values
        }
      delete foo;                     // always free up the memory used with new
     }
   while (GetKey() = "");

   return;
}


here's the output I got.  Notice the size of foo when I try to read it directly with len.

there is sufficient memory for foo
a double variable is  8 bytes long
the length of foo in memory should be 32 bytes long

the length of foo in memory is 1335440 bytes long

0  1.0000
1  10.0000
2  100.0000
3  1000.0000
4  10000.0000

I'm pretty sure numtostr(len(foo)) is returning the address in foo
John Siino, Advanced Engineering Services and Software

John S

I got the example to work with bytes as well:

//  dynamic_byte_array.src
global sub main ()
{
   int num = 4;                    // a variable that compiler does not know the value
                                    // of at compile time, only at runtime is it known

   byte *foo = new ( byte, num+1);  // memory is allocated at runtime for pointer of len(byte*num)

   if ( foo = NULL )                   // check if foo fails to be allocated
     {
      writeln ("there is insufficient memory for foo");
     }
   else
     {
      writeln("there is sufficient memory for foo\n");
      writeln("a byte variable is  " + numtostr( len ( byte ) ) + " bytes long\n" );
      writeln("the length of foo in memory should be " + numtostr( len ( byte ) * num ) + " bytes long\n\n" );
      writeln("the length of foo in memory is " + numtostr( foo ) + " bytes long\n\n" );

      for ( int n = 0; n <= num; n++ )
        {
          *foo[n] = numtostr(2*n);                    // fill foo[] a value
          writeln(numtostr(n)+"  "+ *foo[n] + "\n" ); // show foo's values
        }
      delete foo;                     // always free up the memory used with new
     }
   while (GetKey() = "");

   return;
}


However, when I rewrote it for string, the output identical to that of byte (above) . 

Notice that the length of string returned from numtostr( len ( string ) ) = 1 byte
John Siino, Advanced Engineering Services and Software

Parker

I don't know what len( foo ) would be, I've never tried it. The LEN function tells the length, so it's probably 8. To get the address, just do this
writeln( NumToStr( foo ) );
since foo is a pointer. If you had just a normal float variable, you'd have to do
writeln( NumToStr( &foo ) );

Earn

February 25, 2006, 01:43:38 PM #18 Last Edit: February 25, 2006, 01:45:14 PM by Earn
Maybe this will help.

foo is a pointer (an unsigned int) so len(foo) = 4 bytes
dereference foo = *foo = *foo[0] so len(*foo) = len(*foo[0]) the number of bytes will depend upon the variable type in foo for a double that would be 8 bytes.

In your example
int num = 4
*foo = new ( double, num+1)
the amount of memory allocated for foo is 8 * 5 = 40 bytes or len(*foo)*num+1)

Earn 8)

John S

yeah, I agree with you all but that is not what I get when you apply len(foo).

I made a feeble attempt at creating a 4x4 matrix using pointer and **foo like they show in my C++ book but it didn't work.

I did get get this to work:


// dynamic_int_matrix.src
global sub main()
{
  num = 4;

  int *pMatrix;
  pMatrix = new( int, num*num );    // for a square matrix

  if ( pMatrix = null )
   {
     writeln("insufficient memory\n");
   }
  else
   {
    for(int m = 0; m <= num-1; m++)
      {
      for(int n = 0; n <= num-1; n++)
        {
          *pMatrix[m][n] = (1+m)*10+n+1;
          writeln( numtostr( *pMatrix[m][n] ) + "   " );
        }
      writeln( "\n" );
      }
    delete pMatrix;
   }
  while (GetKey() = "");

  return;
}


I does make a nice presentation of a matrix though ;)
John Siino, Advanced Engineering Services and Software

Parker

February 25, 2006, 04:51:54 PM #20 Last Edit: February 25, 2006, 04:53:25 PM by Parker
As far as I know Aurora only supports 1 level of pointers. In C you can do int **x; // pointer to pointer to int

A good example is the main() function:
int main( int argc, char **argv )
You can also write it as char *argv[], they're equivalent because an array is passed by address instead of by value. It's a pointer to a character array. In Aurora we would write string argv[].

Ionic Wind Support Team

Aurora supports multiple indirection but forces typecasting on the second level.

*(string)*(pointer)p;

len(foo) won't show the size of an array allocated with NEW.  NEW uses GlobalAlloc on Windows so you could use the API function GlobalSize if you needed to know the memory size of something allocated with NEW.

GlobalSize will return the size to the nearest 8 bytes, since that is how windows manages memory.

NumToStr(foo) is just returning the address stored in the pointer.
Ionic Wind Support Team

John S

I tried the same basic format and got *pMatrix[m][n][k][l] to work I thought you could only do 3 dimensions in Aurora.
I dimensioned the vector as pMatrix[num][num][num][num].  It didn't like num^4, but it took num*num*num*num

1111    1112    1113
1121    1122    1123
1131    1132    1133

1211    1212    1213
1221    1222    1223
1231    1232    1233

1311    1312    1313
1321    1322    1323
1331    1332    1333


2111    2112    2113
2121    2122    2123
2131    2132    2133

2211    2212    2213
2221    2222    2223
2231    2232    2233

2311    2312    2313
2321    2322    2323
2331    2332    2333


3111    3112    3113
3121    3122    3123
3131    3132    3133

3211    3212    3213
3221    3222    3223
3231    3232    3233

3311    3312    3313
3321    3322    3323
3331    3332    3333


// dynamic_double_matrix.src
global sub main()
{
  int num = 3;

  double *pMatrix;
  pMatrix = new( double, num*num*num*num );

  if ( pMatrix = null )
   {
     writeln("insufficient memory\n");
   }
  else
   {
    for(int i = 0; i <= num-1; i++)
      {
      for(int j = 0; j <= num-1; j++)
        {
        for(int k = 0; k <= num-1; k++)
          {
          for(int l = 0; l <= num-1; l++)
            {
            *pMatrix[i][j][k][l] = (1+i)*1000+(1+j)*100+10*(k+1)+l+1;
            writeln( numtostr( *pMatrix[i][j][k][l] ) + "    " );
            }
          writeln( "\n" );
          }
        writeln( "\n" );
        }
      writeln( "\n\n" );
      }
    delete pMatrix;
   }
  while (GetKey() = "");

  return;
}


;D This is the kind of stuff I need for my matrix/linear algebra stuff  ;D
I can even set up triangular matrices with efficient memory usage.

How do I expand the matrix if I need to?  Add a row and/or column?
John Siino, Advanced Engineering Services and Software

Ionic Wind Support Team

February 25, 2006, 08:04:54 PM #23 Last Edit: February 25, 2006, 09:03:35 PM by Ionic Wizard
I have no idea why that didn't give you a syntax error ;)  Accessing an array in Aurora is done like so:

array[0,10,10]

Not the C way of

array[0][10][10]

Although it appears works I will have to do a bit of testing on the assembly output to verify what it's doing.

Ionic Wind Support Team

John S

lviklund's Motto is " It's not a bug. It's a feature! "

don't fix it if it works
John Siino, Advanced Engineering Services and Software