1

最大サイズ50の固定長配列を使用します。入力ファイルに50人を超える学生が含まれている場合は、「ファイルに50人を超える学生が含まれています!」などのメッセージを出力します。プログラムを終了します。

これを追加する方法がわかりません。if / elseステートメントを使用して多くの方法を試しましたが、常にセグメンテーション11の問題が発生します。助けてください

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

#define MAX_SIZE 50

// Function declarations
void printInfo();
int readresults(FILE*,int*, int*, int*);
void sort(float avgScore[], int stuID[], int totalStu);
float calcAvg (int score1, int score2);
void getInfo(float avgScore[], int totalStu, float* min, float* max, float* avg);
void writeSortedResults (FILE* AG_Sorted, float avgScore[], int stuID[], int totalStu);
void printdone();

int main (void)
{
// Local Declarations
    FILE* AG_Midterm;
    FILE* AG_Sorted;

    int score1[MAX_SIZE];
    int score2[MAX_SIZE];
    int stuID[MAX_SIZE];
    int i = 0;
    int totalStu = 0;

    float avgScore[MAX_SIZE];
    float avg;
    float min;
    float max;

// Statements
    printInfo();

    AG_Midterm = fopen("/Users/r3spectak/Desktop/AG_Midterm.txt", "r");
    if(AG_Midterm == NULL)
    {
      printf("\aError opening Results File\n");

      return 100;

    } // if open input

    if(!(AG_Sorted = fopen ("/Users/r3spectak/Desktop/AG_Sorted.txt","w")))
    {
      printf("\aError opening Average Results file\n");
      return 102;
    }// if open input
    i = 0;


    while(readresults(AG_Midterm, &stuID[i], &score1[i], &score2[i]))//Kexy
        {
          avgScore[i] = calcAvg(score1[i], score2[i]);
            i++;//Kexy
            totalStu++;//Kexy


        } //while

    sort(avgScore, stuID, totalStu);//Kexy

    getInfo( avgScore, totalStu, &min, &max, &avg );
    printf( "\nHighest Average Score: %.2f\nLowest Average Score: %.2f\nClass Average Score : %.2f\n", max, min, avg );
    printf("Total Students: %d\n", totalStu);

    writeSortedResults(AG_Sorted, avgScore, stuID, totalStu);

    printf("Total Students: %d\n", totalStu);

    fclose(AG_Midterm);
    fclose(AG_Sorted);


    printdone();
    return 0;

} // main


/*==================printInfo==================================
    Reads data from Midterm file
    Pre : Nothing
    Post: Prints introduction message
*/

void printInfo()
{
// Statements
    printf("Begin Calculation of Scores\n");
    return ;

} // printInfo


/*===================readResults==================================
    Reads data from AG_Midterm file
    Pre : AG_Midterm is an open file.
          stuid, score1 , score2
    Post: reads score1 and score2
          if data read -- returns 1
          if EOF or error--returns 0
*/

int readresults(FILE* AG_Midterm, int * stuID, int *score1, int *score2)
{
// Local Variables
    int i;
    int items;
    int ioCheck;

// Statements
    ioCheck = fscanf(AG_Midterm, "%d%d%d",stuID, score1, score2);

    if(ioCheck == EOF)

    {
        return 0;
    }

    else if(ioCheck != 3)

    {
        printf("Error reading file...\n");
        return 0;
    }

    else

        return 1;

} //readresults

/*===================sort===================================
    Sorts by selecting the largest Average score in unsorted
    portion of array and exchanging it with element at the
    beginning of the unsorted list.=
    Pre : list must contain atleast one item
    Post: list rearranged largest to smallest

*/

void sort(float avgScore[], int stuID[], int totalStu)
{
// Local Declarations
    int i = 0;
    int j = 0;
    int largest;
    int tempID;

    float temp;

    for(i = 0; i < totalStu; i++)
    {
        largest = i;
        for(j = i + 1; j < totalStu; j++)
        {
            if(avgScore[j] > avgScore[largest])
                largest = j;

        }

        temp = avgScore[i];
        tempID = stuID[i];

        avgScore[i] = avgScore[largest];
        stuID[i] = stuID[largest];

        avgScore[largest] = temp;
        stuID[largest] = tempID;
   }
} // sort


/*===================calcAvg==================================
    Determines the Average of the two midterm scores
    Pre : score1, score2
    Post: avgScore copied to addresses

*/
float calcAvg (int score1, int score2)

{
    return (score1 + score2)/2.0;
} // calcAvg


/*===================getInfo==================================
    Determines the Class Average,Lowest Average
    and Highest Average scores
    Pre : avgScore , totalStu
    Post: avg , min , max

*/
void getInfo(float avgScore[], int totalStu, float* min, float* max, float* avg)
{
   int i;
   float sum = *min = *max = avgScore[0];

   for( i = 1; i <totalStu; ++i )
   {
        sum += avgScore[i]; /* sum = sum + dAry[i] */
        if( avgScore[i] < *min ) *min = avgScore[i]; /* update ... if applies */
        if( avgScore[i] > *max ) *max = avgScore[i];
    }
        *avg = sum/totalStu;
    return;
}

/*===================writeSortedResults==================================
    Writes Average Scores after Sorting
    Pre : AG_Sorted is an open file
          avgScore
    Post: Data written to file
*/
void writeSortedResults (FILE* AG_Sorted, float avgScore[], int stuID[], int totalStu)
{
// Local Definitions
    int i;
    int line = 0;

// Statements
    for(i = 0; i < totalStu; i++)
    {
        fprintf(AG_Sorted, "%d %.2f     ", stuID[i], avgScore[i]);
        line++;

        if(line == 8)
        {
            fprintf(AG_Sorted, "\n");
            line = 0;
        }

    }

    printf("\nSuccessfully write the sorted data to the new file\n");
    return;


} // writeSortedResults

/*==================printDone==================================
    Reads data from Midterm Score File
    Pre : Nothing
    Post: Prints end message
*/
void printdone()
{
// Statements
    printf("End of Finalizing Scores.Thank you.\n");
    return;

} // printDone
4

4 に答える 4

2

私があなたの意図を理解していれば、誰もが修正しているように見えるオーバーランを避けることに興味があるだけではありません。入力ファイルがオーバーランする場合は完全に中止しようとしていますが、実際にはオーバーランさずにプロセスをセグフォールトさせます。改行、空白、通常のレコードエントリではないfeof()ほとんどすべてのものがある可能性があるため、チェックしても何の役にも立ちません。feof()

目的の結果 (ファイルが大きすぎると中止) に対処するには、データをローカル変数に読み込むことができます。読んでいる間ではありません。それ以外の場合は中止します。

int id, s1, s2;
while(readresults(AG_Midterm, &id, &s1, &s2))//Kexy
{
    // we *know* we have a valid record. make sure it fits
    //  before dropping it in, otherwise proclaim the file too
    // large and abort the whole thing.
    if (i == MAX_SIZE)
    {
        printf("Too many scores. Aborting.\n");
        exit(EXIT_FAILURE);
    }

    stuID[i] = id;
    score1[i] = s1;
    score2[i] = s2;

    avgScore[i] = calcAvg(score1[i], score2[i]);
    i++;//Kexy
    totalStu++;//Kexy

} //while
于 2012-12-10T06:47:00.883 に答える
1

たぶん、あなたは最初にデータを読んで、それがあなたの限界を超えているかどうかをチェックします(あなたがそれをチェックする場所を一目見たことがなくても)。もちろん、最初にもう1つの要素を読み取ることができるかどうかを確認してから、それを読み取る必要があります。しばらくの間、例えば

 while(i < MAX_SIZE && readresults(AG_Midterm, &stuID[i], &score1[i], &score2[i]))

次に、ループが終了した理由を確認する必要があります。最初の条件が満たされた場合、i == MAX_SIZEであるため、しばらくするとすぐに確認できます。

if (i == MAX_SIZE) 
{
   // abort with error
}

さて、これはおそらくそれを行うためのより良い方法ではありませんが、あなたの問題を解決します。

于 2012-12-10T06:36:43.637 に答える
1

あなたの問題はこのループです:

while(readresults(AG_Midterm, &stuID[i], &score1[i], &score2[i]))//Kexy

ファイルの終わりまで読み取っています。これによりi、ファイルに50を超える要素が含まれていると、無効な配列インデックスになります。

whileステートメントに条件を追加して、次のiようにまだ範囲内にあるかどうかを確認します。

while(i < MAX_SIZE && ...)
于 2012-12-10T06:37:01.830 に答える
1

実際に要素を追加する前に、要素の現在の量と追加する量を確認して、その量が 50 を超えているかどうかを確認できます。

if ( sizeof ( array ) + newAmount ) > MAX_SIZE ) {
   // Error.
}
于 2012-12-10T06:34:37.263 に答える