Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
Solved

# Counting the number of elements of a double **

Posted on 2004-10-20
Medium Priority
377 Views
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
Question by:unityxx311
[X]
###### Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

• Help others & share knowledge
• Earn cash & points
• 7
• 7
• 3
• +2

LVL 46

Expert Comment

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

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

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

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

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

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 46

Expert Comment

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

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 46

Expert Comment

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

Author Comment

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 46

Expert Comment

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

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 46

Expert Comment

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

ankuratvb earned 400 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

aib_42 earned 400 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 46

Accepted Solution

Kent Olsen earned 1200 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

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 46

Expert Comment

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

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

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were smallâ€¦
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see soâ€¦
The goal of this video is to provide viewers with basic examples to understand opening and writing to files in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.
###### Suggested Courses
Course of the Month9 days, 22 hours left to enroll