1

First off, I'll admit openly that this is a homework assignment. That being said, my code is VERY close, and hoping for a nudge in the right direction.

The prompt: Write a complete program to read student data from the standard input, sort it by last name / first name , and print out the result to standard output . The student data consists of a last name , first name , and a grade point average (a floating point value ). You should assume no more than 50 students.

SAMPLE INPUT:

Ware Henry 87.2 Dantes Edmond 91.4 Earhart Amelia 92.6

My code accepts user input, swaps them based on last name, then first name, and outputs the list of students and GPA. The online program that tests my code inputs six (6) students data. It sorts them correctly using Swap, but the 5th student is repeated from entries 5-49 (out of 50), before finally outputting student 6. I've searched the forum, but not quite found a previous posting that applies.

I've tried using a 'while' statement in the output loop, but my grasp on booleans is a bit weak still. The attempted while statement is listed at the top of my code. Any assistance would be greatly appreciated.

while((list[i].lastName != list[i + 1].lastName) && (list[i].firstName != list[i + 1].firstName))

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

class student
{
public:
    string firstName;
    string lastName;
    float gpa;

    student() {};
    student(string last, string first, double grade)
    {
        firstName = first;
        lastName = last;
        gpa = grade;
    };
};

int main()
{
    string first;
    string last;
    float grade;

    student list[50];


    for(int i = 0; i < 50; i++)
    {
        cin >> last;
        cin >> first;
        cin >> grade;
        list[i].lastName = last;
        list[i].firstName = first;
        list[i].gpa = grade;
    }
    for ( int i = 0; i < 50 - 1; i++)
        {
            if (list[i].lastName > list[i + 1].lastName)
            {
                swap (list[i], list[i+1]);
            }
        }
        for ( int i = 0; i < 50 - 1; i++)
        {
            if (list[i].firstName > list[i + 1].firstName)
            {
            swap (list[i], list[i+1]);
            }
        }


        for(int i = 0; i < 50 - 1; i++)
        {
            cout << list[i].lastName << " " << list[i].firstName << " " << list[i].gpa << endl;
        }

    return 0;
}
fizzy.lift
  • 11
  • 2
  • 2
    You are trying to read exactly 50 entries from input, and aren't checking for any I/O errors. Once end of file is reached, all those `>>` operators start failing - but you don't notice that, and insert an entry with whatever values those three variables held last. That's how you end up with 44 copies of the same student's data. – Igor Tandetnik Oct 13 '14 at 05:16

2 Answers2

2
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

class student
{
public:
    string firstName;
    string lastName;
    float gpa;

    student() {};
    student(string last, string first, double grade)
    {
        firstName = first;
        lastName = last;
        gpa = grade;
    };
};

int main()
{
    string first;
    string last;
    float grade;

    student list[5];


    for(int i = 0; i < 5; i++) //use 5 instead of 50 because myprogramminglab only input 5 entries, not 50, it lies to you
    {
        cin >> last;
        cin >> first;
        cin >> grade;
        list[i].lastName = last;
        list[i].firstName = first;
        list[i].gpa = grade;
    }
    for ( int i = 0; i < 4; i++)
        {
            if (list[i].lastName > list[i + 1].lastName)
            {
                swap (list[i], list[i+1]);
            }
        }
        for ( int i = 0; i < 4; i++)
        {
            if (list[i].firstName > list[i + 1].firstName)
            {
            swap (list[i], list[i+1]);
            }
        }


        for(int i = 0; i < 5; i++)
        {
            cout << list[i].lastName << " " << list[i].firstName << " " << list[i].gpa << endl;
        }

    return 0;
}

/Comments: I believe that this assignment is from myprogramminglab. The only thing that you need to fix is change from 50 to 5, myprogramminglab just inputs 5 entries instead of 50 as it says/

Fishy
  • 21
  • 2
0

The number of inputs to your program is only guaranteed to be <= 50, indeed in the test data, there are only 6 entries and in your sample input there are only 3.

Your problem lies in that you are currently expecting 50 entries every time you run the program, and when cin >> variable fails, no data is written.

From your sample input, all the data is input on one line. This means we can use the method described in this answer to handle the input.

Your input loop now looks like this:

int count = 0;
std::string line;
std::getline(cin, line);
std::istringstream iss(line);

while ((iss >> last) && (iss >> first) && (iss >> grade))
{
    list[count].lastName = last;
    list[count].firstName = first;
    list[count].gpa = grade;
    cout <<"student: "<< last << " " << " " << first << " " << grade << endl;
    count++;
}

We now read in the entire line in one go, and then use the stream operator >> to read it.
Functionally, this is very similar to your original code, however, unlike cin there is an end to the stream.
iss >> variable will return false when it reaches the end of the data, which breaks us out of the loop. At this point, the count variable will have a value equal to the number of student data-sets input.

We can now use count in the rest of the loops (instead of 50).

Full code:

#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
using namespace std;

class student
{
public:
    string firstName;
    string lastName;
    float gpa;

    student() {};
    student(string last, string first, double grade)
    {
        firstName = first;
        lastName = last;
        gpa = grade;
    };
};

int main()
{
    string first;
    string last;
    float grade;

    student list[50];

    int count = 0;
    std::string line;
    std::getline(cin, line);
    std::istringstream iss(line);

    cout<<"input data: \n";
    while ((iss >> last) && (iss >> first) && (iss >> grade))
    {
        list[count].lastName = last;
        list[count].firstName = first;
        list[count].gpa = grade;
        cout <<"student: "<< last << " " << " " << first << " " << grade << endl;
        count++;
    }

    for ( int i = 0; i < count-1; i++)
        {
            if (list[i].lastName > list[i + 1].lastName)
            {
                swap (list[i], list[i+1]);
            }
        }
        for ( int i = 0; i < count-1; i++)
        {
            if (list[i].firstName > list[i + 1].firstName)
            {
            swap (list[i], list[i+1]);
            }
        }


        for(int i = 0; i < count; i++)
        {
            cout << list[i].lastName << " " << list[i].firstName << " " << list[i].gpa << endl;
        }

    return 0;
}

I've got a running version of this at ideone for you: http://ideone.com/Y9jOkt I have however done a few further enhancements that are in this version: removed using namespace std see here for why used a std::vector instead of a bare array, will adapt to the number of inputs instead of being at a fixed size. Created a locat current_student object to read the data into, keeps the intent clear and works well with std::vector. Can be done with the bare array too.

I'd also like to point out that your sort is, not right.
This input:

f f 9 e e 8 d d 7 c c 6 b b 5 a a 4

should provide this output:

a a 4
b b 5
c c 6
d d 7
e e 8
f f 9

but instead comes out like this:

d d 7
c c 6
b b 5
a a 4
e e 8
f f 9

You are doing a bubble sort (I guess that was your intention), but only doing one pass. I could answer it here, but as a seperate issue, you should probably ask this in another question.

Community
  • 1
  • 1
Baldrickk
  • 4,291
  • 1
  • 15
  • 27
  • Regarding the sorting, it's a pretty easy fix with two steps: Step one: add a nested loop into each sort. Step 2: sort by firstname first, so that entries are ordered by firstname within surname. http://ideone.com/4liN2T – Baldrickk Oct 13 '14 at 11:30