The Ada Program: sort_names.adb

  1 -- sort_names.adb: A main program using generic bounded strings package
  2 
  3 with Ada.Text_IO, Bounded_Strings;
  4 use Ada;
  5 procedure Sort_Names is
  6 
  7 -- Program 5-2 by Dale, Lilly, & McCormick
  8 
  9 -- This program reads names from the keyboard and displays them in
 10 -- alphabetical order.  Names may be entered one per line in one of two forms:
 11 --
 12 --            First_Name Last_Name   or   Last_Name, First_Name
 13 --
 14 -- The comma is required in the second form.
 15 -- End of input is indicated with a null name.
 16 --
 17 -- Assumptions:  1.  There are no more than 20 names.
 18 --               2.  All input lines contain less than 30 characters
 19 --               3.  There is only one blank between the first and
 20 --                   last names; and no leading, or trailing blanks.
 21 
 22    Max_Name_Length : constant := 30; -- Maximum characters in any name
 23    Max_Names       : constant := 20; -- Maximum number of names
 24 
 25    -- Instantiate a bounded-length string package
 26    package String30 is new Bounded_Strings (Max_Length => Max_Name_Length);
 27    use String30;  -- Make operations in String30 directly visible
 28 
 29    -- Array type for holding all the names
 30    type    Index_Type  is range 0..Max_Names;
 31    subtype Index_Range is Index_Type range 1..Max_Names;
 32    type Name_Array is array (Index_Range range <>) of String30.Bounded_String;
 33 
 34    -- Variables for main program
 35    Name      : String30.Bounded_String;  -- One name
 36    Name_List : Name_Array (Index_Range); -- List of names entered by the user
 37    Num_Names : Index_Type;               -- Number of names entered
 38 
 39    -- An unordered list is taken as input.  The same list
 40    -- with the components in ascending order is returned
 41    procedure Selection_Sort (List : in out Name_Array) is
 42      Name      : String30.Bounded_String; --  Temporary variable for swapping
 43      Min_Index : Index_Type;              --  Index of minimum so far
 44    begin
 45       for Pass_Count in  List'First .. List'Last - 1  loop
 46          -- Find index of smallest item in List(Pass_Count)..List(List'Last)
 47          Min_Index := Pass_Count;
 48          for Place_Count in Pass_Count + 1 .. List'Last loop
 49             -- Compare names with String30."<"
 50             if List(Place_Count) < List(Min_Index) then
 51                Min_Index := Place_Count;
 52             end if;
 53          end loop;
 54          --  Swap List(Min_Index) and List(Pass_Count)
 55          Name := List(Min_Index);
 56          List(Min_Index)  := List(Pass_Count);
 57          List(Pass_Count) := Name;
 58       end loop;
 59    end Selection_Sort;
 60 
 61 
 62    -- We assume the given name is of the form "First Last" with
 63    -- exactly one blank between the names, or of the form "Last, First".
 64    -- Names of the first form are converted to the latter.
 65 
 66    procedure Last_Name_First (Name : in out String30.Bounded_String) is
 67       Blank    : constant Bounded_String := To_Bounded_String (" ");
 68       Position : Natural;   -- Position result of string search
 69    begin
 70       -- Determine the position of the blank
 71       Position := Index (Source => Name, Pattern => Blank);
 72       -- Is the first name first (no comma indicates it is)?
 73       if Element (Name, Position-1) /= ',' then
 74          -- Put the last name first (separated by a comma and a blank)
 75          Name := Slice (Name, Position+1, Length(Name))-- The last name
 76                  &  ", "                               -- A comma and blank
 77                  &  Slice (Name, 1, Position-1);       -- The first name
 78       end if;
 79    end Last_Name_First;
 80 
 81 begin
 82 
 83    -- Get all the names
 84    Num_Names  := 0;
 85    Input_Loop:   -- Each iteration, one name is processed
 86    loop
 87       Text_IO.Put_Line ("Enter a name (blank name to end)");
 88       String30.Get_Line (Item => Name);
 89       -- Is this a null name?
 90       exit Input_Loop when Length (Name) = 0;
 91       -- Make sure the last name comes before the first name
 92       Last_Name_First (Name);
 93       -- Put the name into the list
 94       Num_Names  := Num_Names  + 1;
 95       Name_List (Num_Names) := Name;
 96    end loop Input_Loop;
 97 
 98    -- Sort the names
 99    Selection_Sort (List => Name_List (1..Num_Names));
100 
101    -- Display the sorted names
102    for Index in 1..Num_Names loop
103       String30.Put (Item => Name_List (Index));
104       Text_IO.New_Line;
105    end loop;
106 
107 end Sort_Names;