I am trying to pass a struct of 2D arrays and to do calculations on them.
typedef struct{
float X[80][2];
float Y[80][2];
float Z[80][2];
int T[80][2];
int K[80];
} STATS;
void MovingAverage(STATS *stat_array, int last_stat) {
//Average = Average(Prev) + (ValueToAverage/n) - (Average(Prev)/n)
stat_array->**X**[last_stat][0] = stat_array->**X**[last_stat][0] +
(stat_array->**X**[last_stat][1] / stat_array->T[last_stat][0]) -
(stat_array->**X**[last_stat][0] / stat_array->T[last_stat][0]);
}
calling the function:
MovingAverage(*stat_array, last_stat);
My question is:
how do I access in a generic way to X Y and Z inside MovingAverage function?
Edit:
void MovingAverage(STATS *stat_array, int last_stat, (char *(array_idx)) {
//Average = Average(Prev) + (ValueToAverage/n) - (Average(Prev)/n)
stat_array->**array_idx**[last_stat][0] =
stat_array->**array_idx**[last_stat][0] +
(stat_array->**array_idx**[last_stat][1] /
stat_array->T[last_stat][0]) -
(stat_array->**array_idx**[last_stat][0] /
stat_array->T[last_stat][0]);
}
I know it won't work, but just to demonstrate my willings,
Somebody here (not me) could probably come up with some preprocessor magic to do what you're asking, but that is a solution I would not pursue. I consider it bad practice since macros can quickly get hairy and tough to debug. You can't have "variables" inside your source code, if that makes sense. During the build procedure, one of the first things that runs is the preprocessor, which resolves all your macros. It then passes that source code to the compiler. The compiler is not going to do any text substitutions for you, it cranks on the source code it has. To achieve what you want, write a function that operates on the type you want, and call that function with all your types. I'd change your MovingAverage function to something like this:
void MovingAverage(float arr[80][2], const int T[80][2], int last_stat)
{
arr[last_stat][0] = ... // whatever calculation you want to do here
}
int main(void)
{
STATS stat_array;
int last_stat;
// .. initialize stat_array and last_stat
// now call MovingAverage with each of your 3 arrays
MovingAverage(stat_array.X, stat_array.T, last_stat);
MovingAverage(stat_array.Y, stat_array.T, last_stat);
MovingAverage(stat_array.Z, stat_array.T, last_stat);
...
return 0;
}
#include <stdio.h>
#include <math.h>
#define Hey {0.9501, 0.2311, 0.6068, 0.4860, 0.8913, 0.7621, 0.4565, 0.0185, 0.8214, 0.4447, 0.6154, 0.7919, 0.9218, 0.7382, 0.1763, 0.4057, 0.9355, 0.9169, 0.4103, 0.8936, 0.0579, 0.3529, 0.8132, 0.0099, 0.1389, 0.2028, 0.1987, 0.6038, 0.2722, 0.1988, 0.0153, 0.7468, 0.4451, 0.9318, 0.4660, 0.4186, 0.8462, 0.5252, 0.2026, 0.6721, 0.8381, 0.0196, 0.6813, 0.3795, 0.8318, 0.5028, 0.7095, 0.4289, 0.3046, 0.1897, 0.1934, 0.6822, 0.3028, 0.5417, 0.1509, 0.6979, 0.3784, 0.8600, 0.8537, 0.5936, 0.4966, 0.8998, 0.8216, 0.6449, 0.8180, 0.6602, 0.3420, 0.2897, 0.3412, 0.5341, 0.7271, 0.3093, 0.8385, 0.5681, 0.3704, 0.7027, 0.5466, 0.4449, 0.6946, 0.6213, 0.7948, 0.9568, 0.5226, 0.8801, 0.1730, 0.9797, 0.2714, 0.2523, 0.8757, 0.7373, 0.1365, 0.0118, 0.8939, 0.1991, 0.2987, 0.6614, 0.2844, 0.4692, 0.0648,0.9883}
float average(float Hello[]){
int i;
float sum;
for (i=0; i<100;i++) {
sum+= Hello[i];
}
return sum/100;
}
int main(){
printf("%f\n",average(Hey));
//so here the compiler says that expected error without giving me what the error actually is. and i suspect because of the bad definition of the vector that i have at the very beginning of my code.
}
Yeah, so as i stated in my comment the problem is with the c preprocesses as its referred to here in stack overflow. is my predefinition for the array Hey wrong? and why?
Usually this is how to predefine an array in C, omit the size and provide the values in brackets. Eg,
const float Hey[] = {0.9501, 0.2311, 0.6068 };
If you really want to, you can do something like this.
#include <stdio.h>
#include <math.h>
#define HEY_INIT { 0.9501, 0.2311, 0.6068, 0.4860, 0.8913, 0.7621, 0.4565, 0.0185, 0.8214, 0.4447, 0.6154, 0.7919, 0.9218, 0.7382, 0.1763, 0.4057, 0.9355, 0.9169, 0.4103, 0.8936, 0.0579, 0.3529, 0.8132, 0.0099, 0.1389, 0.2028, 0.1987, 0.6038, 0.2722, 0.1988, 0.0153, 0.7468, 0.4451, 0.9318, 0.4660, 0.4186, 0.8462, 0.5252, 0.2026, 0.6721, 0.8381, 0.0196, 0.6813, 0.3795, 0.8318, 0.5028, 0.7095, 0.4289, 0.3046, 0.1897, 0.1934, 0.6822, 0.3028, 0.5417, 0.1509, 0.6979, 0.3784, 0.8600, 0.8537, 0.5936, 0.4966, 0.8998, 0.8216, 0.6449, 0.8180, 0.6602, 0.3420, 0.2897, 0.3412, 0.5341, 0.7271, 0.3093, 0.8385, 0.5681, 0.3704, 0.7027, 0.5466, 0.4449, 0.6946, 0.6213, 0.7948, 0.9568, 0.5226, 0.8801, 0.1730, 0.9797, 0.2714, 0.2523, 0.8757, 0.7373, 0.1365, 0.0118, 0.8939, 0.1991, 0.2987, 0.6614, 0.2844, 0.4692, 0.0648, 0.9883 }
static const float Hey[] = HEY_INIT; // global array
float average(float Hello[]) {
int i;
float sum;
for (i = 0; i < 100; i++) {
sum += Hello[i];
}
return sum / 100;
}
int main(void) {
printf("%f\n", average(Hey));
return 0;
}
example: an array containing 4 integer values of type int called abc could be represented as: int abc [4];
by default, regular arrays of local scope (in this example, those declared inside the function) are ignored.
But the elements in an array can be explicitly initialized to specific values when it is declared, by enclosing those initial values in braces {}. For example:
int abc [4] = { 1, 2, 47, 50, -371 };
in other case you can let empty the brackets so you can initialize them when the program is running e.g. int abc [] ; or you can use a matrix like :int abc [] []; with X lines & Y columns.
I'm new programing in C. I have a main code with 781 lines that is out of control because garbage value is stored in vectors. A short part of the main code is shown below where it calls a subroutine called diff_conv_intermedia1.
diff_conv_intermedia1(&factorteta,&N,ID,DIFF,X1_intermedia,Y1_intermedia,X1C_intermedia,Y1C_intermedia,CU1_intermedia,CV1_intermedia,AW1_intermedia,AE1_intermedia,AS1_intermedia,AN1_intermedia,AP1_intermedia,Q1_intermedia,FXI1,FYI1,FI_intermedia1,1,2,1,1);
int q,w;
for(q=1;q<(*factorteta_Ptr)*2+1;q++)
{
for(w=1;w<(*N_Ptr)+1;w++)
{
printf("%lf\n",AP1_intermedia[q][w]);
}
}
So the subroutine shown below. When I print the results inside the subroutine, everything is OK, but when I print the results outside the subroutine, in the main code, garbage is stored in the vectors as AP1_intermedia. I don't know what could be wrong. I repeat the same procedure with other subroutines and I don't have any errors.
int diff_conv_intermedia1(int *factorteta_Ptr,
int *N_Ptr,
int ID,
double DIFF,
double X[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double Y[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double XC[(*factorteta_Ptr)*2+2][*N_Ptr+2],
double YC[(*factorteta_Ptr)*2+2][*N_Ptr+2],
double CU[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double CV[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AW[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AE[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AS[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AN[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double AP[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double Q[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double FX[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double FY[(*factorteta_Ptr)*2+1][*N_Ptr+1],
double FI[(*factorteta_Ptr)*2+1][*N_Ptr+1],
int WBC,int EBC,int SBC,int NBC)
{
int i,j;
double value,* valuePtr;
double AED, AWD, AND, ASD;
double AEC, AWC, ANC, ASC;
valuePtr = &value;
// Diffusive coefficients
for(i=1;i<(*factorteta_Ptr)*2+1;i++)
{
for(j=1;j<*N_Ptr+1;j++)
{
AWD = -DIFF*(Y[i][j-1]-Y[i-1][j-1])/(XC[i][j]-XC[i][j-1]);
AED = -DIFF*(Y[i][j]-Y[i-1][j])/(XC[i][j+1]-XC[i][j]);
AND = -DIFF*(X[i][j]-X[i][j-1])/(YC[i+1][j]-YC[i][j]);
ASD = -DIFF*(X[i-1][j]-X[i-1][j-1])/(YC[i][j]-YC[i-1][j]);
// Convection term
if(ID==2)
{
max1_or_min2(CU[i][j-1],1,&value);
AWC=-*valuePtr;
max1_or_min2(CU[i][j],2,&value);
AEC=*valuePtr;
max1_or_min2(CV[i-1][j],1,&value);
ASC=-*valuePtr;
max1_or_min2(CV[i][j],2,&value);
ANC=*valuePtr;
}
if(ID==1)
{
AWC =-CU[i][j-1]*(1.0-FX[i][j-1]);
AEC =CU[i][j]*FX[i][j];
ASC =-CV[i-1][j]*(1.0-FY[i-1][j]);
ANC =CV[i][j]*FY[i][j];
}
// Set Coefficients matrix
AW[i][j] = AWD+AWC;
AE[i][j] = AED+AEC;
AS[i][j] = ASD+ASC;
AN[i][j] = AND+ANC;
AP[i][j] = -(AE[i][j]+AW[i][j]+AN[i][j]+AS[i][j]);
Q[i][j] = 0.0;
}
}
// West Boundary - Inlet B.C
for(i=1;i<(*factorteta_Ptr)*2+1;i++)
{
if(WBC==1) Q[i][1] = Q[i][1]-AW[i][1]*FI[i][0];
if(WBC==2) AP[i][1] = AP[i][1] + AW[i][1];
AW[i][1] = 0.0;
// East Boundary - (1)Dirichlet (2)ZERP-GRAD Outflow B.C
if(EBC==1) Q[i][*N_Ptr] = Q[i][*N_Ptr] - AE[i][*N_Ptr]*FI[i][*N_Ptr+1];
if(EBC==2) AP[i][*N_Ptr] = AP[i][*N_Ptr] + AE[i][*N_Ptr];
AE[i][*N_Ptr] = 0.0;
}
// South Boundary - (1)Dirichlet (2)ZERO-GRAD
for(j=1;j<*N_Ptr+1;j++)
{
if(SBC==1) Q[1][j] = Q[1][j] - AS[1][j]*FI[0][j];
if(SBC==2) AP[1][j] = AP[1][j] + AS[1][j];
AS[1][j] = 0.0;
// North Boundary - (1)Dirichlet (2)ZERO-GRAD
if(NBC==1) Q[(*factorteta_Ptr)*2][j] = Q[(*factorteta_Ptr)*2][j] - AN[(*factorteta_Ptr)*2][j]*FI[(*factorteta_Ptr)*2+1][j];
if(NBC==2) AP[(*factorteta_Ptr)*2][j] = AP[(*factorteta_Ptr)*2][j] + AN[(*factorteta_Ptr)*2][j];
AN[(*factorteta_Ptr)*2][j] = 0.0;
}
// Print
int l,k;
for(l=1;l<(*factorteta_Ptr)*2+1;l++)
{
for(k=1;k<*N_Ptr+1;k++)
{
printf("%lf %lf %lf %lf\n",AP[l][k],AS[l][k],AN[l][k],FI[l][k]);
}
}
return 0;
}
If anybody wants I can send all code, but have many extensions.
In your function declaration:
double AP[(*factorteta_Ptr)*2+1][*N_Ptr+1]
I don't quite think this is doing what you think it is doing. While I haven't seen something like this myself before, I believe that this is telling the compiler to create a variable length 2D array for you based on the other given parameters. Then, you fill in these values in your function. But, because you don't return this value nor do you declare it as pass by reference, it is thrown away when you return, thus the work is lost and you have garbage in your array in main(). Better form would be to create this array in main(), then pass it in by reference something like double *AP[][], or return this array upon exit, or hack things up even worse than this function and just make it a global so that you can see it anywhere.