Hello:
(I am using Borland C++ Builder 6 Professional)

Before you jump all over me I've already read the post Returing Arrays C/C++ and completely understand. For some reason I am still having difficulty implementing in my project.

Very brief Project Explanation:

I am collecting data from a laser sensor and want to display my data in cartesian coordinates. I've already created a class that has captured the raw data, converted it to cartesian coordinates and stored these coordinates in an array. Return the array to my main form is what I am having trouble with.

Here is a snippet of the member functions I am referring to
(sorry about the long code most of which is of no interest to you)
data gets stored in array xyz_data

void scan_data::add_image(VARIANT & data_array)
{
  if (current_scan>=10)
  {
  current_scan=0;
  }

  // Check if the variant contains a SAFEARRAY
  // Check if the SAFEARRAY is 1D
  if (SafeArrayGetDim (V_ARRAY (&data_array)) != 1 )
  {
    // Not a 1D SAFEARRAY
    throw ("Logic error css_image::add_image()");
  }

  SAFEARRAY * pArray = V_ARRAY (&data_array);

  long * prgn;
  long elements;
  long i, peaks;

  // Get bounds of array and a pointer to its data
  if ((FAILED (SafeArrayGetLBound (pArray, 1, &i))) ||
      (FAILED (SafeArrayGetUBound (pArray, 1, &elements)))||
      (FAILED (SafeArrayAccessData (pArray, (void **)&prgn))))
  {
    // Failed to get bounds or pointer
    throw ("HRESULT error css_image::add_image()");
  }

  // Create a new image


  elements += 1-i;
  long * end = prgn + elements;

  int j=0;
  unsigned int pos, str;
  scan_points[current_scan]=0;
  long ii;

  while (prgn != end)
  {
  scan_points[current_scan]+=1;
  long state=(*prgn)&0xFFFF;
  ii=(*prgn&0xFFFF0000)>>16;
  ++prgn;
  if (ii > 0) //check if any peaks exist, if they do, get position and strength
  {
  //store the first peak in the raw_data array at the position of the next available scan
  pos=*prgn;
  raw_pos[current_scan][j]=pos;
  str=*(prgn+1);
  raw_str[current_scan][j]=str;
  prgn+=2;
  }
    switch(state)
    {
    case 0,void_sample:
    status[current_scan][j]=dropout;
    break;
    case saturated_sample:
    status[current_scan][j]=saturated;
    break;
    case good_sample:
    status[current_scan][j]=normal;
    break;
    default:
    status[current_scan][j]=dropout;
    }
  j++;

  if (j>=Cycle)
  {
  break;
  }

  --ii;
  while (ii >0)
    {
    //ignore the results of the remaining peaks for this pixel position
    prgn+=2;
    --ii;
    }
  }

  SafeArrayUnaccessData (pArray);

  // Make xyz data if we can
  if (!pCurrentCSS)
  {
    // Can't make xyz data
    return;
  }

  VARIANT xyz_array;
  if (pCurrentCSS->convert_to_xyz (&data_array, &xyz_array)!=S_OK)
  {
    throw ("HRESULT error: css_image::add_image");
  };
  pArray = V_ARRAY (&xyz_array);

  xyz_vector * pxyzelem;

  // Get bounds of array and a pointer to its data
  if ((FAILED (SafeArrayGetLBound (pArray, 1, &i))) ||
      (FAILED (SafeArrayGetUBound (pArray, 1, &elements)))||
      (FAILED (SafeArrayAccessData (pArray, (void **)&pxyzelem))))
  {
    // Failed to get bounds or pointer
    throw ("HRESULT error css_image::add_image()");
  }

  elements += 1-i;
  elements /= 3;


  const double max = 10000.0;

  for (i = 0; ((i < elements) && (i<Cycle)); ++i)
  {
    if (pxyzelem->x < max)
    {
      xyz_data[current_scan][0][i] = pxyzelem->x;
      xyz_data[current_scan][1][i] = pxyzelem->y;
      xyz_data[current_scan][2][i] = pxyzelem->z;
    }
    ++ pxyzelem;
  }

  // Destroy the xyz safearray
  SafeArrayUnaccessData (pArray);
  SafeArrayDestroy (pArray);

  current_scan++;
}
void  scan_data::get_image_data(double data[3][Cycle])

{
int num_scans;
bool flag_good;
for (int i=0; i<Cycle; i++)
{
  num_scans=0;
  flag_good=false;
  data[0][i]=0;
  data[1][i]=0;
  data[2][i]=0;
  for (int j=0; j<current_scan; j++)
  {
    if (pos_good(j,i))
    {
    data[0][i]+=xyz_data[j][0][i];
    data[1][i]+=xyz_data[j][1][i];
    data[2][i]+=xyz_data[j][2][i];
    num_scans++;
    flag_good=true;
    }
    else if (j==(current_scan-1)&& flag_good==false)
    {
    //no good scans were available for this pixel location
    data[0][i]=Bad;
    data[1][i]=Bad;
    data[2][i]=Bad;
    }
  }
  if (flag_good)
  {
  //compute average of all the scans collected
  data[0][i]/=num_scans;
  data[1][i]/=num_scans;
  data[2][i]/=num_scans;
  }
}
return;
}

The data[][] array is what I need to return to my mainform. This is the original code and not any of my failed attempts.

Thanks in advance

Array
An array is a collection of like objects. The simplest case of an array is a vector. C++ provides a convenient syntax for declaration of fixed-size arrays:

decl-specifiers  dname  [  constant-expressionopt  ]  ;

The number of elements in the array is given by the constant-expression. The first element in the array is the 0th element, and the last element is the (n-1th) element, where n is the size of the array. The constant-expression must be of an integral type and must be greater than 0. A zero-sized array is legal only when the array is the last field in a struct or union and when the Microsoft extensions (/Ze) are enabled.

Arrays are derived types and can therefore be constructed from any other derived or fundamental type except functions, references, and void.

Arrays constructed from other arrays are multidimensional arrays. These multidimensional arrays are specified by placing multiple [ constant-expression ] specifications in sequence. For example, consider this declaration:

int i2[5][7];

It specifies an array of type int, conceptually arranged in a two-dimensional matrix of five rows and seven columns, as shown in Figure 7.2.

Figure 7.2 Conceptual Layout of Multidimensional Array
[IMG]http://msdn.microsoft.com/library/en-us/vccelng/htm/vc38rc1.gif[/IMG]

In declarations of multidimensioned arrays that have an initializer-list (as described in Initializers), the constant-expression that specifies the bounds for the first dimension can be omitted. For example:

const int cMarkets = 4;

// Declare a float that represents the transportation costs.
double TransportCosts[][cMarkets] =
{ { 32.19, 47.29, 31.99, 19.11 },
  { 11.29, 22.49, 33.47, 17.29 },
  { 41.97, 22.09,  9.76, 22.55 }  };

The preceding declaration defines an array that is three rows by four columns. The rows represent factories and the columns represent markets to which the factories ship. The values are the transportation costs from the factories to the markets. The first dimension of the array is left out, but the compiler fills it in by examining the initializer.

The technique of omitting the bounds specification for the first dimension of a multidimensioned array can also be used in function declarations as follows:

#include <float.h>         // Includes DBL_MAX.
#include <iostream.h>

const int    cMkts = 4;

// Declare a float that represents the transportation costs.
double TransportCosts[][cMkts] =
{ { 32.19, 47.29, 31.99, 19.11 },
  { 11.29, 22.49, 33.47, 17.29 },
  { 41.97, 22.09,  9.76, 22.55 }  };
// Calculate size of unspecified dimension.
const int cFactories = sizeof TransportCosts /
                       sizeof( double[cMkts] );

double FindMinToMkt( int Mkt, double TransportCosts[][cMkts],
                     int cFacts );

void main( int argc, char *argv[] )
{
    double MinCost;
    MinCost = FindMinToMkt( *argv[1] - '0', TransportCosts,
                            cFacts );
    cout << "The minimum cost to Market " << argv[1] << " is: "
         << MinCost << "\n";
}

double FindMinToMkt( int Mkt, double TransportCosts[][cMkts],
                     int cFacts )
{
    double MinCost = DBL_MAX;
    for( int i = 0; i < cFacts; ++i )
        MinCost = (MinCost < TransportCosts[i][Mkt]) ?
                   MinCost : TransportCosts[i][Mkt];
    return MinCost;
}

The function FindMinToMkt is written such that adding new factories does not require any code changes, just a recompilation.

Attachments
Initializers
Declarators can specify the initial value for objects. The only way to specify a value for objects of const type is in the declarator. The part of the declarator that specifies this initial value is called the initializer.

Syntax
initializer : 
= assignment-expression
= { initializer-list ,opt }
( expression-list ) 
initializer-list : 
expression
initializer-list , expression
{ initializer-list ,opt } 
There are two fundamental types of initializers: 

The initializer invoked using the equal-sign syntax 
The initializer invoked using function-style syntax 
Only objects of classes with constructors can be initialized with the function-style syntax. The two syntax forms also differ in access control and in the potential use of temporary objects. Consider the following code, which illustrates some declarators with initializers:

int      i = 7;                  // Uses equal-sign syntax.
Customer Cust( "Taxpayer, Joe",  // Uses function-style
               "14 Cherry Lane", //  syntax. Requires presence
               "Manteca",        //  of a constructor.
               "CA" );

Declarations of automatic, register, static, and external variables can contain initializers. However, declarations of external variables can contain initializers only if the variables are not declared as extern.

These initializers can contain expressions involving constants and variables in the current scope. The initializer expression is evaluated at the point the declaration is encountered in program flow, or, for global static objects and variables, at program startup.

Thanks for the info. However, my question has not been anwered. The above I am already aware of and anything I have forgotten I can go find my textbook from university. What I can not find in that stupid book is how to return and array/pointer properly I've tried the new/delete and get conversion errors etc. This is what I need help with: returning a multidimensional array(probably through a pointer but how?)

Again thank you.

Tim

Thanks for the info. However, my question has not been anwered. The above I am already aware of and anything I have forgotten I can go find my textbook from university. What I can not find in that stupid book is how to return and array/pointer properly I've tried the new/delete and get conversion errors etc. This is what I need help with: returning a multidimensional array(probably through a pointer but how?)

Again thank you.

Tim

Ok now I realise the problem, not using arrays but returning them.
Try making a global variable of some sort & instead of using 'return' just have the later parts of the program access the global variable created by your script that you are trying to add 'return' to.

This what I've done and get:

I've moved array xyz_data[10][3][512] from being a private data member to a public data member of class scan_data. Called my member function(scan_data::add_image)(see above) that does the wanted conversion and stores that data into the now public xyz_data[10][3][512] array.

In the main form of my project I've cut & pasted the code for my member function get_image_data to avoid having to pass and return my array. Below is that snippet:

{
    long scan_id,scan_length;
    double *pelem;

    if(scan_counter>9)
        scan_counter=0;


    css->get_scan(&scan_id,&scan_time,&scan_length,&data);
//  css_data->Add_Image_Data(data);
    scans.add_image(data);
    VariantClear(&data);
    VariantClear(&scan_time);

  double *holder;
  holder=scans.xyz_data;

  int num_scans;
  bool flag_good;
  double xyz_array[3][Cycle];
  for (int i=0;i<Cycle;i++)
  {
        num_scans=0;
        flag_good=false;
        xyz_array[0][i]=0;
        xyz_array[1][i]=0;
        xyz_array[2][i]=0;

        for (int j=0;j<scan_counter;j++)
        {
                if(scans.pos_good(j,i))
                {
                        xyz_array[0][i]+=holder[j][0][i];
                        xyz_array[1][i]+=holder[j][1][i];
                        xyz_array[2][i]+=holder[j][2][i];
                        num_scans++;
                        flag_good=true;
                }
                else if (j==(scan_counter-1)&& flag_good==false)
                {
                        xyz_array[0][i]=Bad;
                        xyz_array[1][i]=Bad;
                        xyz_array[2][i]=Bad;
                }
        }
        if(flag_good)
        {
                xyz_array[0][i]/=scan_counter;
                xyz_array[1][i]/=scan_counter;
                xyz_array[2][i]/=scan_counter;
        }
  }
    Label4->Caption=FloatToStr(xyz_array[scan_counter][509]);
    Label5->Caption=FloatToStr(xyz_array[scan_counter][509]);
    Label6->Caption=FloatToStr(xyz_array[scan_counter][509]);
    scan_counter++;

}

the error I get is this:
[C++ Error] Unit1.cpp(213): E2034 Cannot convert 'double ( *)[3][512]' to 'double *'
[C++ Error] Unit1.cpp(230): E2062 Invalid indirection


What am I doing wrong....I am not seeing something here that is probably obvious.

Thanks

I am somewhat new to C++ (all programming for that matter) but what I figured out is that if I simply pass the array that I want to be changed as a parameter to the function that would have returned the multidimensional array I can have that function change the data to whatever I need it to be. Probably not what you are looking for and definitely not great programming but I just thought I would throw it out there.

Ex.

int (*data)[9][9];


void *getData(int (*dataToBeChanged)[9][9]) {
dataToBeChanged = data;
}

As you can see above, 'data' is a pointer to a multidimensional array. After passing a multidimensional array of the same size to 'getData', the 'dataToBeChanged' referenced the same array.

Good luck! Looks like your doing some pretty cool stuff.

Edited 3 Years Ago by happygeek: fixed formatting

hey TJW iam doingthe exact same thing and i ran into the same problem so did you find any solution..

hey TJW iam doingthe exact same thing and i ran into the same problem so did you find any solution..

i had the same problem, error message (cannot convert int [80][64] to int *) but i got it to work now.

as you may know, the compiler interprets array_name[0] and instantly converts it to *(array_name+0). so i did two different ways that worked.
return *array_name; // returns an int *
and
return &(array_name[0][0]) // also returns int *
i will check to make sure its good data in both cases but at least it compiled, and i am pretty sure it will give the right address

tricky but efficient

class myClassWithArrayMember
{
private:
   double _something[3];
public:
   void setValue(double sth[3])
    {
      _something[0] = sth[0];
      _something[1] = sth[1];
      _something[2] = sth[2];
    };
   //and now the member function to get it out:
   const double* getValue() const {return _something;};
}

then one will be able to use:

//within a suitable main proram:

myClassWithArrayMember myObject;
double sth[3] = {2,34,56.7};
myObject.setValue(sth);
std::cout<<myObject.getValue()[0]<<std::endl;
std::cout<<myObject.getValue()[1]<<std::endl;
std::cout<<myObject.getValue()[2]<<std::endl;

I think it's the definitive answer to this thread.
Cheers

This article has been dead for over six months. Start a new discussion instead.