Help Returning a new Dynamic Array from a Function

This is a discussion on Help Returning a new Dynamic Array from a Function within the C++ Programming forums, part of the General Programming Boards category; Hi all. This is actually something related to a WINAPI project, but is a basic C++ problem that has caused ...

  1. #1
    Registered User KeithS's Avatar
    Join Date
    Jul 2009
    Location
    Colombia
    Posts
    21

    Help Returning a new Dynamic Array from a Function

    Hi all.

    This is actually something related to a WINAPI project, but is a basic C++ problem that has caused a glitch. First the code, then the description of the problem...

    Code:
    //Passing arrays of a structure to a function....
    
    #include <iostream>
    using namespace std;
    
    // Structures ________________________________________________________________//
    struct My_Struct
    {
    	int x;
    	int y;
    	int z;
    };
    
    // Prototypes ________________________________________________________________//
    void initializer(My_Struct *num_arr, int count);
    void ref_adder(My_Struct *structure, int count);
    // My_Struct make_array(int count); // Not working.
    
    // Main function _____________________________________________________________//
    int main()
    {
    	My_Struct * Test_Struct;
    	int marker = 0;
    	while (marker == 0)
    	{
    		cout << "Enter an index number (greater than 0) for the array size:_  ";
    		cin >> marker;
    		cout << endl;
    		if (marker == 0)
    			cout << "Please enter a number greater than 0" << endl << endl;
    	}
    	system("cls");
    	cout << "The index count you set was " << marker << 
    		". Now here is your dynamic array." << endl << endl;
    
    	// Make the dynamic array. I want a function to do this part.
    	Test_Struct = new (nothrow) My_Struct[marker]; 
    	
    	// *Test_Struct = make_array(marker); // Not working very well, at all.
    
    	initializer(Test_Struct, marker);
    	ref_adder(Test_Struct, marker);
    
    	int i;
    	for (i = 0; i < marker; i++)
    	{
    		cout << Test_Struct[i].x << " + " << Test_Struct[i].y << " = " << 
    			Test_Struct[i].z << endl;
    	}
    	cout << endl;
    	system ("pause");
    
    	delete [] Test_Struct;
    	return 0;
    }
    
    // Custom functions ___________________________________________________________//
    void initializer(My_Struct *num_arr, int count)
    {
    	int i;
    	for (i = 0; i < count; i++)
    	{
    		num_arr[i].x = (i + 1) * 10;
    		num_arr[i].y = (i + 2) * 10;
    	}
    }
    
    void ref_adder(My_Struct *num_arr, int count)
    {
    	int i;
    	for (i = 0; i < count; i++)
    	{
    		num_arr[i].z = num_arr[i].x + num_arr[i].y;
    	}
    }
    
    /*
    My_Struct make_array(int count)
    {
    	return * new (nothrow) My_Struct[count];
    }
    Not working*/
    What I want to do is make the dynamic array inside a function. The code as above (except for the commented out lines) works okay, but is not quite IT. Here's what I am after. Up where the...

    Code:
    Test_Struct = new (nothrow) My_Struct[marker];
    ...line appears in the main() function, I want to put a...

    Code:
    *Test_Struct = make_array(marker);
    ...line, instead, that returns a dynamic array of struct My_Struct from a function. Something like this one...

    Code:
    My_Struct make_array(int count)
    {
    	return * new (nothrow) My_Struct[count];
    }
    I have tried several ways to accomplish this, but none go all the way in doing the job. This one at least compiles, but crashes upon running, when reaching the part that creates the dynamic array (the My_Struct function). I am not doing something right, or what I am trying to do is not possible (though I am pretty sure it must be).

    Any help with this? Please?

    My sincere thanks in advance for any push in the right direction.

  2. #2
    a_capitalist_story
    Join Date
    Dec 2007
    Posts
    2,648
    Code:
    return * new (nothrow) My_Struct[count];
    What's the * doing in there? Oh it's because you told the compiler not that you're returning a pointer to a struct, but that you're returning a struct, and you wanted to fix the compiler error without thinking about what you're doing.

  3. #3
    Registered User KeithS's Avatar
    Join Date
    Jul 2009
    Location
    Colombia
    Posts
    21
    Quote Originally Posted by rags_to_riches View Post
    Code:
    return * new (nothrow) My_Struct[count];
    What's the * doing in there? Oh it's because you told the compiler not that you're returning a pointer to a struct, but that you're returning a struct, and you wanted to fix the compiler error without thinking about what you're doing.
    ????

    I am sorry, did not understand that...

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Code:
    My_Struct make_array(int count)
    Return a copy of one My_Struct

    Code:
    My_Struct* make_array(int count)
    Return a pointer to My_Struct (or to the first item in an array of My_Structs).

    Also

    Code:
    Test_Struct = new (nothrow) My_Struct[marker];  //this works
    	
    *Test_Struct = make_array(marker); // this doesn't
    Notice any difference?
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  5. #5
    Registered User KeithS's Avatar
    Join Date
    Jul 2009
    Location
    Colombia
    Posts
    21
    Yeah, okay. Solved

    I went back to basics with this one and did this ejercicio with a bog-standard int (*) pointer. Thanks for those comments. It is working now, so doing it with My_Struct is just a small step from here.

    Code:
    #include <iostream>
    #include <conio.h>
    using namespace std;
    
    //-------- Function Prototypes ------------------
    void dyn_array_maker(int *);        // , int index); not needed
    void dyn_array_destroyer(int *);
    
    int marker;
    	
    /* It seems this "marker" can be modified in main(), but it MUST be declared globally for this to work.*/
    
    //-------- Main Function ------------------------
    int main()
    {
    	//int marker;      // No. It crashes the program if it is declared here.
    
    	int * number;     // The pointer for the dynamic array.
    	
    	cin >> marker;    // Set the size of marker for the array.
    	cout << endl;
    
    	dyn_array_maker(number);   // Make the dynamic array in a funtion.    // , marker); not needed
    
    	int i;
    	for(i = 0; i < marker; i++)
    	{
    		*(number+i) = (i + 1) * 2;	// Assign some arbitrary values to the new array.
    		cout << *(number+i) << endl;
    	}
    	
    	while (!_kbhit())
    	
    	dyn_array_destroyer(number); // delete the dynamic array in a function.  
    	return 0;
    }
    
    //------ Custom Functions -----------------
    
    void dyn_array_maker(int *dyn_array)                     // , int index); not needed
    {
    	dyn_array = new /*(nothrow)*/ int[marker];       // int [index]; not needed
    }
    
    void dyn_array_destroyer(int *dyn_array)  
    {
    	delete [] dyn_array;    
    }

    The trick seemed to be in declaring the index marker for the dynamic array OUTSIDE of main(); ie, globally. It's value can be changed in the program at runtime with no ill effects, but if it is declared locally in main() --- CRASH!!!

    I cannot explain to myself why this is. Even though the problem is solved, I would like to have an idea. Could anyone please provide a description of these machinations, however short? I am guessing it is because "marker" should be a constant, and declaring it globally causes the compiler to "believe" this. This makes the nothrow part a bit redundant too, I imagine, correct? It works perfectly well with or without it, but, is this safe?

    Thanks again, much appreciated.

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I very much doubt that it works (getting it to compile doesn't mean it works!). Here's what happens when I run it:

    13


    Process returned -1073741819 (0xC0000005) execution time : 16.641 s
    Press any key to continue.
    Firstly, you didn't seem to get the hint about the wrong return type. Did you try:

    Code:
    My_Struct* make_array(int count)
    {
    	return new My_Struct[count];
    }
    
    ...
    Test_Struct = make_array(marker);
    In current code:
    Code:
    void dyn_array_maker(int *dyn_array)                     // , int index); not needed
    {
    	dyn_array = new /*(nothrow)*/ int[marker];       // int [index]; not needed
    }
    This modifies only the local copy of the pointer. In main the pointer (number) remains uninitialized.

    You'll need to pass a pointer or reference to that pointer.

    All in all, you need to make sure that you understand the difference between a pointer and a pointee and things like that.
    Last edited by anon; 09-29-2009 at 01:19 PM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    Registered User KeithS's Avatar
    Join Date
    Jul 2009
    Location
    Colombia
    Posts
    21
    Yes, that works a treat. Thank you for your help!

    Point (appropriately) taken about revising the pointer conventions. I am reasonably clear on passing arrays by reference and value to functions, and such, but this was a little different, or at least appeared to be ...

    Just to back tread a tadge, the previous version really did work (I do mean it ran after compiling) and even allowed resizing of the array runtime. That said, the code did not look completely right even to me, which is why I asked if it was safe in the first place. I use VC++ 2008 Express, I am wondering if it is a sort of compiler "idiot tolerance" issue? Whatever the case, fragile code is fragile code. Your way is much better, as "marker" can be safely declared inside the main(), as I originally intended, and not masquerade outside as something it isn't.

    Any way. Here's the latest snippet in total...

    Code:
    #include <iostream>
    #include <conio.h>
    using namespace std;
    
    // --------- Structures --------------
    struct My_Struct
    {
    	int g;
    	int h;
    };
    
    //---------- Prototypes --------------
    My_Struct *array_maker(int count);
    void assigner(My_Struct *Struct, int count);
    void array_destroyer(My_Struct *Struct);
    
    // --------- main function -----------
    int main()
    {
    	char ch;
    	int marker;
    	int i;
    	My_Struct *Test_Struct;
    	
    	while(ch != 'q')
    	{
    		cout << "Input a size for the dynamic array: ";
    		cin >> marker;
    		cout << endl;
    		Test_Struct = array_maker(marker);
    		assigner(Test_Struct, marker);
    		
    		for(i = 0; i < marker; i++)
    			cout << "g is:_ " << Test_Struct[i].g << " and h is:_ " << Test_Struct[i].h << endl;
    
    		cout << "\nPress 'q' to quit or any other ket to make a new array.\n" << endl;
    		array_destroyer(Test_Struct);
    		
    		ch = _getch();
    		system ("cls");
    		
    	}
    	return 0;
    }
    
    //------ Custom functions -------------
    
    My_Struct *array_maker(int count)
    {
    	return new My_Struct[count];
    }
    
    void assigner(My_Struct *Struct, int count)
    {
    	int i;
    	for(i = 0; i < index; i++)
    	{
    		Struct[i].g = i + 1;
    		Struct[i].h = (i + 1) * 2;
    	}
    }
    
    void array_destroyer(My_Struct *Struct)
    {
    	delete [] Struct;
    }

    Thanks again for your help and patience!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 05-13-2011, 08:28 AM
  2. Replies: 2
    Last Post: 07-11-2008, 07:39 AM
  3. c++ linking problem for x11
    By kron in forum Linux Programming
    Replies: 1
    Last Post: 11-19-2004, 09:18 AM
  4. Help with an Array
    By omalleys in forum C Programming
    Replies: 1
    Last Post: 07-01-2002, 08:31 AM
  5. qt help
    By Unregistered in forum Linux Programming
    Replies: 1
    Last Post: 04-20-2002, 09:51 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21