2013-01-24 70 views
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 
+0

它如何崩潰?分段錯誤?如果是這樣,你是否嘗試通過'gdb'來查看哪條線導致崩潰? –

+0

什麼是錯誤,以及在哪一行?你也可能想讓你的變量名更有意義。 – OldProgrammer

+0

我目前正在使用Codeblocks,當我嘗試運行它時,它說file.exe已停止工作(如在Windows上沒有響應時)。 – user1988898

回答

1

所以我一直在盯着這一段時間。這是我想出的。間隔(我假設是100)。爲了理智,我將它更改爲5,後面的代碼是因爲您的示例發佈數據只有46個元素。我必須假設你的是很多大於這個。

需要注意以下幾點:

  • foo()不再依賴於一些怪誕的「我在哪裏我的計算平均」的變量。 調用者負責將元素的起始位置和數量傳遞給平均值。如您所見,這使得代碼更簡單。這基本上是問題的核心,因爲你的分配循環很好(除非沒有檢查你的realloc返回值)。沒有理由使該函數複雜化,試圖計算某個更大陣列中某處的平均值。把事情簡單化。只需要調用者告訴函數從哪裏開始以及要平均多少。

  • 雖然沒有指定,我相信z是你的「間隔」寬度。下面代碼中要注意的是間隔計數計算。間隔的數量僅爲(N+(z-1))/z,這將導致需要處理的間隔數量,包括最後一個間隔可能只是一個部分。從那裏開始,我們只需遍歷原始數組,在z大小的切片中進行分割,計算平均值,然後重寫剛纔用相同平均值平均的區間。最後的時間間隔也可以是局部的,這需要一點額外的注意。

  • 我將數據文件更改爲命令行參數argv[1]。讓我更容易測試。

當然希望這是你要找的。 Thx爲樂趣,並且不要忘記將此代碼中的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 
+0

非常感謝你。我只希望推動正確的方向,所以你給一個替代版本是太棒了。我明白你所擁有的大部分;我似乎有一個問題(編譯時)是檢查realloc的返回值。它似乎阻止我打印任何東西,而是返回1(這是在CodeBlocks上)。你有什麼想法,爲什麼這個?這是我沒有將它列入首位的原因之一,因爲我能夠在不存在的情況下打印輸出。 – user1988898

+0

return(1)表示EXIT_FAILURE,這不好。你在談論while循環中的'realloc()',對吧?不是最初的那個('malloc()')?哦,再次檢查代碼,我不小心在'if()'中與M進行比較。現在在發佈的代碼中。 – WhozCraig

+0

其實等一下。只是試了一遍,它的工作原理。 – user1988898

0

它不太可能sum+=b[i];將訪問數組b 0至N-1。

0

您已經爲函數的數組參數傳遞了10個用於浮點數的塊。在語句sum + = b [i]中,這裏b [i]不能確保你不是指向數組大小的索引,因爲你的「i」可能超過10當z = 100和t = 1時。

相關問題