添加到数组的最后一个元素正在添加两次,无法弄清楚原因

时间:2013-10-07 02:09:16

标签: c++ arrays insertion-sort

实现:哇花了这么多时间盯着这段代码我终于发现了一直以来我一直在想的东西。我初始化i = size这意味着在开始时阵列正在查看未填充的位置,所以我终于理解为什么它总是重复。现在尝试解决它。随意骂我。

我正在向后查看数组,因为我正在使用插入排序算法,因此我从最后一个已知元素向后工作以按字母顺序排列数据。但无论数据文件中的最后一行(我正在阅读),它总是重复两次。这是打印的数组内容,用于演示重复:

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

请注意,帐单门名列出两次。问题似乎与我循环的方式有关。如果我将循环中的下限修改为1而不是0,则shit会变得混乱。这是有问题的函数,我不相信外面的任何代码是相关的,所以我没有包含它:

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

2 个答案:

答案 0 :(得分:1)

文件结束指示符不是在读取文件的最后一个字节时设置的,而是在尝试读取下一个字节时设置的,该字节不存在。

因此,在读取最后一行之后,while(infile)检查仍然成功,但infile >> temp.last调用失败,保持变量不变。您不检查该失败,因此您使用上一次迭代读取的值运行一次额外的循环迭代。

答案 1 :(得分:1)

您可以通过更改以下内容来组合流提取和测试流状态:

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

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

如果因任何原因(包括EOF)读取失败,这将读取流并失败(返回false)。

注意:请阅读this related question以获取更多说明。