Sorting structs?

Stanislav Blinov stanislav.blinov at gmail.com
Wed Jan 29 03:24:53 PST 2014


On Wednesday, 29 January 2014 at 10:30:06 UTC, Boomerang wrote:

I'll paste here with comments:

import std.algorithm;
import std.stdio;
import std.array;

void main()
{
     struct Student
     {
         string name;
         float grade;
     }

     Student[] studs;

     writeln("Enter student data. Reading stops when student name 
is empty.");

     while (true)
     {
         // Calls to readf() may throw an exception
         // if user inputs invalid data.
         // You may want to consider accounting
         // for that.

         typeof(Student.name) name;
         write("Student name: ");
         readf("%s\n", &name);

         // Don't burden users with typing STOP :)
         if (name.empty)
             break;

         typeof(Student.grade) grade;
         write("Student grade: ");

         import std.exception;
         import std.conv : ConvException;
         // EXAMPLE: catch all ConvExceptions
         // to persuade user to input a number :)
         while(collectException!ConvException(readf("%s\n", 
&grade)))
         {
             // Conversion failed but there's still data in
             // stdin. We get rid of it:
             readln;
             write("Please enter NUMERIC student grade: ");
         }

         // Create Student only when necessary
         // (a good compiler will optimize that
         // to avoid copying):
         studs ~= Student(name, grade);
     }

     // Use anonymous function with explicit
     // parameter storage class specifier;
     // Also Use UFCS
     studs.sort!((ref const a, ref const b) => a.grade > b.grade);

     // You can omit type name in foreach;
     // also it's worth using ref const to avoid
     // unnecessary copies
     foreach (ref const s; studs)
         writeln(s.name);

     // Or avoid foreach altogether:
     studs.map!((ref const s) => writeln(s.name));
}

> Also sorry for double posting but I'm confused how the sorting 
> works when we only specify to be sorted by grade. I think in 
> C++, disregarding other data members can lead to loss of data 
> in things such as std::set.

Yes and no. In fact, std::set is by default instantiated with an 
std::less predicate. But std::set is intended to store unique 
elements. So if you try to insert an element that std::set 
already considers to exist (it uses the predicate to determine 
that), it doesn't insert it.

But you must understand that despite being generic, algorithms 
and containers still serve particular purposes. You wouldn't 
store students in a set unless you had some way to uniquely 
identify them :)


More information about the Digitalmars-d-learn mailing list