6 Replies - 2608 Views - Last Post: 20 June 2012 - 04:26 AM Rate Topic: -----

#1 nradam  Icon User is offline

  • D.I.C Head

Reputation: 2
  • View blog
  • Posts: 56
  • Joined: 28-February 10

returning multidimensional arrays

Posted 18 June 2012 - 02:28 AM

How do i return a multidimensional array (actually it is dynamically allocated although i dont think that matters) of type double in C ? I am not able to understand how by going through google for hours and hours. Any tips would be highly appreciated :)

Cheers
Nifal Adam
Is This A Good Question/Topic? 0
  • +

Replies To: returning multidimensional arrays

#2 Salem_c  Icon User is offline

  • void main'ers are DOOMED
  • member icon

Reputation: 1645
  • View blog
  • Posts: 3,121
  • Joined: 30-May 10

Re: returning multidimensional arrays

Posted 18 June 2012 - 03:04 AM

Typically, something like
double **foo ( ) {
  double *result = malloc....
  result[0] = malloc....
  // more stuff
  return result;
}


Was This Post Helpful? 0
  • +
  • -

#3 nradam  Icon User is offline

  • D.I.C Head

Reputation: 2
  • View blog
  • Posts: 56
  • Joined: 28-February 10

Re: returning multidimensional arrays

Posted 18 June 2012 - 05:57 AM

Here is my program at the moment. I am totally lost here and i have no way out. My current program works perfectly and it reads an stl file (ASCII) of any size and comes out with three matrices. ie.

vectarr (Its a 3N X 3 matrix containing vertices)
normarr (Its a N X 3 matrix containing the normals)
centerarr (Its a N X 3 matrix containing the centers)

I need to call a function in Dymola so that it can access these matrices. But the current problem is that my program is written in the main function. I want to make this program into a function and call it as an external function from the main function of the program. The parameter of the function call must be just the name of the stl file. And the three (or atleast one) multidimensional arrays must be returned.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define COLS 3                      //Defining a constant for number of columns
int main(int argc, char **argv) {
	FILE *fp = fopen(argv[1], "r"); //Opening file to read
	char string1[20];
	int loopx = 0, loopy = 0, loopn = 0;
	double tmp;
	int i = 0;
	static double (*vectarr)[COLS]; //Dynamic memory allocation
	static double (*normarr)[COLS];
	static double (*centerarr)[COLS];
	normarr = malloc(COLS * sizeof(double));
	if (normarr == NULL) {
		puts("Failure to allocate memory");
		exit(0);
	}
	vectarr = malloc(3 * COLS * sizeof(double));
	if (vectarr == NULL) {
		puts("Failure to allocate memory");
		exit(0);
	}
	centerarr = malloc(COLS * sizeof(double));
	if (centerarr == NULL) {
		puts("Failure to allocate memory");
		exit(0);
	}
	if (fp == NULL) {
		printf("Cannot open file.\n");
		exit(1);
	}

	while (fscanf(fp, "%s", string1) != EOF) { //The infinite loop
		if (isdigit(string1[0]) != 0 || isdigit(string1[1]) != 0) {
			//Saving the values into the dynamic array
			if (loopn == 3) {
				vectarr[3 * i + loopx][loopy] = atof(string1);
				loopy++;
				if (loopy == 3) {
					loopx++;
					loopy = 0;
				}
			}
			if (loopn != 3) {
				normarr[i][loopn] = atof(string1);
				loopn++;
			}
			if (loopn == 3 && loopx == 3) { //On to next triangle

				for (loopy = 0; loopy < 3; loopy++) {
					tmp = 0;
					for (loopx = 0; loopx < 3; loopx++)
						tmp = tmp + vectarr[3 * i + loopx][loopy];
					tmp = tmp / 3;
					centerarr[i][loopy] = tmp;
				}

				loopx = 0;
				loopy = 0;
				loopn = 0;
				i++;

				double (*tmp1)[COLS] = realloc(normarr,
						(i + 1) * COLS * sizeof(double)); //reallocating memory
				if (tmp1 != NULL)
					normarr = tmp1;
				else {
					fprintf(stderr, "Can't reallocate memory\n");
				}
				double (*tmp2)[COLS] = realloc(vectarr,
						3 * (i + 1) * COLS * sizeof(double));
				if (tmp2 != NULL)
					vectarr = tmp2;
				else {
					fprintf(stderr, "Can't reallocate memory\n");
				}

				double (*tmp3)[COLS] = realloc(centerarr,
						(i + 1) * COLS * sizeof(double)); //reallocating memory
				if (tmp3 != NULL)
					centerarr = tmp3;
				else {
					fprintf(stderr, "Can't reallocate memory\n");
				}

			}

		}
	}

	printf("Done"); //Indicating that the program is done.

	if (fp != NULL) //Closing the file
		fclose(fp);

	return 0;

}




I am totally stuck now for hours. You have to help me out, ill be greatful :)

Thank you
Was This Post Helpful? 0
  • +
  • -

#4 jimblumberg  Icon User is offline

  • member icon


Reputation: 4018
  • View blog
  • Posts: 12,400
  • Joined: 25-December 09

Re: returning multidimensional arrays

Posted 18 June 2012 - 06:17 AM

Is there a reason for the following?
#define COLS 3                      //Defining a constant for number of columns

int main(int argc, char **argv) {

	static double (*normarr)[COLS];

	normarr = malloc(COLS * sizeof(double));



Since COLS is a constant why use dynamic memory?

Why are you using the static keyword?

Since this is main why not just use a "normal" multidimensional array?
double normarr[COLS][COLS];


Jim

This post has been edited by jimblumberg: 18 June 2012 - 06:17 AM

Was This Post Helpful? 0
  • +
  • -

#5 Salem_c  Icon User is offline

  • void main'ers are DOOMED
  • member icon

Reputation: 1645
  • View blog
  • Posts: 3,121
  • Joined: 30-May 10

Re: returning multidimensional arrays

Posted 18 June 2012 - 06:22 AM

The syntax for returning a pointer to an array is a bit cryptic.
double (*foo())[COLS] {
   double (*vectarr)[COLS] = malloc( 10 * sizeof(*vectarr) );
   return vectarr;
}



Making a typedef simplifies this greatly.
typedef double (*atype)[COLS];
atype bar() {
   double (*vectarr)[COLS] = malloc( 10 * sizeof(*vectarr) );
   // could also do
   // atype vectarr = malloc( 10 * sizeof(*vectarr) );
   return vectarr;
}


Notice in both cases the use of sizeof(*p). You never have to explicitly refer back to the declaration of the pointer. There is enough information from working out the size of what p points to.

But to simplify your code, how about
typedef struct {
    double (*vectarr)[COLS]; //Dynamic memory allocation
    double (*normarr)[COLS];
    double (*centerarr)[COLS];
} stl_st;
stl_st readSTLFile ( const char *filename ) {
  stl_st    result = { NULL, NULL, NULL };
  // do stuff
  return result;
}


All three pointers to all the data travel together in a nice struct you can pass around from one function to another.
Was This Post Helpful? 3
  • +
  • -

#6 baavgai  Icon User is online

  • Dreaming Coder
  • member icon

Reputation: 5801
  • View blog
  • Posts: 12,636
  • Joined: 16-October 07

Re: returning multidimensional arrays

Posted 18 June 2012 - 06:44 AM

I'd second struct passing. I'd really, really want to keep track of rows, too.

I'd probably start with a simple matrix, forget the const cols. Then go from there:
typedef struct {
	double **data;
	int rows, int cols;
} Matrix;

typedef struct {
    Matrix vect, norm, center;
} Data;

void createMatrix(Matrix *, int rows, int cols);
void destroyMatrix(Matrix *);

void createData(Data *, int N, int cols);
void destroyData(Data *);




Now, the rest of the program is simply a function of passing Data * or Matrix *. Much easier.
Was This Post Helpful? 3
  • +
  • -

#7 nradam  Icon User is offline

  • D.I.C Head

Reputation: 2
  • View blog
  • Posts: 56
  • Joined: 28-February 10

Re: returning multidimensional arrays

Posted 20 June 2012 - 04:26 AM

DAmn, thanks for all the replies. But returning the array was a pain in the a$$ because of the multiple arrays, i tried everything but even when i succeeded i had no idea how to pass the array into dymola that way. A much easier way was to directly allocate the arrays into the pointer passed as parameter from modelica (dymola). I also stopped using so much reallocation of memory as it makes the programming crappy and instead found the number of rows by reading the file once and allocating a constant sized array directly by malloc. Also i stopped using 2 dimensional arrays and switched to 1 dimensional array as required by dymola (and also easier :)). Yea, so here is my final code :) There are two functions, one for finding size required for the array and other one for parsing the stl file and creating the arrays.

Finding array size code:
//Count the no of facets

#ifndef ExtRowFunc_C
#define ExtRowFunc_C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void ExtRowFunc(char* file_name, int* no_facets) {
	FILE *fp = fopen(file_name, "r"); //Opening file to read
	if (fp == NULL) {
		printf("Cannot open file.\n");
		exit(1);
	}
	*no_facets = 0;
	char string[20];
	while (fscanf(fp, "%s", string) != EOF) {
		if (!strcmp(string, "endfacet"))
			(*no_facets)++;
	}
}

#endif



Parsing stl and creating array code:
#ifndef StlParse_C
#define StlParse_C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

void StlParse(char* file_name, int no_facets, double* vectarr, double* normarr) {
	char string[20];
	int i = 0;
	int loopx = 0, loopy = 0, loopn = 0;

	FILE *fp = fopen(file_name, "r"); //Opening file to read
	if (fp == NULL) {
		printf("Cannot open file.\n");
		exit(1);
	}

	while (fscanf(fp, "%s", string) != EOF) {
		if (isdigit(string[0]) != 0 || isdigit(string[1]) != 0) {

			if (loopn == 3) {
				vectarr[9 * i + 3 * loopx + loopy] = atof(string);
				loopy++;
				if (loopy == 3) {
					loopx++;
					loopy = 0;
				}
			}
			if (loopn != 3) {
				normarr[3 * i + loopn] = atof(string);
				loopn++;
			}
			if (loopn == 3 && loopx == 3) { //On to next triangle
				loopx = 0;
				loopy = 0;
				loopn = 0;
				i++;
			}
		} //isdigit
	} //while

}

#endif



I have other doubts now, and i will ask it in a different thread :D
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1