外部功能不起作用 - 但不确定原因

时间:2013-01-24 03:22:35

标签: c

我目前正在处理一些代码,到目前为止,一切都已编译好了。代码的目的是:

  • 从数据文件中读取输入并将值赋给数组。
  • "平滑数据"通过获取给定间隔的平均数据并用该平均值替换该区间中的每个值。

这是导致我麻烦的第二部分。在外部功能中,出于某种原因,它适用于我的'' for'循环看起来像这样:

for(i=t; i<t+z; i++)

但我不想让它这样做。我希望它能做到这一点:

for(i=t*z; i<(t+1)*z; i++)

当我尝试编译时,它只是崩溃了我。谁知道原因?几个小时以来我一直困扰着我。所有代码如下所示:

#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);
}

旁注:您可能会注意到在代码中间定义浮动u [N]的不良做法。我不是很喜欢这里,但你会注意到N是一个变量,它计算输入文件中的值的数量(最初是未知的),并且最初设置为N = 0,所以我&# 39;我不确定如何解决这个问题。

另外,我先前在这里问过这个问题,但如果失败,我的realloc没有条款。它是我正在努力的东西,但目前它在没有它存在的情况下进行编译。

此外,所有数据值都是float形式,带有七位小数,并且采用科学计数法,因此为%e。

谢谢!


编辑:这是数据文件中的一些值。即使左侧的值看起来是有序的,它们也是文件中的实际值,而不是表示右侧的值。

   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

3 个答案:

答案 0 :(得分:1)

所以我一直盯着这个。这就是我提出的。间隔(我假设是100)。为了理智,我在后面的代码中将其更改为5,因为您的样本发布数据只有46个元素长。我必须假设你的大于此。

有些注意事项:

  • foo()不再依赖于“我在哪里计算平均值”变量。 调用者负责将起始位置和元素数量传递给平均值。正如您将看到的,这使得代码更多更简单。这基本上是问题的核心,因为你的分配循环很好(除了没有检查你的realloc返回值)。没有理由使该函数复杂化以尝试在某个较大数组的中间某处计算平均值。把事情简单化。只需让调用者告诉函数从哪里开始以及要平均多少。

  • 虽然未指定,但我认为z是您的“间隔”宽度。下面的代码中要注意的是间隔计数计算。间隔的数量只是(N+(z-1))/z,这将导致要处理的间隔数,包括最后一个可能只是部分间隔的间隔。从那里,我们简单地遍历原始数组,在z大小的切片中进行分区,计算平均值,然后重写我们刚刚用所述相同平均值求平均的区间。最后一个间隔也可以是部分间隔,这需要一点额外的照顾。

  • 我将数据文件更改为命令行参数argv[1]。让我更容易测试。

当然希望这是你想要的。感兴趣的是,如果你打算使用它,不要忘记将此代码中的z值重置为100。

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

float foo(float a[], int count);

int main(int argc, char* argv[])
{
    if (argc !=2)
        return EXIT_FAILURE;

    FILE *input=fopen(argv[1], "r");
    if (input != NULL)
    {
        int z=5,t=0;
        int M=10,N=0;
        float *a = malloc(M*sizeof(float));

        while(fscanf(input, " %e", a + N) ==1 )
        {
            if (++N>=M)
            {
                void *tmp = realloc(a, (M*=2)*sizeof(float));
                if (tmp != NULL)
                {
                    a = tmp;
                }
                else
                {
                    perror("Failed to allocate memory.");
                    exit(EXIT_FAILURE);
                }
            }
        }

        // compute number of intervals we will process. the last
        //  interval may be only a partial.
        for (t=0;t<N;t+=z)
        {
            // how many we're doing in this interval
            int count = (z < (N-t) ? z : (N-t)), k=0;
            float avg =  foo(a+t, count);
            printf("Avg[%d] = %e\n", t/z, avg);

            // smooth over original array with just-found svg.
            for (k=0;k<count; a[t+k++] = avg);
        }
        fclose(input);

        // dump the final array content
        for (t=0;t<N;++t)
            printf("a[%d] = %e\n", t, a[t]);

        // release original array.
        free(a);
    }
    else
    {
        perror("Input file could not be opened.");
    }

    return(0);
}
// find the average of the range of floats we're given.
float foo(float a[], int count)
{
    float sum = 0;
    int i = 0;

    for(i=0; i<count; sum += a[i++]);
    return (sum)/(float)(count);
}

输出(z = 5)

Avg[0] = 5.139628e+00
Avg[1] = 3.791246e+00
Avg[2] = 5.332921e+00
Avg[3] = 3.949121e+00
Avg[4] = 5.420036e+00
Avg[5] = 3.866650e+00
Avg[6] = 5.024508e+00
Avg[7] = 3.941051e+00
Avg[8] = 5.466672e+00
Avg[9] = 2.305841e+00
a[0] = 5.139628e+00
a[1] = 5.139628e+00
a[2] = 5.139628e+00
a[3] = 5.139628e+00
a[4] = 5.139628e+00
a[5] = 3.791246e+00
a[6] = 3.791246e+00
a[7] = 3.791246e+00
a[8] = 3.791246e+00
a[9] = 3.791246e+00
a[10] = 5.332921e+00
a[11] = 5.332921e+00
a[12] = 5.332921e+00
a[13] = 5.332921e+00
a[14] = 5.332921e+00
a[15] = 3.949121e+00
a[16] = 3.949121e+00
a[17] = 3.949121e+00
a[18] = 3.949121e+00
a[19] = 3.949121e+00
a[20] = 5.420036e+00
a[21] = 5.420036e+00
a[22] = 5.420036e+00
a[23] = 5.420036e+00
a[24] = 5.420036e+00
a[25] = 3.866650e+00
a[26] = 3.866650e+00
a[27] = 3.866650e+00
a[28] = 3.866650e+00
a[29] = 3.866650e+00
a[30] = 5.024508e+00
a[31] = 5.024508e+00
a[32] = 5.024508e+00
a[33] = 5.024508e+00
a[34] = 5.024508e+00
a[35] = 3.941051e+00
a[36] = 3.941051e+00
a[37] = 3.941051e+00
a[38] = 3.941051e+00
a[39] = 3.941051e+00
a[40] = 5.466672e+00
a[41] = 5.466672e+00
a[42] = 5.466672e+00
a[43] = 5.466672e+00
a[44] = 5.466672e+00
a[45] = 2.305841e+00

输出(z = 10)

Avg[0] = 4.465437e+00
Avg[1] = 4.641021e+00
Avg[2] = 4.643343e+00
Avg[3] = 4.482779e+00
Avg[4] = 4.939867e+00
a[0] = 4.465437e+00
a[1] = 4.465437e+00
a[2] = 4.465437e+00
a[3] = 4.465437e+00
a[4] = 4.465437e+00
a[5] = 4.465437e+00
a[6] = 4.465437e+00
a[7] = 4.465437e+00
a[8] = 4.465437e+00
a[9] = 4.465437e+00
a[10] = 4.641021e+00
a[11] = 4.641021e+00
a[12] = 4.641021e+00
a[13] = 4.641021e+00
a[14] = 4.641021e+00
a[15] = 4.641021e+00
a[16] = 4.641021e+00
a[17] = 4.641021e+00
a[18] = 4.641021e+00
a[19] = 4.641021e+00
a[20] = 4.643343e+00
a[21] = 4.643343e+00
a[22] = 4.643343e+00
a[23] = 4.643343e+00
a[24] = 4.643343e+00
a[25] = 4.643343e+00
a[26] = 4.643343e+00
a[27] = 4.643343e+00
a[28] = 4.643343e+00
a[29] = 4.643343e+00
a[30] = 4.482779e+00
a[31] = 4.482779e+00
a[32] = 4.482779e+00
a[33] = 4.482779e+00
a[34] = 4.482779e+00
a[35] = 4.482779e+00
a[36] = 4.482779e+00
a[37] = 4.482779e+00
a[38] = 4.482779e+00
a[39] = 4.482779e+00
a[40] = 4.939867e+00
a[41] = 4.939867e+00
a[42] = 4.939867e+00
a[43] = 4.939867e+00
a[44] = 4.939867e+00
a[45] = 4.939867e+00

答案 1 :(得分:0)

sum+=b[i];不太可能在0和N-1之间访问数组b。

答案 2 :(得分:0)

你为浮点数分配了10个块,它作为函数的数组参数传递。在语句sum + = b [i]中,这里b [i]不能确保你没有在数组大小的索引外引用,因为你有“i”,它可以超过10,例如当z = 100且t = 1时。