Thread: returning multiple arrays from one function to another

  1. #1
    Registered User
    Join Date
    Aug 2010
    Posts
    12

    returning multiple arrays from one function to another

    HI there

    I usually program in Fortran but for a certain project i need to use some existing C routines.
    I am mildly familiar with C but clearly not enough to get round this problem.

    Below you will see a funciton called 'readinfiles' and then the main program below that.
    Previously i had the content of readinfiles in the main program, but i want to be able to read in all my 3 files in a separate function, allocate all the arrays, pass them out of the function 'readinfiles' and into the main program and into the other functions shown below i.e rr_counts(xx_r,yy_r,zz_r,nrows2,nrows3,rad); dr_counts(xx_d,yy_d,zz_d,xx_r,yy_r,zz_r,nrows1,nro ws3,rad);
    dd_counts(xx_d,yy_d,zz_d,nrows1,nrows3,rad);

    so the arrays that are being allocated are xx_r,yy_r,zz_r,xx_d,yy_d,zz_d and rad . nrows1 and nrows3 are integers which are the number of rows in the arrays.

    I have tried various ways to get the function to work - none of them successful.. mostly i get an error saying that e.g xx_r is not declared in int main (or something like that). The version below has been stripped back to very basic declaration at the top and return at the bottom.


    Any help would be much appreciated!





    --------------------------
    Code:
    int  readinfiles(){
    	
      int headercount1,linecount1,nrows1,headercount2,linecount2,nrows2;
      int headercount3,linecount3,nrows3;
      int i;
      FILE *file1,*file2,*file3;  
    
      file1 = open_file_read("file1");	
      if(file1 == NULL)  {
        exit(1);
      }
      get_file_length(file1,&headercount1,&linecount1);
      nrows1 = linecount1 - headercount1;
      printf("there are %d in FIRST data\n",nrows1);
      (void) rewind(file1);
    	
      long double  *xx_d = malloc(sizeof(long double) * nrows1);
      long double  *yy_d = malloc(sizeof(long double) * nrows1);
      long double  *zz_d = malloc(sizeof(long double) * nrows1);
      for(i=0; i<nrows1; i++) 
    	{	
    		fscanf(file1,"%Le %Le %Le",&xx_d[i],&yy_d[i],&zz_d[i]);
    	}
    	
      fclose(file1);
     	
    
    	file2 = open_file_read("file2.dat");	
    	if(file2 == NULL)  {
        exit(1);
      }
      get_file_length(file2,&headercount2,&linecount2);
      nrows2 = linecount2 - headercount2;
      printf("there are %d in random data\n",nrows2);
      (void) rewind(file2);	
    	
      long double  *xx_r = malloc(sizeof(long double) * nrows2);
      long double  *yy_r = malloc(sizeof(long double) * nrows2);
      long double  *zz_r = malloc(sizeof(long double) * nrows2);
      for(i=0; i<nrows2; i++) 
    	{
    		fscanf(file2,"%Le %Le %Le",&xx_r[i],&yy_r[i],&zz_r[i]);
    	}
      fclose(file2);
    	
      file3 = open_file_read("file3.dat");
    	
      if(file3 == NULL)  {
        exit(1);
      }
      get_file_length(file3,&headercount3,&linecount3);
      nrows3 = linecount3 - headercount3;
      printf("there are %d in rad.dat\n",nrows3);
    	
      long double *rad=malloc(sizeof(long double) *nrows3);
    	
      for(i=0; i<nrows3; i++) 
    	{
    		fscanf(file3,"%Le",&rad[i]);
    		printf("%Le\n",rad[i]);
    	}
      fclose(file3);  
      return ;
    }
    
    /*----------------------------------------------------------------------------*/
    /*---------------M A I N    P R O G R A M ------------------------------------*/
    int main(int argc, char **argv)
    {	
     	
         readinfiles();
    	
         rr_counts(xx_r,yy_r,zz_r,nrows2,nrows3,rad);  	
       dr_counts(xx_d,yy_d,zz_d,xx_r,yy_r,zz_r,nrows1,nrows3,rad); 
       dd_counts(xx_d,yy_d,zz_d,nrows1,nrows3,rad); 
    
    	twoptcorr();
    	
      return 0;
    }
    Last edited by renderg; 08-24-2010 at 02:59 AM. Reason: adding tags

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Begin by following the advice here: << !! Posting Code? Read this First !! >>
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Registered User
    Join Date
    Jan 2010
    Posts
    34
    Looking at your code, the first problem is that all the variables you use in the main are defined in the readinfiles() function.
    You must move them outside of the function, for example:
    Code:
    long double *xx_r;
    long double *yy_r ;
    long double *zz_r ;
    
    int readinfiles(){
    .
    .
    .
    .
    	xx_r =  malloc(sizeof(long double) * nrows2);
    	yy_r =  malloc(sizeof(long double) * nrows2);
    	zz_r =  malloc(sizeof(long double) * nrows2);
    
    
    }

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by giove
    Looking at your code, the first problem is that all the variables you use in the main are defined in the readinfiles() function.
    Agreed, that looks like a problem.

    Quote Originally Posted by giove
    You must move them outside of the function, for example:
    No, that is not required, and in fact is bad advice. Generally, global variables should be avoided. Passing a pointer is likely to be more appropriate.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Aug 2010
    Posts
    12
    Quote Originally Posted by giove View Post
    Looking at your code, the first problem is that all the variables you use in the main are defined in the readinfiles() function.
    You must move them outside of the function, for example:
    Code:
    long double *xx_r;
    long double *yy_r ;
    long double *zz_r ;
    
    int readinfiles(){
    .
    .
    .
    .
    	xx_r =  malloc(sizeof(long double) * nrows2);
    	yy_r =  malloc(sizeof(long double) * nrows2);
    	zz_r =  malloc(sizeof(long double) * nrows2);
    
    
    }

    ahh ok.. noted: so in fortran, for example, i would do something like the following:

    Code:
    subroutine readinfiles(xx_d, nrows1,nrows2)
    integer, parameter :: N=1000000
    real :: xx_d(N)
    integer :: nrows1,nrows2
    
    and so on...
    
    .
    .
    .
    
    return
    end
    That way all the arrays get passed through the parenthasis.
    then in the main program would be :

    Code:
    program blah
    integer, parameter :: N=1000000
    real :: xx_d(N)
    integer :: nrows1,nrows2
    
    call readinfiles(xx_d, nrows1,nrows2)
    
    so then pass those arrays into:
    call nextsubroutine(xx_d,nrows1,nrows2)

    So when you say that i have to declare the arrays outside the function - is that delcared in main only?

    many thanks!

  6. #6
    Registered User
    Join Date
    Aug 2010
    Posts
    12
    Quote Originally Posted by laserlight View Post
    Agreed, that looks like a problem.


    No, that is not required, and in fact is bad advice. Generally, global variables should be avoided. Passing a pointer is likely to be more appropriate.
    Hmmm... how would one do that ?

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by renderg
    ahh ok.. noted: so in fortran, for example, i would do something like the following:
    (...)
    That way all the arrays get passed through the parenthasis.
    I do not know Fortran so I cannot say if your syntax corresponds to what I have in mind, but if you are talking about the use of function parameters, then yes, that is the right idea.

    Quote Originally Posted by renderg
    So when you say that i have to declare the arrays outside the function - is that delcared in main only?
    You should declare the pointers in the main function. You are not declaring arrays at all. Rather, what you can do is then pass a pointer to each of these pointers in the main function to readinfiles as arguments. You would also need to pass pointers to corresponding variables that hold the size of the dynamic arrays.

    Looking at your current readinfiles function, I would say that it is doing too much work. You are effectively repeating the same process of reading three times in the same function. Rather, write a function that performs this process once, then pass it different arguments three times.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Aug 2010
    Posts
    12
    Quote Originally Posted by laserlight View Post
    I do not know Fortran so I cannot say if your syntax corresponds to what I have in mind, but if you are talking about the use of function parameters, then yes, that is the right idea.


    You should declare the pointers in the main function. You are not declaring arrays at all. Rather, what you can do is then pass a pointer to each of these pointers in the main function to readinfiles as arguments. You would also need to pass pointers to corresponding variables that hold the size of the dynamic arrays.

    Looking at your current readinfiles function, I would say that it is doing too much work. You are effectively repeating the same process of reading three times in the same function. Rather, write a function that performs this process once, then pass it different arguments three times.
    Ok, thanks for your advice (and everyone else).. i will try to implement this just now and post on my progress....

    cheers!

  9. #9
    Registered User
    Join Date
    Jan 2010
    Posts
    34
    The rule inside a single file is this:

    a variable is called global if it's defined outside main() or functions().

    If you want to declare them inside the main(), you must then pass all them as function's parameters.

  10. #10
    Registered User
    Join Date
    Aug 2010
    Posts
    12
    Quote Originally Posted by laserlight View Post
    I do not know Fortran so I cannot say if your syntax corresponds to what I have in mind, but if you are talking about the use of function parameters, then yes, that is the right idea.


    You should declare the pointers in the main function. You are not declaring arrays at all. Rather, what you can do is then pass a pointer to each of these pointers in the main function to readinfiles as arguments. You would also need to pass pointers to corresponding variables that hold the size of the dynamic arrays.
    So against your advice - just so i can get a handle on things - i have done the following which seems to work....

    At the top of the program i declare the following...

    Code:
    #include <stdio.h>
    #include <math.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <assert.h>
    #include <sys/time.h>
    #include <time.h>
    #include "kdtree.h"
    #include <fftw3.h>
    /* for the read in a csv file code */
    #include <string.h>
    #define NUM_OF(x) (sizeof (x) / sizeof *(x))
    #define MAXLINELEN 256
    
    long double  *xx_d; 
    long double  *yy_d;
    long double  *zz_d;
    long double  *xx_r; 
    long double  *yy_r;
    long double  *zz_r;
    long double  *rad;
    int nrows1,nrows3,nrows2;
    then in function readin files we have:

    Code:
    int readinfiles()
    {  
    .
    .
    .
    	
      xx_d = malloc(sizeof(long double) * nrows1);
      yy_d = malloc(sizeof(long double) * nrows1);
      zz_d = malloc(sizeof(long double) * nrows1);
    .
    .
    .
    return 0;
    
    }
    finally in int main i write:

    Code:
    int main(int argc, char **argv)
    {	
    	
    readinfiles();
    
    rr_counts(xx_r,yy_r,zz_r,nrows2,nrows3,rad);  	
    
    .
    .
    .
    return 0;
    }
    so on the surface it seems to be working fine, but how would you amend this such that i am not declaring global variables? Also, return 0 in the readinfile function seems to not affect things being returned - is this ok?

    many thanks in advance!

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by renderg
    so on the surface it seems to be working fine, but how would you amend this such that i am not declaring global variables? Also, return 0 in the readinfile function seems to not affect things being returned - is this ok?
    I had something like this in mind:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "your_other_header.h"
    
    struct Data /* For lack of a better name */
    {
        long double x;
        long double y;
        long double z;
    };
    
    struct DataList
    {
        struct Data *data;
        size_t size;
    };
    
    int readFile(const char *filename, struct DataList *data_list)
    {
        FILE *file;
        int header_count, line_count;
        int i;
    
        file = open_file_read(filename);
        if (file == NULL)
        {
            return 0;
        }
    
        get_file_length(file, &header_count, &line_count);
        data_list->size = line_count - header_count;
        (void)rewind(file);
    
        /* Assume malloc succeeds */
        data_list->data = malloc(sizeof(*data_list->data) * data_list->size);
        for (i = 0; i < data_list->size; ++i)
        {
            /* Assume fscanf succeeds */
            fscanf(file, "%Le %Le %Le",
                &data_list->data[i].x, &data_list->data[i].y, &data_list->data[i].z);
        }
        fclose(file);
        return 1;
    }
    
    int main(void)
    {
        struct DataList data_list_d, data_list_r;
        if (readFile("file1", &data_list_d))
        {
            printf("there are %d in FIRST data\n", data_list_d.size);
            free(data_list_d.data);
        }
    
        if (readFile("file2.dat", &data_list_r))
        {
            printf("there are %d in random data\n", data_list_r.size);
            free(data_list_r.data);
        }
    
        /* The code for the third file read is left as an exercise for the reader. */
    
        return 0;
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    Registered User
    Join Date
    Aug 2010
    Posts
    12
    Quote Originally Posted by laserlight View Post
    I had something like this in mind:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "your_other_header.h"
    
    struct Data /* For lack of a better name */
    {
        long double x;
        long double y;
        long double z;
    };
    
    struct DataList
    {
        struct Data *data;
        size_t size;
    };
    
    int readFile(const char *filename, struct DataList *data_list)
    {
        FILE *file;
        int header_count, line_count;
        int i;
    
        file = open_file_read(filename);
        if (file == NULL)
        {
            return 0;
        }
    
        get_file_length(file, &header_count, &line_count);
        data_list->size = line_count - header_count;
        (void)rewind(file);
    
        /* Assume malloc succeeds */
        data_list->data = malloc(sizeof(*data_list->data) * data_list->size);
        for (i = 0; i < data_list->size; ++i)
        {
            /* Assume fscanf succeeds */
            fscanf(file, "%Le %Le %Le",
                &data_list->data[i].x, &data_list->data[i].y, &data_list->data[i].z);
        }
        fclose(file);
        return 1;
    }
    
    int main(void)
    {
        struct DataList data_list_d, data_list_r;
        if (readFile("file1", &data_list_d))
        {
            printf("there are %d in FIRST data\n", data_list_d.size);
            free(data_list_d.data);
        }
    
        if (readFile("file2.dat", &data_list_r))
        {
            printf("there are %d in random data\n", data_list_r.size);
            free(data_list_r.data);
        }
    
        /* The code for the third file read is left as an exercise for the reader. */
    
        return 0;
    }
    Thanks so much for that - it seems to work exactly as you have written it!

    cheers
    R.

  13. #13
    Registered User
    Join Date
    Aug 2010
    Posts
    12

    One last thing!

    So, one last problem.... I can get the above code to work but i cant see how i 'pass' the x,y & z values into another function...

    So, for example, in int main after reading in file to '&data_list_d' i can print to screen the values of x,y,z for data_list_d such that

    Code:
    for (i=0; i<data_list_d.size; ++i) {
    		printf("%d %Le %Le %Le\n"
    ,i,data_list_d.data[i].x,data_list_d.data[i].y,data_list_d.data[i].z);
    	}
    but now i want to use those arrays in another function which is called straight afterwards:

    rr_counts();

    but cant see how to do that.

  14. #14
    Registered User
    Join Date
    Jan 2010
    Posts
    34
    You must define the function
    rr_counts(struct DataList* arrayOne,struct DataList* arrayTwo);

  15. #15
    Registered User
    Join Date
    Aug 2010
    Posts
    12
    Quote Originally Posted by giove View Post
    You must define the function
    rr_counts(struct DataList* arrayOne,struct DataList* arrayTwo);
    Hi Giove

    thanks for the help.. i should probably re-iterate my general ignorance of C syntax.. whilst through this thread i am getting a better handle on structures and pointers, I just need a little push to get over the finishing line.

    In the above syntax that you quoted how to pass the arrays through but how does that translate into the following:

    1. the rr_counts function itself? what i mean by this is when i delcare the
    function what exactly do i put in the paranthasis in terms of

    data_list_d.data[i].x,data_list_d.data[i].y,data_list_d.data[i].z

    Code:
    int rr_counts(how do i pass things in here?) {
    
    do i need to declare anything here?
    
    }
    2. In terms of calling the function in int main

    Code:
    rr_counts(struct DataList* how do i define ArrayOne from say data_list_d.data[i].x ... etc...);

    I have tried various combinations but end of with various errors when compiling.

    THANKS!
    R.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. random number gen difficult
    By Chris_1980 in forum C Programming
    Replies: 21
    Last Post: 04-30-2010, 09:02 AM
  2. doubt in c parser coding
    By akshara.sinha in forum C Programming
    Replies: 4
    Last Post: 12-23-2007, 01:49 PM
  3. returning char arrays!!!!
    By bobthebullet990 in forum C Programming
    Replies: 2
    Last Post: 03-30-2006, 07:05 AM
  4. Problem with Visual C++ Object-Oriented Programming Book.
    By GameGenie in forum C++ Programming
    Replies: 9
    Last Post: 08-29-2005, 11:21 PM
  5. c function returning multiple values
    By Unregistered in forum C Programming
    Replies: 3
    Last Post: 11-23-2001, 10:09 AM

Tags for this Thread