I’m currently working on some code and, up to now, everything has compiled fine. The aim of the code is this:
- read input from data file and assign values to an array.
- “smooth the data” by taking average of the data on a given interval and replacing each value in that interval with the average.
It’s the second part that causing me trouble. In the external function, for some reason it works when my ‘for’ loop looks like this:
for(i=t; i<t+z; i++)
But I don’t want it to do that. I want it to do this:
for(i=t*z; i<(t+1)*z; i++)
When I try to compile, it just crashes out on me. Anyone know the reason why? It’s been puzzling me for hours now. All the code is shown below by the way:
#include <stdio.h>
#include <stdlib.h>
float foo(float*, int, int);
int main(int argc, char* argv[])
{
FILE *input;
const char datafile[]="datainput.dat";
input=fopen(datafile, "r");
int i;
int N=0, t=0;
int z=100;
int M=10;
float *a, avg;
a=(float*)malloc(M*sizeof(float));
if((input!=(FILE*) NULL))
{
while(fscanf(input, "%e", &a[t++])==1)
{
if (t>=M)
{
M*=2;
a=(float *)realloc(a, M*sizeof(float));
}
N++;
}
float u[N];
for(t=0; t<N; t++)
{
avg = foo(a, z, t);
u[t] = avg;
}
fclose(input);
}
else
printf("Input file could not be opened.\n");
return(0);
}
float foo(float b[], int z, int t)
{
int i;
int k=0;
float avg;
float sum=0;
for(i=t*z; i<(t+1)*z; i++)
{
sum+=b[i];
k++;
}
avg = sum/(float)k;
return(avg);
}
side note: you’ll probably notice the poor practise of defining float u[N] half way down the code. I don’t really like this being there, but you’ll note that N is a variable that counts the number of values in the input file (initially unknown) and is initally set to N=0, so I’m not sure how I get around that.
additionally, I asked the question earlier on here but my realloc has no clause if it fails. it’s something i’m working on though but at the moment it compiles without it being there.
Also, all the data values are of the form float with seven decimal places and in scientific notation, hence the %e.
Thank you!
EDIT: here are some of the values from the data file. Even though the values on the left look ordered, they are actual values in the file and not there to denote the values on the right.
8.0800000e+00 7.0872796e-01
8.0900000e+00 7.1941101e-01
8.1000000e+00 2.1635408e+00
8.1100000e+00 -5.4200807e-01
8.1200000e+00 1.1046968e+00
8.1300000e+00 1.5833782e+00
8.1400000e+00 6.6122899e-01
8.1500000e+00 1.7922273e+00
8.1600000e+00 1.2446803e+00
8.1700000e+00 3.7869871e-01
8.1800000e+00 1.4793635e+00
8.1900000e+00 1.0508171e+00
8.2000000e+00 9.1012735e-01
8.2100000e+00 6.0967729e-01
8.2200000e+00 1.3834455e+00
8.2300000e+00 -5.2312924e-01
8.2400000e+00 9.2566688e-01
8.2500000e+00 7.8145188e-01
8.2600000e+00 4.1410150e-01
8.2700000e+00 1.9796986e+00
8.2800000e+00 5.9372874e-01
8.2900000e+00 1.8696331e+00
8.3000000e+00 2.3058409e+00
So I’ve been staring at this for awhile. This is what I came up with. The interval (i’m assuming is 100). for the sake of sanity I’ve changed it to
5in the code that follows because your sample posted data is only 46 elements long. I must assume yours is much larger than this.Some things to note:
foo()no longer relies on some whacky ‘where do I compute my average’ variables. The caller is responsible for passing the starting location and count of elements to average. This, as you will see, makes that code much simpler. This was fundamentally the heart of the problem to begin with, as your allocation loop was fine (save for not checking yourreallocreturn value). There is no reason to complicate that function to try and compute an average somewhere in the middle of some larger array. Keep it simple. Just have the caller tell the function where to start and how many to average.Though it wasn’t specified, I believe
zis your “interval” width. The thing to note in the code below is the interval-count calculation. The number of intervals is simply(N+(z-1))/z, which will result in the number of intervals to process, including the last interval which may only be a partial. From there, we simply walk through the original array, partitioning up inz-sized slices, calculating the average, then rewriting the interval we just averaged with the said-same average. The last interval, again, can be a partial, which requires a little bit of extra care.I changed the data file to be a command line parameter
argv[1]. Made it easier for me to test.Sure hope this is what you were looking for. Thx for the fun, and don’t forget to reset the
zvalue in this code back to 100 if you plan on using it.Output (z=5)
Output (z=10)