473,583 Members | 2,875 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

need help returning or passing by reference a 2-d array

4 New Member
Hello all,

I am fairly new to c, coming from a Java background. I am working on a mathematical program and I have a function that needs to return a 2-d array. After some web searching, I have determined that in c, it is better to just pass the array in the function. Since arrays are passed by reference, I expected for the updated array to be passed back with the correct values filled in, however, only the first row of the array is returned (with the rest of the rows filled with zeroes) upon returning from the function. I know that the values are being properly filled in since I verify that before returning from the function (that fills the array). Sorry for the long post, just trying to explain the situation. Below is a simplified version of the code that I'm using

Expand|Select|Wrap|Line Numbers
  1.  
  2. void createVectorSeries(float input[], float output[][COLS])  {
  3.   /* populate the output array */
  4. }
  5.  
  6. void main() {
  7.   float output[ROWS][COLS] ;
  8.   /* fill input array */
  9.   createVectorSeries(input, output) ;
  10.  
Sample output:
Expand|Select|Wrap|Line Numbers
  1. 0.3 0.4 0.5 0.6
  2. 0      0    0   0
  3. 0     0    0    0
  4.  
any help is appreciated
Feb 11 '07 #1
11 2038
Ganon11
3,652 Recognized Expert Specialist
It might help to see more of the code, especially the function. You may have to pass the array using pointers or double-pointers.
Feb 11 '07 #2
jza
4 New Member
here are the 2 principle functions. The rest of the code just reads data from a file, creates an array from the data and breaks it down and passes it (as signal[] ) to getCorrelationI ntegral. Let me know if that's enough, or too much information.

Expand|Select|Wrap|Line Numbers
  1.  
  2.  
  3. /*
  4.  * Get the vector series of a signal, given the signal,
  5.  * the interval time (tau) and the embedding dimension (m)
  6.  */
  7. void getVectorSeries(float signal[], int tau, int m, float vectorSeries[][COLS])  {
  8.  
  9. //      int v ; for(v = 0 ; v < 10 ; v++) printf("%f \t", signal[v])    ;
  10. //      debug("at getVectorSeries . . . ") ;
  11.  
  12.         int a, b;
  13.         int i = 0, j = 0 ;
  14.         for(a = 0 ; a < (SZ_WINDOW - m) ; a += tau) {
  15.                 for(b = a ; b < (m+a) ; b++) {
  16. //                      segment[j++] = signal[b] ;
  17.                         vectorSeries[i][j++] = signal[b] ;
  18.                 }
  19.                 j = 0 ;
  20.                 i++ ;
  21.         }
  22. // //  make sure vector series is correct (it is )
  23. //      int v,vv ;
  24. //      printf("\n");
  25. //      for(v = 0 ; v < 10 ; v++) {
  26. //              for(vv = 0 ; vv < m ; vv++) {
  27. //                      printf("%f \t", vectorSeries[v][vv]);
  28. //              }
  29. //              printf("\n") ;
  30. //      }
  31. }
  32.  
  33.  
  34. /**
  35.  * Get the correlation integral of a signal
  36.  */
  37. void getCorrelationIntegral(float signal[], float* corrIntegral, int currentElectrode) {
  38.  
  39.         int vsNumRows=  (int)((int)(SZ_WINDOW - m) / tau) + 1 ;
  40.         float vectorSeries[ vsNumRows] [ m ] ;
  41. //      printf("##%i", vsNumRows) ;
  42.         getVectorSeries(signal, tau, m, vectorSeries) ;
  43.  
  44.         // //  make sure vector series is correct
  45.         // -> for some reason, only the first row is returned (but it is correct in the getVectorSeries function, hmmm
  46.         int v,vv ;
  47.         printf("\n");
  48.         for(v = 0 ; v < 10 ; v++) {
  49.                 for(vv = 0 ; vv < m ; vv++) {
  50.                         printf("%f \t", vectorSeries[v][vv]);
  51.                 }
  52.                 printf("\n") ;
  53.         }
  54.  
  55.         float ratio = 0.01 ;
  56.         float dist[m] ;
  57.         int b = 0 ;
  58.         float distance[ vsNumRows * (vsNumRows -1) ] ; // random distance here
  59.         int t, s, col ;
  60.         for(t = 0 ; t < vsNumRows ; t++) {
  61.                 for(s = (t+1) ; s < vsNumRows; s++) {
  62.                         float norm[m] ;
  63.                         float sumOfDims = 0.0 ;
  64.                         for(col = 0 ; col < m ; col++) {
  65.                                 printf("%f-%f=%f\n",   vectorSeries[t][col], vectorSeries[s][col],   vectorSeries[t][col] - vectorSeries[s][col]) ;
  66.                                 norm[col] = powf( fabsf( vectorSeries[t][col] - vectorSeries[s][col]), 2.0 ) ;
  67.                                 debugFloatArray(norm, m) ;
  68.                                 sumOfDims += norm[col] ;
  69.                         }
  70.                         distance[b++] = sqrt(sumOfDims) ;
  71. //                      debugFloatArray(distance,  vsNumRows * (vsNumRows -1) ) ;
  72.                         if(distance[b] < RATIO) {
  73.                                 H_eachElectrode++ ;
  74.                         }
  75.               }
  76.                 g_distanceSize =  vsNumRows * (vsNumRows -1) ;
  77.                 H_electrode[g_windowNo][ (currentElectrode - 1) ] = H_eachElectrode ;
  78.                 divideElectrodesArrayByDistanceSize() ;
  79.         }
  80. }
  81.  
thanks
Feb 11 '07 #3
AdrianH
1,251 Recognized Expert Top Contributor
Hello all,

I am fairly new to c, coming from a Java background. I am working on a mathematical program and I have a function that needs to return a 2-d array. After some web searching, I have determined that in c, it is better to just pass the array in the function. Since arrays are passed by reference, I expected for the updated array to be passed back with the correct values filled in, however, only the first row of the array is returned (with the rest of the rows filled with zeroes) upon returning from the function. I know that the values are being properly filled in since I verify that before returning from the function (that fills the array). Sorry for the long post, just trying to explain the situation. Below is a simplified version of the code that I'm using

Expand|Select|Wrap|Line Numbers
  1.  
  2. void createVectorSeries(float input[], float output[][COLS])  {
  3.   /* populate the output array */
  4. }
  5.  
  6. void main() {
  7.   float output[ROWS][COLS] ;
  8.   /* fill input array */
  9.   createVectorSeries(input, output) ;
  10.  
Sample output:
Expand|Select|Wrap|Line Numbers
  1. 0.3 0.4 0.5 0.6
  2. 0      0    0   0
  3. 0     0    0    0
  4.  
any help is appreciated

Yeah, the problem is that you are passing a 2D array. You can't do that. It has to do with how arrays are handled when passed. If you declare a multi-dimensional array like you did, it gets allocated as one big chunk. However, if you pass that array, it will not be treated as one big chunk, but as a multi-pointer (in the case of a 2D array, it becomes a double pointer, 3D - triple pointer).

What this means for your 2D example is that you must create a 1D array of pointers, and then allocate the pointers in each element to another array of floats. This will then be properly recognised by functions that are passed it.

I've got to run, but I can explain why this occurs later. Unless someone else would like to do the honours?


Adrian
Feb 12 '07 #4
RRick
463 Recognized Expert Contributor
There's nothing wrong with passing a 2-D array to a subroutine. The definition in the code looks good. I suspect the problem lies in the code itself within. The quickest way to find out if the code is bad is to add a print statement for each row being calculated.

If you want the number of columns to vary in your program, then you will have to give up on the 2-D array and implement an array of pointers. You pass m to getVectorSeries , but m must always equal COLS.

Also, I would use doubles not floats for you calculations. Floats are only used in cases of emergencies where the arrays are too massive.
Feb 12 '07 #5
AdrianH
1,251 Recognized Expert Top Contributor
There's nothing wrong with passing a 2-D array to a subroutine. The definition in the code looks good. I suspect the problem lies in the code itself within. The quickest way to find out if the code is bad is to add a print statement for each row being calculated.

If you want the number of columns to vary in your program, then you will have to give up on the 2-D array and implement an array of pointers. You pass m to getVectorSeries , but m must always equal COLS.

Also, I would use doubles not floats for you calculations. Floats are only used in cases of emergencies where the arrays are too massive.
When C++ came out with those arrays, I wasn't able to get them to work. I guess I understand why now.

RRick is right, the problem lies in the populating of the array inside of the function. That is where your error lies. The decision to use floats or doubles is yours, but you should know that though it is half the size of a double and possibly slightly faster, you will have less precision and thus are subject to more severe rounding errors. See Wikipedia’s IEEE 754 for more info.

Sorry for the misinformation in the last response. Hope this helps.


Adrian
Feb 12 '07 #6
jza
4 New Member
There's nothing wrong with passing a 2-D array to a subroutine. The definition in the code looks good. I suspect the problem lies in the code itself within. The quickest way to find out if the code is bad is to add a print statement for each row being calculated.
When C++ came out with those arrays, I wasn't able to get them to work. I guess I understand why now.

RRick is right, the problem lies in the populating of the array inside of the function. That is where your error lies.

Adrian
If you'll notice in the code, I print out the array in the getVectorSeries (where it is populated) and this produces the correct output. I then print it after returning from getVectorSeries and only the first row is populated. This leads me to believe that the problem lies in how I'm passing the array. I really don't know what else to look for in the code itself. Do you agree with me?
BTW, thanks for the info on floats, I'll switch to double
Feb 12 '07 #7
RRick
463 Recognized Expert Contributor
You have some commented out code that does print the array, but it is hard coded for rows = 10. Earlier in your post, you print out an array with rows=3. Something is not matching here and that is probably the problem. Take a look and see what the sizes of the array is in both routines.

You need to check this because I can't make much sense of the code in getCorrelationI ntegral. If the code in getCorrelationI ntegral compiles, then m and tau are global variables. This doesn't seem right.
Feb 12 '07 #8
AdrianH
1,251 Recognized Expert Top Contributor
If you'll notice in the code, I print out the array in the getVectorSeries (where it is populated) and this produces the correct output. I then print it after returning from getVectorSeries and only the first row is populated. This leads me to believe that the problem lies in how I'm passing the array. I really don't know what else to look for in the code itself. Do you agree with me?
BTW, thanks for the info on floats, I'll switch to double
I'm posting simple sample to show that a 2D array can be passed, modified and have it's modification seen in the caller in a row that is not 0. I'm going to take a closer look at your code in a minute.

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2.  
  3. int const COLS=10;
  4. int const ROWS=5;
  5.  
  6. void f(int array[][COLS], int row, int col, int value)
  7. {
  8.     array[row][col]=value;
  9. }
  10.  
  11. int main()
  12. {
  13.     int array[ROWS][COLS] = {};
  14.     f(array, 2, 3, 4);
  15.     printf("array[2][3] = %d\n", array[2][3]);
  16.     return 0;
  17. }
  18.  

Adrian
Feb 12 '07 #9
AdrianH
1,251 Recognized Expert Top Contributor
Ahh, I think I see your problem. Here is the prototype:
Expand|Select|Wrap|Line Numbers
  1. void getVectorSeries(float signal[], int tau, int m, float vectorSeries[][COLS]);
  2.  
Here is the code leading up to the call to getVectorSeries ():
Expand|Select|Wrap|Line Numbers
  1. /**
  2.  * Get the correlation integral of a signal
  3.  */
  4. void getCorrelationIntegral(float signal[], float* corrIntegral, int currentElectrode) {
  5.  
  6.         int vsNumRows=  (int)((int)(SZ_WINDOW - m) / tau) + 1 ;
  7.         float vectorSeries[ vsNumRows] [ m ] ;
  8. //      printf("##%i", vsNumRows) ;
  9.         getVectorSeries(signal, tau, m, vectorSeries) ;
  10.  
Assuming that your compiler is not catching this, the problem is being caused by you allocating an array based on m columns. m is not defined here but I bet it is not 30.

In order to pass a multi-dimensional array, the caller and callee must agree as to what the sizes of all of the dimensions are except for the very first which can be variable. Otherwise, there is no way of properly calculating the location of an element in the array, which is physically just a block of memory with no information attached to it describing it.

This being the case, you can actually tell the compiler how many cols there are in one of two ways, by passing a variable or by creating a template function.

Variable Passing Method:
Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2.  
  3. #define COLS 10
  4. #define ROWS 5
  5.  
  6. void f(int cols, int array[][cols], int row, int col, int value)
  7. {
  8.     array[row][col]=value;
  9. }
  10.  
  11. int main()
  12. {
  13.     int array[ROWS][COLS] = {};
  14.     f(COLS, array, 2, 3, 4);
  15.     printf("array[2][3] = %d\n", array[2][3]);
  16.     return 0;
  17. }
  18.  
Advantages over Templates
  • Object size remains constant no matter how many different arrays with different number of columns you have.
  • Function source can be hidden in the source file and not exposed to who ever wants to look at it. This is a design issue, making the code a black box so people don't start to rely on internal private matters that may change in the future.

Disadvantages over Templates
  • The number of columns must come before the array in the parameter list.
  • Because there is a separation between the array and the number of columns that it should have, there is a chance that you may inadvertently pass an array that has n columns but state that it has m columns (sort of like i'm thinking in your case).
  • It is slightly slower as optimisations based on the number of columns cannot be done.
    This is only really noticeable when the function is called thousands (if not more) of times or unless you are running this on a very slow system.
  • I'm not sure if this is part of the ANSII C++ standard. It might be just a gnu extension.
Template Method
Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2.  
  3. #define COLS 10
  4. #define ROWS 5
  5.  
  6. template <int cols>
  7. void f(int array[][cols], int row, int col, int value)
  8. {
  9.     array[row][col]=value;
  10. }
  11.  
  12. int main()
  13. {
  14.     int array[ROWS][COLS] = {};
  15.     f(array, 2, 3, 4);
  16.     printf("array[2][3] = %d\n", array[2][3]);
  17.     return 0;
  18. }
  19.  
In the template method, the number of columns in the array is inferred by the array that it is passed.

Advantages over Variable Passing
  • The number of columns is inferred by the array you pass it.
  • It has a slight speed advantage because for each array with a different number of columns that is passed to the function f(), a whole new function f() is compiled, optimised for that number of columns.
    This is only really noticeable when the function is called thousands (if not more) of times or unless you are running this on a very slow system.
  • Should be accepted by any ANSII C++ compiler.

Disadvantages over Variable Passing
  • Increase in the object size if you have many, many, many different arrays with equally as many different number of columns being passed to the template function. This concern is usually very minimal
  • Template functions as yet, cannot be hidden in source code due to current compilation methods. This function, in its entirety, must be exposed to those functions who use it. Which usually means that it has to be put in to the header file.

If I am wrong, no great loss to me, I learned quite a bit from this conversation, but it wouldn’t help you much ;).

If I am right, please state what compiler you are using. I’d be interested.


Adrian
Feb 12 '07 #10

Sign in to post your reply or Sign up for a free account.

Similar topics

17
43906
by: Roland Hall | last post by:
Is there a way to return multiple values from a function without using an array? Would a dictionary object work better? -- Roland Hall /* This information is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. */ Technet Script...
5
3076
by: Gent | last post by:
I have two questions which are very similar: Is it possible to return an object in C++. Below is part of my code for reference however I am more concerned about the concept. It seems like the function below is returning a pointer to pointers who are GUID. I am trying to write a wrapper to use in my VB code and what I would prefer to do is be...
7
1529
by: pmatos | last post by:
Hi all, I've been having questions about strings, references, initializations... I've created code (which will not compile due to a reference problem) and I'd like comments on why this won't work and any other comment to the code with efficiency in mind. #include <iostream> #include <string>
10
10275
by: Fraser Ross | last post by:
I need to know the syntax for writing a reference of an array. I haven't seen it done often. I have a class with a member array and I want a member function to return an reference to it. Returning a pointer to the first element might do but I want to do what I've said. Fraser.
3
2682
by: Faustino Dina | last post by:
Hi, The following code is from an article published in Informit.com at http://www.informit.com/guides/content.asp?g=dotnet&seqNum=142. The problem is the author says it is not a good idea to return an array as a property because it will return a copy of the array instead a reference to it. How can I force the property to return a reference...
11
8106
by: John Pass | last post by:
Hi, In the attached example, I do understand that the references are not changed if an array is passed by Val. What I do not understand is the result of line 99 (If one can find this by line number) which is the last line of the following sub routine: ' procedure modifies elements of array and assigns ' new reference (note ByVal) Sub...
9
1861
by: josh | last post by:
Hi, I'm converting (for learning purpose) )a program from Java to C++ and I've a doubt: In Java every argument (variable and reference types) is passed and returned in functions by-value so if I want to create inside that function a matrix (i.e. int a) and than passing the reference to it I can simply returning that value: in main()
8
2924
by: =?Utf-8?B?UHVjY2E=?= | last post by:
Hi, I'm using vs2005, .net 2, C# for Windows application. I use DllImport so I can call up a function written in C++ as unmanaged code and compiled as a dll us vs2005. My application is able to call the function, EncodeAsnUser. And it's returning OK but when I display the decoded data in another part of my application it shows no data has...
8
1779
by: jodleren | last post by:
Hi! I have a function, a part of my code which I can use as a function. It will return 2 arrays, and I am wondering what way to do so. Both arrays hold strings, there are no special keys. 1) setting the arrays as globals 2) returnin an array of arrays 3) returning a large array with a known marker to indicate when the 2nd part starts.
1
7922
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
8185
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6571
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
5366
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3811
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3836
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2317
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1416
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1147
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.