0

実現: このコードを見つめるのに非常に多くの時間を費やしました。i = size を初期化します。これは、最初に配列が塗りつぶされていない場所を見ていることを意味するため、常に繰り返しを置く理由が最終的にわかりました。今、それを修正しようとしています。お気軽に私を怒らせてください。

挿入ソートアルゴリズムを使用しているため、配列を逆方向に調べているため、最後の既知の要素から逆方向に作業してデータをアルファベット順に並べています。ただし、データ ファイル (私が読んでいる) の最終行が何であっても、常に 2 回繰り返されます。繰り返しを示すために印刷された配列の内容を次に示します。

List of names sorted:
 100 bill gates
 100 bill gates
 65 duck donald
 60 frog freddie
 71 ghost casper
 85 mouse abby
 73 mouse mickey
 95 mouse minnie

ビル ゲートが 2 回表示されていることに注意してください。問題は、私がループしている方法にあるようです。ループの下限を 0 ではなく 1 に変更すると、大変なことになります。問題の関数は次のとおりです。外部のコードはどれも関連性があるとは思わないため、含めませんでした。

bool sortInput(ifstream &infile, StudentType students[], int &size)
{
   StudentType temp;

   //empty condition
   if(size == 0)
   {
      infile >> temp.last >> temp.first >> temp.grade;
      strcpy(students[0].last, temp.last);
      strcpy(students[0].first, temp.first);
      students[0].grade = temp.grade;
      size++;
   } 

   while(infile)
   {
      infile >> temp.last >> temp.first >> temp.grade;

      if(temp.grade >= LOWGRADE && temp.grade <= MAXGRADE)
      {            
         for(int i = size; i > 0; i--)
         {       
            if(strcmp(temp.last, students[i-1].last) < 0)
            {
               students[i] = students[i-1];
               students[i-1] = temp;
            }
            else if(strcmp(temp.last, students[i-1].last) == 0 && strcmp(temp.first, students[i-1].first) < 0)
            {
               students[i] = students[i-1];
               students[i-1] = temp;
            }
            else
            {
               students[i] = temp;
               break;
            }
         }

         size++;

         //tester loop to print contents every step of the way
         for(int i = 0; i < size; i++)
         {
            cout << "TEST: " << students[i].last << " " << students[i].first << " " << students[i].grade << endl;
         }
         cout << "DONE" << endl;

      } //end for loop  
   } //end while loop

   return true;
}

ただし、詳細なコンテキストのために完全なコードが必要な場合は、次のとおりです。

// ----------------------------------------------------------------------------
// You write meaningful doxygen comments and assumptions

#include <string.h>
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;

int const MAXSIZE = 100;            // maximum number of records in total
int const MAXLENGTH = 31;           // maximum string length 
int const MAXGRADE = 100;           // highest possible grade
int const LOWGRADE = 0;             // lowest possible grade
int const GROUP = 10;               // group amount
int const HISTOGRAMSIZE = (MAXGRADE-LOWGRADE)/GROUP + 1;    // grouped by GROUP

struct StudentType  {               // information of one student
   int grade;                       // the grade of the student
   char last[MAXLENGTH];            // last name (MAXLENGTH-1 at most)
   char first[MAXLENGTH];           // first name (MAXLENGTH-1 at most)
};

// prototypes go here
bool sortInput(ifstream &, StudentType [], int &);
void displayList(StudentType [], int);
void setHistogram(int [], StudentType [], int);
void displayHistogram(int []);
int findAverage(StudentType [], int);

//------------------------------- main ----------------------------------------
int main()  {
   StudentType students[MAXSIZE];   // list of MAXSIZE number of students
   int size = 0;                    // total number of students
   int histogram[HISTOGRAMSIZE];    // grades grouped by GROUP
   int average = 0;                 // average exam score, truncated

   // creates file object and opens the data file
   ifstream infile("data1.txt");
   if (!infile)  { 
      cout << "File could not be opened." << endl; 
      return 1;  
   }

   // read and sort input by last then first name
   bool successfulRead = sortInput(infile, students, size);              

   // display list, histogram, and class average 
   if (successfulRead)  {
      displayList(students, size);
      setHistogram(histogram, students, size);
      displayHistogram(histogram);
      average = findAverage(students, size);
      cout << "Average grade: " << average << endl << endl;
   }
   return 0;
}

bool sortInput(ifstream &infile, StudentType students[], int &size)
{
   StudentType temp;

   //empty condition
   if(size == 0)
   {
      infile >> temp.last >> temp.first >> temp.grade;
      strcpy(students[0].last, temp.last);
      strcpy(students[0].first, temp.first);
      students[0].grade = temp.grade;
      size++;
   } 

   while(infile)
   {
      infile >> temp.last >> temp.first >> temp.grade;

      if(temp.grade >= LOWGRADE && temp.grade <= MAXGRADE)
      {            
         for(int i = size; i > 0; i--)
         {       
            if(strcmp(temp.last, students[i-1].last) < 0)
            {
               students[i] = students[i-1];
               students[i-1] = temp;
            }
            else if(strcmp(temp.last, students[i-1].last) == 0 && strcmp(temp.first, students[i-1].first) < 0)
            {
               students[i] = students[i-1];
               students[i-1] = temp;
            }
            else
            {
               students[i] = temp;
               break;
            }
         }

         size++;

         for(int i = 0; i < size; i++)
         {
            cout << "TEST: " << students[i].last << " " << students[i].first << " " << students[i].grade << endl;
         }
         cout << "DONE" << endl;

      } //end for loop  
   } //end while loop

   return true;
}

void displayList(StudentType students[], int size)
{
   cout << "List of names sorted:" << endl;

   for(int i = 0; i < size; i++)
   {
      cout << " " << students[i].grade << " " << students[i].last << " " << students[i].first << endl;
   }

   cout << endl;
}

void setHistogram(int histogram[], StudentType students[], int size)
{
   int groupIndex;

   for(int i = 0; i < size; i++)
   {
      groupIndex = (students[i].grade - LOWGRADE) / GROUP;
      histogram[groupIndex]++;
   }
}

void displayHistogram(int histogram[])
{
   cout << "Histogram of grades: " << endl;
   int bottomBin = LOWGRADE;
   int binWidth = (MAXGRADE - LOWGRADE) / GROUP - 1;
   int topBin = bottomBin + binWidth;

   for(int i = 0; i < HISTOGRAMSIZE; i++)
   {
      cout << bottomBin << "--> " << topBin << ": ";

      for(int j = 0; j < histogram[i]; j++)
      {
         cout << "*";
      }

      cout << endl;
      bottomBin += binWidth + 1;
      topBin = min(topBin + binWidth + 1, MAXGRADE);
   }
}

int findAverage(StudentType students[], int size)
{
   int total = 0;

   for(int i = 0; i < size; i++)
   {
      total += students[i].grade;
   }

   return total / size;
}

// ----------------------------------------------------------------------------
// functions with meaningful doxygen comments and assumptions go here
4

2 に答える 2

1

以下を変更することで、ストリームの抽出とストリームの状態のテストを組み合わせることができます。

while(infile)
{
    infile >> temp.last >> temp.first >> temp.grade;
    ...
}

while(infile >> temp.last >> temp.first >> temp.grade)
{
   ...
}

これはストリームを読み取り、EOF を含む何らかの理由で読み取りが失敗した場合は失敗します (false を返します)。

注:詳細については、この関連する質問をお読みください。

于 2013-10-07T02:30:23.937 に答える
1

ファイルの最後のバイトが読み取られたときではなく、次のバイト (存在しないバイト) を読み取ろうとしたときに、ファイルの終わり標識が設定されます。

したがって、最後の行が読み取られた後while(infile)でもチェックは成功infile >> temp.lastしますが、呼び出しは失敗し、変数はそのまま残ります。その失敗をチェックしないので、前の繰り返しで読み取った値を使用して、ループの追加の繰り返しを 1 回実行します。

于 2013-10-07T02:16:39.077 に答える