0

C の関数に配列を渡す際に問題があります。メインで配列を宣言しています。

そして、関数内に入力します。

その時点で、関数を離れ、プロトタイプを使用して配列を別の関数に渡します

そして、配列へのアクセスを試みます。

ただし、配列にデータを入力した最初の関数を終了すると、配列にアクセスできなくなります。0.00000 と nan の値を返すだけです。

void ReadData(FILE *fpIn, int lines, double *pA );
void MinMaxAvg(double *pA, double *min, double *max, double *avg, int lines);

int main()
{
    FILE *fpIn = NULL;

    int lines = 0;

    double *pA = NULL;

    ReadData(fpIn, lines, pA);

    double min = 0;
    double max = 0;
    double avg = 0;

    MinMaxAvg(pA, &min, &max, &avg, lines);

    printf("%lf %s %lf %s %lf \n", avg, " ", min, " ", max);

    return 0;
}   

void ReadData(FILE *fpIn, int lines, double *pA )
{
    char fName[20];
    scanf( "%s", fName);

    fpIn = fopen ( fName, "rt");
// fpIn = fopen( "test1.txt", "rt");

    if ( fpIn == NULL)
    {
        printf( "Unable to open: ");
        exit(99);
    }

//Gets Lines

//int lines=0;
    char ch;

    while((ch=fgetc(fpIn))!=EOF)
    {
        if (ch=='\n') { lines++; }

    }

// clearerr(fName *fpIn);
    fclose(fpIn);
    fopen(fName, "rt");

//Makes Array

//double *pA;

    pA = (double *)malloc(lines*sizeof(double));

//Fills Array

    for (int i=0; i<lines; i++)
    {
        fscanf(fpIn, "%lf", &pA[i]);
    }

    for (int i=0; i<lines; i++)
    {
        printf("%lf \n", pA[i]);
    }
}

void MinMaxAvg(double *pA, double *min, double *max, double *avg, int lines)
{
    double total = 0;

    for (int i=0; i<lines; i++)
    {
        if ( i==0)
        {
            *min = pA[0];
            *max = pA[0];
        }
        else
        {
            if (pA[i] < *min)
            {
                *min = pA[i];
            }

            if (pA[i] > *max)
            {
                *max = pA[i];
            }
        }

        total += pA[i];

    }

    *avg = (total / (double)lines);

}

助言がありますか?

ありがとう!

4

3 に答える 3

3

関数 ReadData() でローカル変数「lines」にファイル内の行数をカウントしましたが、これは main に戻されるという意味ではありません。MinMaxAvg() に渡される「lines」変数値はゼロです。

于 2013-02-07T15:05:47.017 に答える
0

あなたのコードをテストしたところ、動作します。私が行った唯一の違いは、fscanf の stdin であり、max、min、avg、および lines が含まれています。

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


void MinMaxAvg(double *pA, double *min, double *max, double *avg, int lines)
{
    double total = 0;

    for (int i=0; i<lines; i++)
    {
    if ( i==0)
    {
        *min = pA[0];
        *max = pA[0];
    }
    else
    {
        if (pA[i] < *min)
        {
        *min = pA[i];
        }

        if (pA[i] > *max)
        {
        *max = pA[i];
        }
    }

    total += pA[i];

    }

    *avg = (total / (double)lines);

return;
}



int main(int argc, char** argv)
{
    double *pA = NULL;

    int lines = 3;

    double min,max,avg;

    pA = (double *)malloc(lines*sizeof(double));

    //Fills Array

    for (int i=0; i<lines; i++)
    {
        fscanf(stdin, "%lf", &pA[i]);
    }

     MinMaxAvg( pA, &min, &max, &avg,  lines);


    for (int i=0; i<lines; i++)
    {
        printf("%lf \n", pA[i]);
    }

    printf( "min: %f  max: %f  avg: %f" , min , max , avg );
}
于 2013-02-07T14:56:50.193 に答える
-1

質問の内容に基づいて、関数にpAを入力している場合、pAの内容を変更していないと思われますが、これが問題になる可能性があります。pA の入力に使用しているルーチンを確認すると役立つ場合があります。

C関数は値で呼び出すので、ポインター(pAのみ)を渡すだけで、ポインターの値を変更するには、ポインターのアドレス(必要に応じてポインターへのポインター)を渡す必要があります。次に、(ポインターへの) ポインターを設定するために 1 回参照し、割り当てられたメモリ/配列に値を設定するために 2 回参照する必要があります。

したがって、関数の呼び出しは

void init(File *fpin, double **pA, int lines)
{
  /* Deference once to set the pointer to the pitner */
  *pA = (double *)malloc(lines*sizeof(double));

  for (int i=0; i<lines; i++)
  {
     /* deference twice to set the the element of the pointer to the pointer */
     fscanf(fpIn, "%lf", &(**pA)[i]);
  }
}

次に、ルーチンを呼び出すときに、pA のアドレスを渡す必要があります。

init(fpIn,&pA,lines);

ポインターからポインターへのポインターを説明するのに役立つリンクは次のとおりです

ポインタへのポインタを作成してから長い時間が経ちましたが、上記を使用する場合は、いくつかのマイナーな変更を加える必要がある場合があります。

larsmans がほのめかしているように、ルーチンを変更して、割り当てたメモリへのポインターを返し、その値を pA に配置するという彼の提案が気に入っています。

double* init(File *fpin, int lines)
{
  double *local = (double *)malloc(lines*sizeof(double));

  //Fills Array

  for (int i=0; i<lines; i++)
  {
    fscanf(fpIn, "%lf", &local[i]);
  }

  return(local);

}

そしてinitへの呼び出しで

pA = init(fpIn,lines);

何を達成しようとしているのかによって、これは理解しやすく、それほど複雑ではない場合があります。

于 2013-02-07T15:11:37.640 に答える