1

私は現在いくつかのコードに取り組んでおり、これまではすべてが正常にコンパイルされています。コードの目的は次のとおりです。

  • データファイルから入力を読み取り、配列に値を割り当てます。
  • 特定の間隔のデータの平均を取り、その間隔の各値を平均に置き換えることにより、「データを平滑化」します。

それは私に問題を引き起こしている2番目の部分です。外部関数では、何らかの理由で、「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);
}

補足:コードの途中でfloatu[N]を定義するという不適切な方法に気付くでしょう。これが存在するのはあまり好きではありませんが、Nは入力ファイル(最初は不明)の値の数をカウントする変数であり、最初はN = 0に設定されているため、方法がわかりません。私はそれを回避します。

さらに、ここで先に質問しましたが、失敗した場合、reallocには句がありません。それは私が取り組んでいるものですが、現時点ではそこになくてもコンパイルされます。

また、すべてのデータ値は、小数点以下7桁の浮動小数点形式であり、科学的記数法であるため、%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サイズのスライスに分割して平均を計算し、平均した間隔を同じ平均で書き換えます。最後の間隔も部分的である可能性があり、少し特別な注意が必要です。

  • データファイルをコマンドラインパラメータに変更しましたargv[1]。テストが簡単になりました。

これがあなたが探していたものであることを願っています。楽しみのためにThx、そしてそれを使用することを計画しているなら、このコードの値を100にリセットすることを忘れないでください。z

#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

関数の配列パラメーターとして渡されるfloatに10ブロックを割り当てました。ステートメントsum+= b [i]では、ここでb [i]は、配列サイズの外側のインデックスで参照していないことを保証しません。たとえば、z=100およびt=の場合に10を超える可能性がある「i」があるためです。 1.1。

于 2013-01-24T06:24:24.423 に答える