8 Replies - 882 Views - Last Post: 12 July 2008 - 02:13 AM Rate Topic: -----

#1 Delta_Echo  Icon User is offline

  • D.I.C Addict

Reputation: 5
  • View blog
  • Posts: 722
  • Joined: 24-October 07

Effective Way to use Arrays and Fucntions

Posted 10 July 2008 - 08:20 PM

Can I use 'return' to return an entire array? (All the elements)
Is This A Good Question/Topic? 0
  • +

Replies To: Effective Way to use Arrays and Fucntions

#2 lanec42  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 0
  • View blog
  • Posts: 229
  • Joined: 26-March 08

Re: Effective Way to use Arrays and Fucntions

Posted 10 July 2008 - 10:59 PM

I don't see why not.... I've never done it, though.
Was This Post Helpful? 0
  • +
  • -

#3 skaoth  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 91
  • View blog
  • Posts: 601
  • Joined: 07-November 07

Re: Effective Way to use Arrays and Fucntions

Posted 11 July 2008 - 12:01 AM

In short Yes you can use return to return a complete array. It really depends on
how you go about it. In the example below I will work with integer arrays to keep
things simple. I will go through several examples so bear with me

1) One way to deal with an array is to pass it into a function as either
an array or a pointer (in this case a pointer to an integer). When you do
this you don't actually need a return statement. Any modification to the
array will be seen by the calling function. Here is an example

// Multiply each value of the array by 'multiplier'
void MultiplyBy(int myArray[], int arraySize, int multiplier)
{
	for(int i = 0; i < arraySize; i++)
	{
		myArray[i] = myArray[i] * multiplier;
	}
}

// Multiply each value of the array by 'multiplier'
void MultiplyBy2(int *myArray, int arraySize, int multiplier)
{
	for(int i = 0; i < arraySize; i++)
	{
		*(myArray + i) = *(myArray + i) * multiplier;
	}
}



These 2 functions are identical and it all depends on how comfortable you are with
pointer notation vs. array notation.The one caveat is that myArray has to already
be allocated and initialized before calling these functions for the modifications to be
seen by the caller.

2) Things you can't do. Returning new arrays

// This is invalid
int[] ReturnArray1()
{
	int newArr[] = {9, 8, 7, 6, 5};

	return newArr;
}

// This is also invalid.
int* ReturnArray2()
{
	int newArr[] = {9, 8, 7, 6, 5};

	// Omitting '(int*)' causes a compiler error (at least with VS2k8)
	return (int*) &newArr;
}



Both of these examples are invalid. The first one won't event compile. The second one however, will.
The problem is that the pointer return by ReturnArray2() holds the address for the variable newArr[].
However, when the function completes, that variable no longer exits and the address is invalid.
That means when I make this call

int *myArr = ReturnArray2();



myArr will point to the newArry[] variable that was allocated on the stack in ReturnArray2 which is
no longer valid after the call has returned.

3) Returning arrays by allocating from the heap.
int* ReturnArray3()
{
	int *newArr = new int[5];
	for(int i = 0; i < 5; i++)
	{
		newArr[i] = i * -1 - 1;
	}

	return newArr;
}

// Make sure ptr is empty (NULL) when passed in
int ReturnArray4(int **ptr)
{
	*ptr = new int[5];
	for(int i = 0; i < 5; i++)
	{
		(*ptr)[i] = i + 1;
	}

	return 5;
}

// This does not work as you would think. 
// Make sure ptr is empty (NULL) when passed in
int ReturnArray5(int *ptr)
{
	ptr = new int[5];
	for(int i = 0; i < 5; i++)
	{
		ptr[i] = i + 1;
	}

	return 5;
}



ReturnArray3() should fairly self explainatory. newArr will be the new array that will be returned. This
works because the memory used to store this array is on the heap and not on the stack. The only problem with
this one is that the user doesn't know how many elements were allocated. They also have to remember to delete
the array when done by calling delete [] .

Another common way to return a pointer and notify the user of the size is by returning the size of the newly
created array as the return value, and the pointer passed in as the new array to be allocated. It is used
like this

int* newArr = NULL;

// Note we're passing in a reference to an int pointer)
int size = ReturnArray4(&newArr);

// NewArr now contains the new array
delete [] newArr;

// This does not work. newArr2 is still NULL after the call
// to ReturnArray5()
int* newArr2 = NULL;
size = ReturnArray5(newArr2);



The prototype may seem odd for ReturnArray4() but it is there because 'ptr' that gets passed in has pass by value
semantics. Contrast this with how ReturnArray5() is called (we're not passing in a reference to an int pointer).
If your still unclear what is going on here you'll need to brush up on pointers and references. Remember when
returning any array from a function it should be clear as to who has to perform memory cleanup. In my examples
above any allocated array had to be deleted by the user though this need not be the case.

Hope this helps
Was This Post Helpful? 0
  • +
  • -

#4 Delta_Echo  Icon User is offline

  • D.I.C Addict

Reputation: 5
  • View blog
  • Posts: 722
  • Joined: 24-October 07

Re: Effective Way to use Arrays and Fucntions

Posted 11 July 2008 - 01:28 AM

Thanks! I will try it out.
Was This Post Helpful? 0
  • +
  • -

#5 Emilius  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 01-July 08

Re: Effective Way to use Arrays and Fucntions

Posted 11 July 2008 - 01:22 PM

Why don't you use the array as an argument for the function? Something like this:

int array[10];

void init_arr(int arr[], int n)
{
	for (int i = 0; i < n; i++)
	{
		arr[i] = i;
	};
}

void show_arr(int arr[], int n)
{
	for (int i = 0; i < n; i++)
		cout << arr[i] << ' ';
	cout << endl;
}



...or you may use std::vector, instead of using array, i suppose...
Was This Post Helpful? 0
  • +
  • -

#6 Delta_Echo  Icon User is offline

  • D.I.C Addict

Reputation: 5
  • View blog
  • Posts: 722
  • Joined: 24-October 07

Re: Effective Way to use Arrays and Fucntions

Posted 11 July 2008 - 09:53 PM

Skaoth,

I tried to apply your method. This is my code:
#include <iostream>

using namespace std;

void func(int* myPoint[]);

int main(){

    int myArr[4] = {0,0,0};
    int* myPoint[4] = &myArr[];

    for(int a = 0;a > 2;a++){
        cout << myArr[a];
    }
    cin.get();
    func(*myPoint[]);
    for ( int c=0;c > 2;c++){
        cout << myArr[c];
    }
    cin.get();
    return 1;

}
void func(int* myPoint[]){
    for (int b = 0;b > 2;b++){
        myArr[b] = 3;
    }
}



It compiles properly, however when I execute the program i get nothing.
By that i mean, nothing happens. Bash goes to the program then returns to bash.
Was This Post Helpful? 0
  • +
  • -

#7 skaoth  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 91
  • View blog
  • Posts: 601
  • Joined: 07-November 07

Re: Effective Way to use Arrays and Fucntions

Posted 11 July 2008 - 10:55 PM

There are a couple of issues with your sample

1) Make sure that your loops will execute
This will never execute for(int a = 0;a > 2;a++)
I'm sure you meant to say for(int a = 0; a < 4; a++)

2) I'm not sure what you are trying to do here
void func(int* myPoint[]) but what you are saying is that the
parameter is an array of integer pointer. What you want is either
void func(int* myArr) or void func(int myArr[]). They are logically equivalent

3) You don't need to declare your array like this
int myArr[4] = {0,0,0}; (your missing 1 initializer by the way)
Indexing starts at 0 for arrays in C/C++. If you declare an array and initialize it right
away like you did, you can actually leave out the size, the compiler will be able to infer
the size from the number of items you initialize the array with.

4) Make sure you modify the correct array
 void func(int* myPoint[]){  
	 for (int b = 0;b > 2;b++){  
		 myArr[b] = 3;  
	 }  
 }  


I'm surprised this compiles. Your trying to modify myPoint[] NOT myArr

Here is a fixed up version
 void func(int* myPoint){  
	 for (int b = 0;b < 3;b++){  
		 myPoint[b] = 3;  
	 }  
 }  

int main(void)
{
	 int myArr[3] = {0,0,0};  
	
	 // This is not needed
	 //int* myPoint[4] = &myArr[];  
	
	 for(int a = 0;a < 3;a++){  
		 cout << myArr[a];   
	 }  
 
	 func(myArr);  
	 for ( int c=0;c < 3;c++){  
		 cout << myArr[c];  
	 }  
}


This post has been edited by skaoth: 11 July 2008 - 10:56 PM

Was This Post Helpful? 1
  • +
  • -

#8 Delta_Echo  Icon User is offline

  • D.I.C Addict

Reputation: 5
  • View blog
  • Posts: 722
  • Joined: 24-October 07

Re: Effective Way to use Arrays and Fucntions

Posted 11 July 2008 - 11:17 PM

Ah, i thought the condition in a for loop was the condition for the loop to break, so that when the condition was met, the loop would end.
Thanks for all your help! It REALLY help me out.
:):):):):):)
Was This Post Helpful? 0
  • +
  • -

#9 Delta_Echo  Icon User is offline

  • D.I.C Addict

Reputation: 5
  • View blog
  • Posts: 722
  • Joined: 24-October 07

Re: Effective Way to use Arrays and Fucntions

Posted 12 July 2008 - 02:13 AM

Having some problems :(
I made a program to create a cipher (i intend to use this later in an encryption program).
I'm getting errors I have never seen before, probably because I have never used classes.

main.cpp:
#include <cstdlib>
#include <stdio.h>
#include <time.h>
#include <iostream>
#include <fstream>

#include "cipher.h"

using namespace std;

cipher Ciph1;

int main(){
     Ciph1.seed_gen(Ciph1.MySeed);
     Ciph1.ciph_gen(Ciph1.MyCipher,Ciph1.MySeed);
     if (ciph_any(Ciph1.MyCipher) != true){
         cout << "Fatal Error: In: main(): In: ciph_any(): Ciph1: MyCipher: Values out of range! Terminating...\n";
         return 0;
     }
     Ciph1.ciph_pri(Ciph1.MyCipher);
     cin.get();
}


cipher.h:
/**
 Fucntions:
 **************************************************************************************************
 *seed_gen(<Seed_Array>);                | Generates the seeds to be used by the cipher generater.*
 *ciph_gen(<Cipher_Array>,<Seed_Array>); | Generates the cipher using the seed array.             *
 *ciph_any(<Cipher_Array>);              | Checks the array for values exceding 9 or preceding 0  *
 *                                       | if an error is found the main() decides how to handle  *
 *                                       | it, based on user arguments to main().                 *
 *ciph_pri(<Cipher_Array>);              | Prints the array.                                      *
 **************************************************************************************************
 **/

#include <stdio.h>
#include <cstdlib>
#include <time.h>
#include <iostream>

using namespace std;


#define RAND_MAX = 9
#define RAND_MIN = 0

class cipher{
    public:

    // Public Variables
    int MyCipher[512][10];
    int MySeed[512];

    // Public Functions

     // ***Seed Generator***
     void seed_gen(int* MyPoint){
         for (int a = 0;a != 512;a++){
             srand (time(NULL));
             MyPoint[a] = rand();
         }
     }

     // ***Cipher Generator***
     // ciph_gen(<Cipher_Array>,<Seed_Array>);
     void ciph_gen(int* MyPoint,int* MySec){
         // Stage 1: Set each first element of
         // each line to the seed value of that
         // line
         for (int a = 1;a != 512;a++){
             MyPoint[a][1] = MySec[a];
         }
         int con;
         //Stage 2
         for (int b = 1;b != 512;b++){
             con = MyPoint[b][1];
             for (int c = 1;c != 10;c++){
                 if (con == 9){
                     c++;
                     con = 0;
                     MyPoint[b][c] = con;
                 }
                 else {
                     MyPoint[b][c] = con++;
                 }
             }
         }
     }

     // ***Cipher Anylizer***
     // ciph_any(<cipher_array>);
     bool cipher_any(int* MyPoint){
         for (int a = 1;a != 512;a++){
             for(int b = 1;b != 10;a++){
                 if (MyPoint[a][b] > 9 || MyPoint[a][b] < 0){
                     return false; // Integrity = VOID
                 }
             }
         }
     }

     // ***Print Cipher***
     // ciph_pri(<Cipher_Array>)
     void ciph_pri(int* MyPoint){
         for (int a = 1;a != 512;a++){
             for (int b = 1;b != 10;b++){
                 cout << MyPoint[a][b];
             }
             cout << "\n";
         }
     cin.get();
     }

}



Compiler Output:
In file included from main.cpp:7:
cipher.h:21:1: warning: "RAND_MAX" redefined
In file included from /usr/lib/gcc/i386-redhat-linux/4.3.0/../../../../include/c++/4.3.0/cstdlib:73,
                 from main.cpp:1:
/usr/include/stdlib.h:129:1: warning: this is the location of the previous definition
In file included from main.cpp:7:
cipher.h: In member function ‘void cipher::ciph_gen(int*, int*)’:
cipher.h:48: error: invalid types ‘int[int]’ for array subscript
cipher.h:53: error: invalid types ‘int[int]’ for array subscript
cipher.h:58: error: invalid types ‘int[int]’ for array subscript
cipher.h:61: error: invalid types ‘int[int]’ for array subscript
cipher.h: In member function ‘bool cipher::cipher_any(int*)’:
cipher.h:72: error: invalid types ‘int[int]’ for array subscript
cipher.h:72: error: invalid types ‘int[int]’ for array subscript
cipher.h: In member function ‘void cipher::ciph_pri(int*)’:
cipher.h:84: error: invalid types ‘int[int]’ for array subscript
main.cpp: At global scope:
main.cpp:9: error: expected unqualified-id before ‘using’
main.cpp: In function ‘int main()’:
main.cpp:15: error: no matching function for call to ‘cipher::ciph_gen(int [512][10], int [512])’
cipher.h:43: note: candidates are: void cipher::ciph_gen(int*, int*)
main.cpp:16: error: ‘ciph_any’ was not declared in this scope
main.cpp:20: error: no matching function for call to ‘cipher::ciph_pri(int [512][10])’
cipher.h:81: note: candidates are: void cipher::ciph_pri(int*)



Any help would be appreciated.
Ty
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1