Frage

Preface: Guidelines set by professor, I must use the array, not some other data structure. His psuedo code (which isn't very concise) of the method we should be following:

name and grade are read into a temporary location
loop from the end of the filled part of the array down to beginning {
if (new last name < current last name) {
   copy current name and grade down
}
else if (new/current last names are equal and new first name < current first name) {
   copy/assign current name and grade down
}
else {
   found right place, break out of loop
}
}
now that you've made room, insert (copy) new name into correct sorted position

I see that I'm probably breaking array bounds by attempting to read array position [-1] but I can't think of a way to avoid that since I'm counting backwards from the number of items I have and have to compare them.

I'm reading lines from a text file and storing pieces of each line into a struct. Then I'm using an insertion-sort-esque algorithm to store the structs in alphabetical order. However, my array does not seem to populate past the first couple lines with the new lines simply overwriting the previous lines... It's as if one of my comparison tests is failing since my copy position never appears to change although that could be because the initial array populating is failing in some way. I feel foolish, I must be missing something simple... Also my DisplayList module apparently never gets an array that's been populated with anything. Am I altering the array in an incorrect manner?

Here is the module with the problem:

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

   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;
      //cout << "TEST" << temp.last << temp.first << temp.grade << endl;

      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].last) == 0 && strcmp(temp.first, students[i].first) < 0)
         {
            students[i] = students[i-1];
         }
         else
         {
            break;
         }

         copyToHere = i;
      }

      cout << "Size = " << size << " and copy position = " << copyToHere << endl;
      students[copyToHere] = temp;
      size++;

      //test to see if array is populated properly
      for(int i = 0; i < size; i++)
      {
         cout << "Name is " << students[i].first << " " << students[i].last << " and grade is " << students[i].grade << endl;
      }

      cout << "DONE" << endl;

   } //end while loop

   return true;
}

Here is the full code (if necessary for whatever reason or further context):

// ----------------------------------------------------------------------------
// 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);
/*setHistrogram();
displayHistogram();
findAverage();*/

//------------------------------- 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(... you figure parameters ...);
     // displayHistogram(... you figure parameters ...);
     // average = findAverage(... you figure parameters ...);
      cout << "Average grade: " << average << endl << endl;
   }
   return 0;
}

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

   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;
      //cout << "TEST" << temp.last << temp.first << temp.grade << endl;

      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].last) == 0 && strcmp(temp.first, students[i].first) < 0)
         {
            students[i] = students[i-1];
         }
         else
         {
            break;
         }

         copyToHere = i;
      }

      cout << "Size = " << size << " and copy position = " << copyToHere << endl;
      students[copyToHere] = temp;
      size++;

      //test to see if array is populated properly
      for(int i = 0; i < size; i++)
      {
         cout << "Name is " << students[i].first << " " << students[i].last << " and grade is " << students[i].grade << endl;
      }

      cout << "DONE" << endl;

   } //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;
   }
}

// ----------------------------------------------------------------------------
// functions with meaningful doxygen comments and assumptions go here
War es hilfreich?

Lösung

Your insertion sort isn't really inserting properly. Let's look at one part of your main insertion loop:

   if(strcmp(temp.last, students[i-1].last) < 0)
     {
        students[i] = students[i-1];
        students[i-1] = temp;
     }

The intention of this is obviously to insert temp into the array at position i-1. You're shifting the item at i-1 to i but what happened to the other elements in the array? You need to move them all up one position to make room for the inserted element. Something like:

memmove(students + i, students + i - 1, sizeof(students[0]) * size - i - 1);

You have other problems in your code too. copyToHere is potentially uninitialized. You are copying temp into the array multiple times (students[i-1] = temp; and students[copyToHere] = temp; aren't both needed). Once you have done the insertion in the inner loop you should break out. Your special handling for when the list is empty isn't really necessary, and so on.

Have a look at the pseudo-code for an insertion sort algorithm and see if you can simplify and rewrite yours to eliminate the problems.

Andere Tipps

Solution to my own problem haha. I was stupid for not having completed the else statement properly. Now I'm working to redo my first name comparisons as something appears wrong since it wont order same last names alphabetically.

LESSON LEARNED: Get it all down before thinking you're forked. Now I really do feel like an idiot, hopefully didn't waste many peeps time.

  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].last) == 0 && strcmp(temp.first, students[i].first) < 0)
     {
        students[i] = students[i-1];
        students[i-1] = temp;
     }
     else
     {
        students[i] = temp;
        break;
     }

     insertHere = i;
  }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top