Thread: 2D Dynamically allocated pointer arrays

  1. #1
    Registered User
    Join Date
    May 2005
    Posts
    207

    2D Dynamically allocated pointer arrays

    Hi!

    I'm trying to create (insert subject)!

    I get an error "missing ';' before type" on the line where I declare my pointer. Can anyone tell me what I'm doing wrong?

    Code:
    
    #include<stdio.h>
    //#include<stdlib.h>
    
    /*
    
    This program demonstrates recursive functions and dynamic, multi-dimensional pointer arrays.
    
    It will calculate the total factorial value for multiple groups of items.
    
    You enter the total number of items, and the number of groups you will have.  Then you enter the
    number of items in each group.  The program error-checks to make sure the number of items
    entered in each groups adds up to be the total number of items.
    
    */
    
    
    //	Prototypes.
    
    unsigned long factr (unsigned long n);
    
    void main ()
    {
    
    //	These are in order of appearance.
    
    	unsigned long num_items = 0;
    	unsigned long num_groups = 0;
    	unsigned long loop = 0;
    	unsigned long total = 0;
    	unsigned long quantity = 0;
    	unsigned long numerator = 0;
    	unsigned long denominator = 1;
    
    	printf ("\n\nHow many items total?\n");
    	scanf ("%u", &num_items);
    
    	printf ("\n\nHow many groups?\n");
    	scanf ("%u", &num_groups);
    
    	if (num_groups > num_items)
    	{
    		printf("\n\nError! Can't have more groups than items!\n\n");
    		exit (1);
    	}
    
    //	Array dimensioning.
    
    	unsigned long *group_total[num_groups][2];
    	group_total = malloc (num_groups*2*sizeof(int));
    
    	if(!group_total)
    	{
    		puts ("\n\nERROR! Not enough Memory!\n\n");
    		exit (1);
    	}
    
    //	Array initialization.
    
    	for (loop = 1; loop <= num_items; loop++)
    	{
    		group_total[loop][1] = 0;
    		group_total[loop][2] = 0;
    	}
    	loop = 0;
    
    //	Array data-entry.
    
    	for (loop = 1; loop <= num_groups; loop++)
    	{
    		printf ("\n\nHow many in group %d\n", loop);
    		scanf ("%u", &quantity);
    
    		group_total[loop][1] = quantity;
    		total = total + quantity;
    	}
    	loop = 0;
    
    //	Error checking and factorial calculations for each group
    
    	if (total = num_groups);
    	{
    		for (loop = 1; loop <= num_groups; loop++)
    		{
    			group_total[loop][2] = factr (quantity);
    		}
    		loop = 0;
    	}
    	else
    	{
    		printf ("\n\nTotal number of items not equal to total items entered!\n\n");
    		free (group_total);
    		exit (1);
    	}
    	total = 0;
    
    //	Final calculations.
    
    	numerator = factr (num_items);
    
    	for (loop = 1; loop <= num_groups; loop++)
    	{
    		denominator = denominator * group_total[loop][2];
    	}
    	total = numerator / denominator;
    	printf ("\n\nTotal factorial for this mess: %u\n\n", total);
    	total = 0;
    	loop = 0;
    	free (group_total);
    }
    
    //	Factorial engine.
    
    unsigned long factr (unsigned long n)
    {
    	unsigned long answer;
    
    	if (n==1) return (1);
    	answer = n==0 ? 1: n * factr (n - 1); // recursive call
    	return (answer);
    }

  2. #2
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    In C90, declare variables before any statements.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  3. #3
    Registered User
    Join Date
    May 2005
    Posts
    207
    I thought that was the problem... :-(

    Can I make my pointer declaration a function by itself and retain the pointer after the function returns?

    mw

  4. #4
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    >Can I make my pointer declaration a function by itself and retain the pointer after the function returns?

    I don't think I fully understand, but sure.

    There are plenty of issues with your code that are handled in the FAQ.
    Code:
    for (loop = 1; loop <= num_items; loop++)
    Arrays are indexed from 0 to N-1, not 1 to N.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  5. #5
    Registered User
    Join Date
    May 2005
    Posts
    207
    What I meant was:

    The program asks the user how many groups there are and then declares a pointer array of that size. I can do this by calling a function that declares a pointer, but then when the function returns the pointer is gone.

    Since I'm already using a recursive function, I want to close all of the extra functions before I start "recursing". I guess I can call a function that sets up my pointer and then calls the recursive function to perform my calculations, but is this going to "flood my stack" or whatever?

    I know about the starting index of an array being zero but aren't pointers indexed starting at one?

    mw

  6. #6
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by Lionmane
    What I meant was:

    The program asks the user how many groups there are and then declares a pointer array of that size. I can do this by calling a function that declares a pointer, but then when the function returns the pointer is gone.
    Perhaps pass a pointer to pointer. Also,
    http://www.eskimo.com/~scs/C-faq/q6.16.html

    Quote Originally Posted by Lionmane
    I know about the starting index of an array being zero but aren't pointers indexed starting at one?
    No. Pointers point.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  7. #7
    Registered User
    Join Date
    May 2005
    Posts
    207
    Ok, I've changed my code:

    Code:
    
    #include<stdio.h>
    #include<stdlib.h>
    
    /*
    
    This program demonstrates recursive functions and dynamic, multi-dimensional pointer arrays.
    
    It will calculate the total factorial value for multiple groups of items.
    
    You enter the total number of items, and the number of groups you will have.  Then you enter the
    number of items in each group.  The program error-checks to make sure the number of items
    entered in each groups adds up to be the total number of items.
    
    */
    
    
    //	Prototypes.
    
    unsigned long factr (unsigned long num_items2, unsigned long num_groups2);
    unsigned long factorial_engine (unsigned long n);
    
    void main ()
    {
    	unsigned long num_items = 0;
    	unsigned long num_groups = 0;
    
    	printf ("\n\nHow many items total?\n");
    	scanf ("%u", &num_items);
    
    	printf ("\n\nHow many groups?\n");
    	scanf ("%u", &num_groups);
    
    	if (num_groups > num_items)
    	{
    		printf("\n\nError! Can't have more groups than items!\n\n");
    		exit (1);
    	}
    	else
    	{
    		factr (num_items, num_groups);
    	}
    }
    
    unsigned long factr (unsigned long num_items2, unsigned long num_groups2)
    {
    
    //	These are in order of appearance.
    
    	unsigned long loop = 0;
    	unsigned long total = 0;
    	unsigned long quantity = 0;
    	unsigned long numerator = 0;
    	unsigned long denominator = 1;
    
    //	Array dimensioning.
    
    	unsigned long *group_total;
    	group_total = malloc (num_groups2*2*sizeof(int));
    
    	if(!group_total)
    	{
    		puts ("\n\nERROR! Not enough Memory!\n\n");
    		exit (1);
    	}
    
    //	Array initialization.
    
    	for (loop = 1; loop <= num_items2; loop++)
    	{
    		group_total[loop][1] = 0;
    		group_total[loop][2] = 0;
    	}
    	loop = 0;
    
    //	Array data-entry.
    
    	for (loop = 1; loop <= num_groups2; loop++)
    	{
    		printf ("\n\nHow many in group %d\n", loop);
    		scanf ("%u", &quantity);
    
    		group_total[loop][1] = quantity;
    		total = total + quantity;
    	}
    	loop = 0;
    
    //	Error checking and factorial calculations for each group
    
    	if (total = num_groups2);
    	{
    		for (loop = 1; loop <= num_groups2; loop++)
    		{
    			group_total[loop][2] = factr (quantity);
    		}
    		loop = 0;
    	}
    	else
    	{
    		printf ("\n\nTotal number of items not equal to total items entered!\n\n");
    		free (group_total);
    		exit (1);
    	}
    	total = 0;
    
    //	Final calculations.
    
    	numerator = factr (num_items2);
    
    	for (loop = 1; loop <= num_groups2; loop++)
    	{
    		denominator = denominator * group_total[loop][2];
    	}
    	total = numerator / denominator;
    	printf ("\n\nTotal factorial for this mess: %u\n\n", total);
    	total = 0;
    	loop = 0;
    	free (group_total);
    }
    
    //	Factorial engine.
    
    unsigned long factorial_engine (unsigned long n)
    {
    	unsigned long answer;
    
    	if (n==1) return (1);
    	answer = n==0 ? 1: n * factr (n - 1); // recursive call
    	return (answer);
    }
    But now when I tried to reference a subscript in group_total it gives me "subscript requires array or pointer type". I think it's telling me I didn't declare my pointer as a 2D array.

    I looked up that link you gave me about multi-dimensional arrays, but I don't understand it.

    mw
    Last edited by Lionmane; 06-09-2005 at 09:40 AM.

  8. #8
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Looking at your code:

    Arrays are indexed from 0 to N-1, not 1 to N.
    You forgot to change your code for this.

    >void main ()
    main return an int:
    Code:
    int main(void)
    > if (total = num_groups2);
    This statement contains two errors:
    1) = means assignment not equality.
    2) The semicolon at the end means everything following the if() gets executed regardless of the outcome of the condition.

    > group_total[loop][1] = 0;
    > group_total[loop][2] = 0;
    If you're not using the second element, then just make this one dimension.
    Code:
    		group_total[loop] = 0;
    Last edited by swoopy; 06-09-2005 at 09:50 AM.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > unsigned long *group_total;
    > group_total = malloc (num_groups2*2*sizeof(int));
    If you're trying to malloc the equivalent of unsigned long group_total[num_groups2][2];
    This is what you do

    Code:
      unsigned long (*group_total)[2];
      group_total = malloc ( num_groups2 * sizeof *group_total );
    Be very careful here, (*group_total)[2] is NOT the same thing as *group_total[2], so don't go leaving out the () for the fun of it, it simply won't work.

    By the way, this only works if your minor dimensions are constant. If they vary, then you need to start with unsigned long **group_total


    Then you need to fix all your loops to index from 0 to N-1
    Code:
    for ( i = 0 ; i < num_groups2 ; i++ ) {
      for ( j = 0 ; j < 2 ; j++ ) {
        group_total[i][j] = 0;
      }
    }
    When you're done, it's simply
    Code:
      free( group_total );
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    May 2005
    Posts
    207
    Thanks guys! I'm still not understanding pointers very well it seems... :-(

    The "C for Dummies" has little to no info about pointers. I have "The Complete Reference: C" by Herbert Schildt but I couldn't figure it out with that either.

    Anyway, I was finally able to compile without any errors but now I'm getting a pop-up window that says "Debug Error!" and gives me some obscure message. The program runs fine until it begins calculating the factorials.

    The error is "Damage: after Normal block (#44) at 0x00431DF0." Any ideas there? Sorry to ask so many questions. I'm trying to learn C pretty much on my own.

    mw

  11. #11
    Registered User
    Join Date
    May 2005
    Location
    Toronto, Canada
    Posts
    257
    If the size of the array varies, you have to dynamically allocate the rows and columns:

    Code:
    //allocate 1D array of pointers, one pointer per row
    
    	a = (int **) calloc(row, sizeof(int *));
    
    //allocate one column element array of ints for each row
    
    	for (i=0; i<row; ++i)
    	{
    		a[i]=(int *) calloc(column, sizeof(int));
    
    //fill the matrix
    		for (i=0; i< row; ++i)
    		{
    			for (j=0; j<column; ++j)
    				a[i][j] = 2;
    		}
    	}
    calloc fills the array with 0's automatically. You can have the user specify what the number of rows and columns is.

    See if that helps.

  12. #12
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Don't cast malloc and calloc in C. (Or any other function that returns a void * for that matter.)


    Quzah.
    Hope is the first step on the road to disappointment.

  13. #13
    Registered User
    Join Date
    May 2005
    Posts
    207
    Quzah, how do you create 2D dynamic arrays (first subscript is dynamic, second is static)? I thought malloc was used to check the memory.

    mw

  14. #14
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    I never said to not use malloc. I said don't typecast it's return.
    Code:
    char **twodee;
    int numofrows = 5, numofcols = 10, x;
    
    twodee = malloc( sizeof( char * ) * numofrows );
    for( x = 0; x < numofrows; x++ )
        twodee[ x ] = malloc( sizeof( char ) * numofcols );
    The 'sizeof( char )' is just to illustrate the point, were this any other type than characters. The reason being, 'sizeof( char )' always evaluates to one, so it's not needed in this example. Were this any other type, it would be needed there (of the appropriate type (int, float, struct foo, etc etc).


    Quzah.
    Hope is the first step on the road to disappointment.

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > The error is "Damage: after Normal block (#44) at 0x00431DF0." Any ideas there?
    Yeah, you modified some memory which wasn't yours.
    Typically, you walked off the end of whatever array you allocated.

    Post some more code.

    > The Complete Reference: C" by Herbert Schildt
    Oh dear - hope you still have the receipt, and time to take it back.
    http://www.plethora.net/~seebs/c/c_tcr.html
    A book so famed in infamy, it's got it's own buzzword
    http://catb.org/~esr/jargon/html/B/bullschildt.html
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 6
    Last Post: 01-16-2007, 09:21 PM
  2. 2D array pointer?
    By willc0de4food in forum C Programming
    Replies: 4
    Last Post: 04-23-2006, 08:16 AM
  3. Checking if memory has been dynamically allocated
    By Xzyx987X in forum C Programming
    Replies: 28
    Last Post: 03-14-2004, 06:53 PM
  4. Destructors in dynamically allocated arrays
    By frenchfry164 in forum C++ Programming
    Replies: 1
    Last Post: 11-28-2003, 11:26 PM
  5. Initialising 2D and 3D arrays
    By fry in forum C++ Programming
    Replies: 5
    Last Post: 08-01-2002, 04:34 AM