Link to home
Start Free TrialLog in
Avatar of unityxx311
unityxx311

asked on

Counting the number of elements of a double **

Hi, in a called function I have counted and allocated the size for this double **, I have now passed it back to the original function. I need to know the number of elements in the y position, i.e. double[x][y], I have tried a few stabs at using sizeof and could only get the size of the pointers, now I am trying to traverse until I reach a NULL, but I am getting the compiler error of: invalid operands to binary !=
Here is a snippet of my traversing code:

  input_index= 0;
  int count_this= 0;
  while (trajectory_data[0][input_index]!= NULL)
    {
      count_this++;
      input_index++;
    }

I am trying to count just the number of elements in trajectory_data[0]

Thanks for any advice and help, I am putting 500 on this one because it is URGENT.
M.
Avatar of Kent Olsen
Kent Olsen
Flag of United States of America image


Depending on where you placed the NULL, this should work.

Kent



  double **Table;
  double **Ptr;
  int       count;

  for (count = 0, Ptr = Table; (*Ptr); Ptr++)
    count++;
Avatar of unityxx311
unityxx311

ASKER

::In Response to Kdo::

Kent, sorry this only counts the number of elements in the 1st position of  **Table
M.
Hi unityxx311,
The y dimension needs a different end-of-list indicator.

It's recommendable that you put the size of the array either in two extra parameters (e.g. xsize, ysize), or each [0] for both axes holds the number of elements.

You could also use something non-existing in normal IEEE numbers as EOL indicator, such as
* negative 0
* non-normalized number

...but make sure you use == or, better, memcmp. That's not a clean solution, though.

Cheers!

Stefan
Hi unityxx311,

IMHO,a better way to get the size of the array would be by passing the two parameters by reference to the function which allocates the memory,and updating these parameters when you allocate memory.

Thus,you'd get the size of the array without doing any processing on the array.
::In Response to ankuratvb::

That sounds like the most sensible solution without making a big mess of my code... what about this... if I know the number of elements in the x position, e.g. 21 and then I counted the total number of elements in the entire array and divided by 21, would this not give me the number of elements in the y position in my 2D array? How would I count the total amount of this 2D array also...
Thanks, M.
>>
if I know the number of elements in the x position, e.g. 21 and then I counted the total number of elements in the entire array and divided by 21, would this not give me the number of elements in the y position in my 2D array?
<<

Yes.

>How would I count the total amount of this 2D array also...

You can use another variable to store the total number of elements in the 2D array,or the number of rows in the 2D array.Either way,you can get the total number of elements.

This way,you dont have to calculate the total number of elements,when using the 2D array in another function.



>>Kent, sorry this only counts the number of elements in the 1st position of  **Table

Sorry, that's what I thought that you wanted to do.

  double **Table;
  double **outer_Ptr;
  double *inner_Ptr;
  int       outer_count;
  int       inner_count;

  for (outer_count = 0, outer_Ptr = Table; (*outer_Ptr); outer_Ptr++)
  {
    outer_count++;
    for (inner_count = 0, inner_Ptr = *outer_Ptr; (*inner_Ptr); inner_Ptr++)
      inner_count++;
/*    Do something with inner_count;  */
  }


Kent
::In Response to Kdo::


Ok, great that inner_count does produce the right number at the end of the outer_count, but  before the last outer_count I get weird results, with a Table size of [21][10003] I get these counts during execution:
out_count: 1    inner_count: 0
out_count: 2    inner_count: 40012
out_count: 3    inner_count: 30009
out_count: 4    inner_count: 20006
out_count: 5    inner_count: 10003
out_count: 6    inner_count: 0
out_count: 7    inner_count: 150045
out_count: 8    inner_count: 140042
out_count: 9    inner_count: 130039
out_count: 10   inner_count: 120036
out_count: 11   inner_count: 110033
out_count: 12   inner_count: 100030
out_count: 13   inner_count: 90027
out_count: 14   inner_count: 80024
out_count: 15   inner_count: 70021
out_count: 16   inner_count: 60018
out_count: 17   inner_count: 50015
out_count: 18   inner_count: 40012
out_count: 19   inner_count: 30009
out_count: 20   inner_count: 20006
out_count: 21   inner_count: 10003

Does someone understand these inner_counts please? BTW, each of the 21 x elements has all 10003 y elements filled.
Thanks, M.

Backup up a second.  Are you using the term [21][10003] symbolically (suggesting that you've actually done 21+1 malloc() calls) or are you hard-wiring the table for test.

Also, are all 10003 elements really filled?  If so did the NULL get placed in the last item or did it overwrite the next buffer?


Kent
::In Response to Kdo::

No hard-wiring, actually doing 21+1 calloc calls, I have checked the file for this test case and the table is being filled with 21 elements in the x position with 10003 in the y.
My allocation:

double **table
table= calloc(data_items_count+ 1, sizeof(double *));
 for(i= 0; i < (data_items_count+ 1) ; i++)
 {
   table[i]= calloc(data_lines, sizeof(double));
 }

I'll have to check on NULL getting placed at the end of the 10003 position.
Thanks, M.

Ok, great!  I was concerned that we were chasing the wrong symptoms....

Perhaps you mean to do:

 for(i= 0; i < (data_items_count+ 1) ; i++)
 {
   table[i]= calloc(data_lines + 1, sizeof(double));    /*  Note the '+1'  */
 }


Kent
::In Response to Kdo::

Yes, great that worked.. but something funny is happening in the inner_count.. when checking to see if  the current element pointing at is NULL or not it will say that the first element is NULL when it acutally is not it has a value of 0, but the check believes this to be NULL. For example with the data below..

a                b                    c                 d
0.000000    400.000000    -81.52149     41.08040  
0.000001    399.999997    -81.52149     41.08040
0.000002    399.999995    -81.52149     41.08040
0.000003    399.999992    -81.52149     41.08040
0.000004    399.999989    -81.52149     41.08040
0.000005    399.999986    -81.52149     41.08040
0.000006    399.999984    -81.52149     41.08040
...               ...                 ...                 ...

The inner_count for the first element would be 0. Know of a way to slove this?
Thanks for all the help, M.

inner_Count will be zero at the first element and increment for each position past inner_Ptr.

inner_Ptr will point to (*outer_Ptr)+inner_Count;   i.e.  element[outer_Count][inner_Count]

How large is your code?  Can you post the relevent portions?


Kent
SOLUTION
Avatar of ankuratvb
ankuratvb
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
::In Response to Kdo::
I do not see the one big advantage with the solution you describe above can you further explain?
Thanks, M.

It's intended as a "debug solution".  While it works just as well in production, the setup code is a little less "obvious" than the traditional 21+1 calls to calloc().


After allocating and building the tables, you can dump the entire data portion with

for (idx = 0; idx < MAX_ROWS * MAX_COLUMNS)
  fprintf (DebugFile, "  %8d  %8x  %f\n", idx, *(Data+idx), *(Data+idx));

What you then look for is odd values in the "corner cases".  In this case, these would be the variables at:

*(Data + (MAX_ROWS * n   +- 2 ))

If your program is over/underindexing an array (index too large, relative 0 vs relative 1 issues, etc) they'll show up as data items in the wrong place.

Using the more common method that you deploy (and I usually do too) overindexing an array can be hidden and hard to find.  Remember that when you malloc() a block of memory, there is a header area in the front and often unused space at the end.  Since you assign a different block for each row, overindexing a row causes a read/write in the unused space at the end.  Sometimes it writes over the next memory header, in which case your program will eventually segfault.  Underindexing usually causes a segfault, too.  But underindexing is less common because your index must go negative for this to happen.

Kent
Thanks! I think I will go with what I think is the cleanest solution suggested above of setting the rows/columns to some ints. I do not know the file size initally, but do have a method that calculates this for the inital allocation. Beyond setting a specific value at the end of the columns, e.g. 999999, I do not see search solution where the count is correct every time. Thanks to Kent for the extended explanations. Add anymore comments if you have them.
Thanks, M.