Solved

Counting the number of elements of a double **

Posted on 2004-10-20
19
328 Views
Last Modified: 2010-04-15
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.
0
Comment
Question by:unityxx311
  • 7
  • 7
  • 3
  • +2
19 Comments
 
LVL 45

Expert Comment

by:Kdo
ID: 12359311

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++;
0
 

Author Comment

by:unityxx311
ID: 12359519
::In Response to Kdo::

Kent, sorry this only counts the number of elements in the 1st position of  **Table
M.
0
 
LVL 12

Expert Comment

by:stefan73
ID: 12359620
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
0
 
LVL 9

Expert Comment

by:ankuratvb
ID: 12359731
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.
0
 

Author Comment

by:unityxx311
ID: 12359855
::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.
0
 
LVL 9

Expert Comment

by:ankuratvb
ID: 12360014
>>
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.

0
 
LVL 45

Expert Comment

by:Kdo
ID: 12361240


>>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
0
 

Author Comment

by:unityxx311
ID: 12362450
::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.
0
 
LVL 45

Expert Comment

by:Kdo
ID: 12362685

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
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:unityxx311
ID: 12362907
::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.
0
 
LVL 45

Expert Comment

by:Kdo
ID: 12363086

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
0
 

Author Comment

by:unityxx311
ID: 12363403
::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.
0
 
LVL 45

Expert Comment

by:Kdo
ID: 12363669

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
0
 
LVL 9

Assisted Solution

by:ankuratvb
ankuratvb earned 100 total points
ID: 12366394
On most implementations,NULL is defined as 0.

Check in your stdio.h to see what the value of NULL is.
0
 
LVL 7

Assisted Solution

by:aib_42
aib_42 earned 100 total points
ID: 12368091
Thing is, NULL is not a unique value except for using pointers, when it means "invalid pointer". I would never recommend giving a double variable the value NULL, or actually using NULL to indicate the end of the array.

I'd say that the best solution here in terms of complexity and memory optimization is actually storing the length and width of the array in two seperate integer variables.
0
 
LVL 45

Accepted Solution

by:
Kdo earned 300 total points
ID: 12370819
Hi unityxx311,

Debugging indirect pointers (**) can be tricky.  Prior to developing a general purpose set of tools for managing data tables, I learned that debugging them can be much easier if you allocate one large buffer and assign blocks within it.  There are fewer critical items to get corrupted and you can actually dump the entire buffer and examine it with more understanding.

#define MAX_ROWS 21
#define MAX_COLUMNS 10003

double **Table;  /*  Ptr to array[x][]  */
double *Data;     /*  Ptr to array[][y]   buffers  */
double **PtrPtr;
double *DoublePtr;
int idx;

  Table = calloc (MAX_ROWS, sizeof (double *));                        /*  Allocate the pointer array  */
  Data = calloc (MAX_ROWS * MAX_COLUMNS, sizeof (double));  /*  Allocate the data buffer  */
 
  PtrPtr = Table;        /*  Start of pointer buffer  */
  DoublePtr = Data;   /*  Start of data buffer  */
  for (idx = 0; idx < MAX_ROWS; idx++)  /*  set the row pointers  */
  {
    (DoublePtr *)PtrPtr = DoublePtr;   /*  Table[x][] = &Data[ROW]  */
    PtrPtr++;
    DoublePtr += MAX_COLUMNS;
  }


This gives you the same structure that you're already using, with one big advantage.  You can dump the entire data are in one small loop.

If you know the structure and content of your data it's much easier to pick them out this way than to dump individual buffers.  And, array indexing errors are much more likely to overwrite other data this way.  With "discreet" buffers for each row, indexing errors are much more likely to overwrite things that the C libraries would really rather not have corrupted.

Good Luck,
Kent
0
 

Author Comment

by:unityxx311
ID: 12371161
::In Response to Kdo::
I do not see the one big advantage with the solution you describe above can you further explain?
Thanks, M.
0
 
LVL 45

Expert Comment

by:Kdo
ID: 12372267

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
0
 

Author Comment

by:unityxx311
ID: 12373202
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.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now