Последний элемент, добавленный в массив, добавляется дважды, не в состоянии понять, почему

0

Реализация: Wow потратил так много времени, глядя на этот код. Наконец я заметил то, что я пропустил. Я инициализирую я = размер, что означает, что в начале массив смотрит на незаполненное место, поэтому я, наконец, понимаю, почему он всегда повторяет. Теперь попытаемся исправить это. Не стесняйтесь меня бить.

Я просматриваю массив назад, потому что я использую алгоритм сортировки вставки, поэтому я работаю назад от последнего известного элемента для алфавита данных. Однако независимо от того, какая конечная строка в файле данных (из которого я читаю), она всегда повторяется дважды. Вот массив, напечатанный для демонстрации повтора:

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, тогда дерьмо уйдет. Вот функция, о которой идет речь, я не верю, что какой-либо код вне релевантен, поэтому я не включил его:

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
Теги:
arrays
insertion-sort

2 ответа

1
Лучший ответ

Вы можете объединить извлечение потока и проверить состояние потока, изменив:

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

в

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

Это прочитает поток и завершит неудачу (вернет false), если чтение по какой-либо причине завершится, включая EOF.

Примечание: прочитайте этот связанный вопрос для получения более подробного объяснения.

1

Индикатор конца файла устанавливается не тогда, когда последний байт файла считывается, но когда делается попытка прочитать следующий байт, байт, который не существует.

Таким образом, после того, как прочитана последняя строка, в while(infile) проверка по-прежнему выполняется успешно, но вызов infile >> temp.last завершается с ошибкой, оставляя переменную неповрежденной. Вы не проверяете этот отказ, поэтому вы запускаете одну дополнительную итерацию цикла, используя значения, считанные предыдущей итерацией.

  • 0
    Да. Сначала вы пытаетесь прочитать, а затем проверьте, удалось ли прочитать. Вы не можете заранее проверить, удастся ли в будущем прочитать, что в основном пытается сделать ваш текущий код.
  • 0
    Удалил предыдущий комментарий, потому что я его обманул ... хе-хе. Как бы я правильно проверил, чтобы этот звонок был успешным? Если я использую ifstream.good () в качестве условия для этого оператора if, то он просто полностью пропускает последний элемент, а не повторяет его. То же самое происходит, если я использую '! Ifstream.eof ()'
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню