0

Structure and DMA. I want to retrieve all the inserted record in decreasing order of cgpa. Without sorting it give the result as shown below image.

image

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

struct student {
    string name;
    int age;
    float cgpa;
};
void main()
{
    student *ptr;
    int size;
    cout << "enter size \n";
    cin >> size;
    ptr = new student[size];
    for (int i = 0; i < size; i++)
    {
        cout << "enter student " << i + 1 << " name\n";
        cin >> ptr[i].name;
        cout << "enter student " << i + 1 << " age\n";
        cin >> ptr[i].age;
        cout << "enter student " << i + 1 << " cgpa\n";
        cin >> ptr[i].cgpa;
    }
    cout << "with out sorting \n";
    for (int i = 0; i < size; i++)
    {
        cout << " NAME\tAGE\tCGPA\n";
        cout << ptr[i].name << "\t" << ptr[i].age << "\t" << ptr[i].cgpa << endl;
    }
    system("pause");
}


  [1]: https://i.stack.imgur.com/whP8d.png
Sercan
  • 2,081
  • 2
  • 10
  • 23
  • 1
    What do you mean "without sorting"? Does putting the data into a `std::set` count? – cigien Jun 29 '20 at 23:10
  • Unrelated, but you have memory leak, don't use raw pointers, use `std::vector` or `std::set` as mentioned above. – fas Jun 29 '20 at 23:23
  • As mentioned by @fas you have to do `delete [] ptr` at the end to deallocate the pointer to avoid memory leak. – EEAH Jun 29 '20 at 23:28
  • `std::sort(ptr, ptr + size, [](const student& s1, const student& s2){return s1.cgpa > s2.cgpa;});` -- Anything stopping from using this? – PaulMcKenzie Jun 29 '20 at 23:33
  • As surprising as this may sound, sorting an array is exactly the same with or without dynamic allocation. – user4581301 Jun 30 '20 at 00:07

2 Answers2

0

"Without sorting" is a bit unclear, but I take that to mean you cannot call std::sort directly or use another explicit sorting routine. That leaves you with choosing a container that stores object in sort order based on a compare function (or overload) you provide. Looking at the Microsoft C++ language conformance table for VS2015, it shows all core language features for C++11 supported -- which would include std::set.

std::set allows you to store a sorted set of unique objects. This means you can take input and store the results in a std::set based a Compare function you provide. Providing a Compare function that will compare the cgpa of each student will then automatically store your student objects based cgpa.

To make std::set available, you simply need to #include<set>. Writing the compare function that can be used to store students based on cgpa simply requires providing an overload for the < operator that takes two of your student objects as arguments and then returns true when the first argument sorts before the second, false otherwise. That can be as simple as:

/* overload of < comparing student by cgpa */
bool operator <(const student& a, const student& b) {
    return a.cgpa < b.cgpa;
}

A note: unless you are compiling for a micro-controller or embedded system with no Operating System (called a freestanding environment), void main() is wrong. A standard conforming invocation of main() is either int main(void) or int main (int argc, char **argv) where argc is the argument count and argv your argument vector (technically an array of pointers to null-terminated strings where the next pointer after the last argument is set to NULL as a sentinel) There are other non-standard extensions added by some compilers like char **envp providing a pointer to each of the environment variables.

To declare your set of student you need to provide the type student and the compare function to be used when inserting students into your set. Since you provide an overload for the less-than operator, you can use std::less<> providing one template argument, e.g.

int main(void)
{
    /* create std::set of students using std::less for compare */
    std::set<student, std::less<const student&>> students {};

And since you are using a container that provides automatic memory management for you, there is no need to know the size (or number of students to enter) before hand. You can simply enter as many students as you need and then press Ctrl+d on Linux or Ctrl+z on Windows to generate a manual EOF signifying your end of input. However you do need to validate every user input by checking the return (stream state) following each input. At minimum you can use:

        std::cout << "enter student " << i + 1 << " name\n";
        if (!(std::cin >> s.name))  /*  validate all input, ctrl + z to end input */
            break;

(note: the variable i is only needed to show the student number when you prompt for input, all containers provides the .size() member function that tell you how many objects are contained within.)

When done taking input, you can use a Range-based for loop to iterate over each student in your set outputting the desired information. For example:

    std::cout << "\nwith out sorting \n";
    for (auto& s : students) {      /* output in order of cgpa w/o sorting */
        std::cout << " NAME\tAGE\tCGPA\n"
                    << s.name << "\t" << s.age << "\t" << s.cgpa << '\n';
    }

Putting it altogether, you could do:

#include <iostream>
#include <string>
#include <set>

struct student {            /* struct student */
    std::string name;
    int age;
    float cgpa;
};

/* overload of < comparing student by cgpa */
bool operator <(const student& a, const student& b) {
    return a.cgpa < b.cgpa;
}

int main(void)
{
    /* create std::set of students using std::less for compare */
    std::set<student, std::less<const student&>> students {};
    
    for (int i = 0; ; i++) {
        student s {};       /* temporary struct to add to set */
        std::cout << "enter student " << i + 1 << " name\n";
        if (!(std::cin >> s.name))  /*  validate all input, ctrl + z to end input */
            break;
        std::cout << "enter student " << i + 1 << " age\n";
        if (!(std::cin >> s.age))
            break;
        std::cout << "enter student " << i + 1 << " cgpa\n";
        if (!(std::cin >> s.cgpa))
            break;
        students.insert(s); /* insert student in set */
    }
    std::cout << "\nwith out sorting \n";
    for (auto& s : students) {      /* output in order of cgpa w/o sorting */
        std::cout << " NAME\tAGE\tCGPA\n"
                    << s.name << "\t" << s.age << "\t" << s.cgpa << '\n';
    }
}

(note: Look at Why is “using namespace std;” considered bad practice?. Developing good habits early is a lot easier that trying to break bad ones later...)

(note 2: you might consider using getline(std::cin, s.name) to take input for the student name so you can handle names with spaces, like Firstname Lastname, e.g. Mickey Mouse, up to you)

Add system("pause"); back in to hold your terminal window open as needed.

Example Use/Output

Now just enter the student data for as many students as you like and then terminate input by generating a manual EOF as described above, e.g.

$ ./bin/set_student_grades
enter student 1 name
gates
enter student 1 age
20
enter student 1 cgpa
2.12
enter student 2 name
della
enter student 2 age
21
enter student 2 cgpa
2.00
enter student 3 name
jim
enter student 3 age
30
enter student 3 cgpa
3.12
enter student 4 name

with out sorting
 NAME   AGE     CGPA
della   21      2
 NAME   AGE     CGPA
gates   20      2.12
 NAME   AGE     CGPA
jim     30      3.12

This provides a way to store and provide the student data in order of cgpa without an explicit sort. Of course std::set does that for you, but if avoiding an explicit sort was the intent of your program, this is very good option. Let me know if you have further questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • It will work fine in VS2015. I just built it in the Microsoft SDK 7.1 (VS 2010 compiler) and aside from changing the range based for loop to one that iterates `for (auto s = students.begin(); s != students.end(); s++)` it worked just fine. – David C. Rankin Jun 30 '20 at 08:28
0
#include<iostream>
#include<string>
using namespace std;
struct student {
    string name;
    int age;
    float cgpa;
};
void main() {
    student *ptr;
    int size;
    cout << "enter size \n"; cin >> size;
    ptr = new student[size];
    for (int i = 0; i < size; i++)
    {
        cout << "enter student " << i + 1 << " name\n";
        cin >> ptr[i].name;
        cout << "enter student " << i + 1 << " age\n";
        cin >> ptr[i].age;
        cout << "enter student " << i + 1 << " cgpa\n";
        cin >> ptr[i].cgpa;
    }
    string temp1; int temp2;    float temp3;
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            if (ptr[i].cgpa < ptr[j].cgpa)
            {
                temp1 = ptr[j].name;
                ptr[j].name = ptr[i].name;
                ptr[i].name = temp1;

                temp2 = ptr[j].age;
                ptr[j].age = ptr[i].age;
                ptr[i].age = temp2;

                temp3 = ptr[j].cgpa;
                ptr[j].cgpa = ptr[i].cgpa;
                ptr[i].cgpa = temp3;
            }
        }
    }
    for (int i = 0; i < size; i++) {
        cout << " NAME\tAGE\tCGPA\n";
        cout << ptr[i].name << "\t" << ptr[i].age << "\t" << ptr[i].cgpa << endl;
    }
    
    delete[] ptr;
    system("pause");
}