I have an assignment in class I'm and almost done but I need help with one part.

Within each subject in the output file, list the students in alphabetic order, sorted by last name. Do not change the given case (upper/lower case) of the names that were read from the input file when you print the output file. However, this sort needs to be true alphabetical (not just the "lexicographical" sort).

#include <iostream>
#include <iomanip>
#include <fstream>
#include <cctype>
#include <cstdlib>
#include <cstring>
using namespace std;

struct Student
{
    char lastname[20];
    char firstname[20];
    char course;
    int grade1;
    int grade2;
    int final;
    double average;
};

void openFile (ofstream &, ifstream &, char[]);
void PrintClass (Student*, ofstream &, int, char);
double TestAverage (const Student&);
char Grade (const Student&);
void Alphasort (Student*, int);

int main()
{
    Student* students = NULL; 
    char filename[25];  // a string for filenames
    ifstream in1;       // a file input stream
    ofstream out1;       // a file output stream
    int classSize;

    openFile (out1, in1, filename);



    in1 >> classSize;

    students = new Student[classSize];

    for( int i = 0; i < classSize; i++)
    {
        in1.ignore(80, '\n');
        in1.getline(students[i].lastname, 20, ',');
        in1.getline(students[i].firstname, 20, ',');
        in1.get(students[i].course);
        in1.ignore(80, ',');
        in1 >> students[i].grade1;
        in1.ignore(80, ',');
        in1 >> students[i].grade2;
        in1.ignore(80, ',');
        in1 >> students[i].final;
        students[i].average = TestAverage (students[i]);
    }


    out1 << "Student Grade Summary" << endl;
    out1 << "---------------------" << endl << endl;

    out1 << "ENGLISH CLASS" << endl;
    PrintClass (students, out1, classSize, 'E');


    out1 << "HISTORY CLASS" << endl;
    PrintClass (students, out1, classSize, 'H');

    out1 << "MATH CLASS" << endl;
    PrintClass (students, out1, classSize, 'M');


    delete [] students;

    return 0;

}
// this function will read the file

void openFile (ofstream& out1, ifstream& in1, char filename[])
{
    do
   {
    in1.clear();    // to clear status flags in the stream

        cout << "Please enter the name of the input file.\n";
        cout << "Filename:  ";
        cin >> filename;

        in1.open(filename);
        if (!in1)
            cout << "That is not a valid file.  Try again!\n";

   } while (!in1);

   do
   {
    out1.clear();   // to clear status flags in the stream

        cout << "Please enter the name of the output file.\n";
        cout << "Filename:  ";
        cin >> filename;

        out1.open(filename);
        if (!out1)
            cout << "That is not a valid file.  Try again!\n";
         } while (!out1);
}
// this function will display each student
void PrintClass (Student* students, ofstream& out1, int size, char subject)
{
    int count = 0;
    double sum = 0;
    char Fullname[40];


    out1 << endl;
    out1 << "Student Name                             Test Avg" << endl;
    out1 << "----------------------------------------------------------------" << endl;

    for( int i = 0; i < size; i++)
    {
        Alphasort(students,size); // EXTRA Credit function

        if (students[i].course == subject)
        {
            strncpy(Fullname,students[i].firstname, 20);
            strncat(Fullname, " ", 1);
            strncat(Fullname, students[i].lastname, 20);
            out1 << setw(44)<< left << Fullname;
            out1 << right << showpoint << fixed << setprecision(2)<< students[i].average << "  " << Grade(students[i]) << endl;
            sum += students[i].average;
            count ++;
        }
    }
    out1 << endl;
    out1 << "     Class Average               " << (sum/count) << endl;
    out1 << "----------------------------------------------------------------" << endl;
    out1 << endl << endl;
}
// This fuction will calculate the test average of the studnts
double TestAverage (const Student& student)
{
    double average;

    average = (student.grade1 * .3) + (student.grade2 * .3) + (student.final * .4);
    return average;
}
// This fuction will display the grades
char Grade (const Student& student)
{
    char grade;

    if (student.average < 60)
        grade = 'F';
    else if (student.average < 70)
        grade = 'D';
    else if (student.average < 80)
        grade = 'C';
    else if (student.average < 90)
        grade = 'B';
    else
        grade = 'A';
    return grade;
}
// Extra Credit: fuction that will alphabetize the last names
void Alphasort (Student* student, int size)
{
    int j, i;

    Student temp;

        for(i = 0; i < size - 1; ++i)
        {
            for(j = i + 1; j < size; ++j)
            {
                if(strcmp(student[i].lastname,student[j].lastname) > 0)
                {
                    temp = student[i];
                    student[i] = student[j];
                    student[j] = temp;
                };
            }
        }
}

Dani AI

Generated

Nice catch by @Ancient Dragon on case-insensitive compare. One more tweak you likely want: break ties by first name, and avoid re-sorting inside your print loop. Right now PrintClass calls Alphasort on every iteration, which is O(n^3) overall and unnecessary.

Here is a small, drop-in update that keeps original casing when printing, compares last names case-insensitively, then first names if needed. It also uses a tiny wrapper so it works both on Windows and POSIX compilers.

// Case-insensitive C-string compare wrapper
static inline int icmp(const char* a, const char* b) {
#if defined(_WIN32)
    return _stricmp(a, b);     // <string.h>
#else
    return strcasecmp(a, b);   // <strings.h>
#endif
}

// Sort by last name (case-insensitive), then first name
void Alphasort(Student* s, int n)
{
    for (int i = 0; i < n - 1; ++i) {
        for (int j = i + 1; j < n; ++j) {
            if (icmp(s[i].lastname, s[j].lastname) > 0 ||
               (icmp(s[i].lastname, s[j].lastname) == 0 &&
                icmp(s[i].firstname, s[j].firstname) > 0))
            {
                Student tmp = s[i];
                s[i] = s[j];
                s[j] = tmp;
            }
        }
    }
}

How to use it cleanly:

  • Call Alphasort(students, classSize); once before printing any classes, or once at the start of PrintClass (not inside the for loop).
  • If your instructor expects "true alphabetical" to ignore punctuation like apostrophes or hyphens (e.g., O'Neil vs Oneil), add a small helper that skips those chars before comparing.

This keeps output casing unchanged, gives a predictable order for duplicate last names, and avoids the extra work in the print loop.

Recommended Answers

All 2 Replies

In Alphasort() you strcmp() is NOT case insensitive. You need to use a case-insensitive function, such as stricmp() or strcasecmp(), depending on the compiler you are using.

Or you could write your own compariso function by copying both strings into a temp variable, convert each to all UPPER case then use strcmp() in the temp strings.

Thank you so much. I used stricmp() instead and it worked out perfectly

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.