1

我目前正在编写一些代码,到目前为止,一切都编译得很好。代码的目的是这样的:

  • 从数据文件中读取输入并将值分配给数组。
  • 通过对给定间隔内的数据取平均值并将该间隔中的每个值替换为平均值来“平滑数据”。

这是给我带来麻烦的第二部分。在外部函数中,由于某种原因,当我的“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);
}

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

另外,我之前在这里问过这个问题,但是如果我的 realloc 失败了,它就没有子句。这是我正在做的事情,但目前它在没有它的情况下编译。

此外,所有数据值的形式都是浮点数,有七位小数,采用科学计数法,因此是 %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
4

3 回答 3

1

所以我一直盯着这个看了一段时间。这就是我想出的。间隔(我假设是100)。为了理智起见,我5在下面的代码中将其更改为,因为您发布的示例数据只有 46 个元素长。我必须假设你的比这大得多

需要注意的一些事项:

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

  • 虽然没有指定,但我相信z是你的“间隔”宽度。下面代码中要注意的是间隔计数计算。间隔数是简单的(N+(z-1))/z,这将导致要处理的间隔数,包括可能只是部分的最后一个间隔。从那里,我们简单地遍历原始数组,分割成z-size 的切片,计算平均值,然后用上述相同的平均值重写我们刚刚平均的间隔。同样,最后一个间隔可能是部分的,这需要一点额外的照顾。

  • 我将数据文件更改为命令行参数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
于 2013-01-24T06:08:47.187 回答
0

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

于 2013-01-24T06:21:21.747 回答
0

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

于 2013-01-24T06:24:24.423 回答