user14236936
user14236936

Reputation:

How to define "+" for a record type

I'm trying to create a package in ADA. I have three files, adb(main program), ads(package), and adb(body package). I can not see any problems with my main and package files. However, in my body package, I have trouble in writing a function that adds the values of P1 and P2 together and then returns its value.

My main program:

with Ada.Text_IO;                use Ada.Text_IO;
with Ada.Integer_Text_IO;        use Ada.Integer_Text_IO;
with Price_Handling;             use Price_Handling;
procedure Test_Price_Plus is

P1, P2 : Price_Type;  
begin
P1.Dollar:= 19;
P1.Cents:= 50;
P2 := (Dollar => 10, Cents=> 0);
Put("P1 is ");
Put(P1);
New_Line;
Put("P2 is ");
Put(P2); 
New_Line;

Put("If we add P1 and P2, then we get: ");
Put(P1 + P2);
New_Line;
end Test_Price_Plus;

My package:

with Ada.Text_IO;                use Ada.Text_IO;
with Ada.Integer_Text_IO;        use Ada.Integer_Text_IO;
package Price_Handling is

type Price_Type is private;
procedure Get(Item: out Price_Type);
function "+"(Left, Right: in Price_Type) return Price_Type;  -- Left(Dollar), Right(Cents)
private 
type Price_Type is
record
Dollar, Cents: Integer;
end record;
end Price_Handling;

My Package Body:

Package Body Price_Handling is 
procedure Put(Item:in  Price_Type) is
begin
Put(Item.Dollar); Put(":");
Put(Item.Cents);
end Put; 
function "+"(Left, Right: in Price_Type) return Price_type is   
begin
  -- Need to write a function that adds P1 and P2 together and return its value
  end "+";

Upvotes: 2

Views: 125

Answers (2)

Jim Rogers
Jim Rogers

Reputation: 5031

Another approach for this problem is to convert the dollars and cents for each instance of Price_Type to a total number of cents. Simply add the two cents values then convert the result back to dollars and cents.

package Price_Handling is
   
   type Price_Type is private;
   
   function "+" (Left, Right : Price_Type) return Price_Type;
   procedure Get(Item : out Price_type);
   procedure Print(Item : in Price_Type);
private
   
   subtype Cents_Type is Integer range 0..99;
   type Price_Type is record
      Dollars : Natural := 0;
      Cents   : Cents_Type := 0;
   end record;

end Price_Handling;


with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

package body Price_Handling is

   ---------
   -- "+" --
   ---------

   function "+" (Left, Right : Price_Type) return Price_Type is
      function To_Cents ( Item : Price_type) return Natural is
         Temp : Natural := 100 * Item.Dollars + Item.Cents ;
      begin
         return Temp;
      end To_Cents;
      function To_Price(Item : in Natural) return Price_Type is
         Dollars : Natural;
         Cents   : Cents_Type;
      begin
         Dollars := Item / 100;
         Cents   := Item mod 100;
         return (Dollars, Cents);
      end To_Price;
      
   begin
      return To_Price(To_Cents(Left) + To_Cents(Right));
   end "+";

   ---------
   -- Get --
   ---------

   procedure Get (Item : out Price_type) is
      
   begin
      Put("Enter the dollars for the price: ");
      Get(Item.Dollars);
      Put("Enter the cents for the price: ");
      Get(Item.Cents);
   end Get;
   
   -----------
   -- Print --
   -----------
   
   procedure Print (Item : in Price_Type) is
   begin
      Put(Item => Item.Dollars, Width => 1);
      Put (".");
      if Item.Cents < 10 then
         Put ("0");
      end if;
      Put (Item => Item.Cents, Width => 1);
   end Print;
   

end Price_Handling;


with Price_Handling; use Price_Handling;
with Ada.Text_IO; use Ada.Text_IO;

procedure Main is
   P1 , P2 : Price_Type;
begin
   Get(P1);
   Get(P2);
   Put("The sum of P1 and P2 is: ");
   Print(P1 + P2);
   New_Line;
end Main;

An example of executing this program produces the following output:

Enter the dollars for the price: 10
Enter the cents for the price: 41
Enter the dollars for the price: 0
Enter the cents for the price: 32
The sum of P1 and P2 is: 10.73

Another example showing proper incrementation of the dollars amount when the two cents amounts sum to more than a dollar is:

Enter the dollars for the price: 10
Enter the cents for the price: 52
Enter the dollars for the price: 3
Enter the cents for the price: 95
The sum of P1 and P2 is: 14.47

Upvotes: 1

Jere
Jere

Reputation: 3641

The easiest way for newcomers is probably just create a dummy result value and return it:

function "+"(Left, Right: in Price_Type) return Price_type is  
   Result : Price_Type; 
begin
   Result.Dollars := Left.Dollars + Right.Dollars;
   Result.Cents   := Left.Cents   + Right.Cents;
   
   -- If your cents are higher than 100, then we 
   -- need to increment dollars and adjust the cents
   -- count
   if Result.Cents > 99 then
      Result.Dollars := Result.Dollars + 1;
      Result.Cents   := Result.Cents - 100;
   end if;

   return Result;
end "+";

However, this is really weak. Your Price_type is not design using types that can protect you from errors. If you want to leverage Ada's safety aspects, consider making a Cents subtype that restricts you to 0 to 99:

subtype Cents_Type is Natural range 0 .. 99;

That way, if you make a programming error and put in a value higher than 99 or negative, then the program will catch it and raise an exception. Same for dollars. Make a new type for non negative values:

subtype Dollars_Type is Natural;

Now update your record to use those types and also default initialize them:

type Price_Type is record
   Dollars : Dollars_Type := 0;
   Cents   : Cents_Type   := 0;
end record;

Then if you do that, you can update the + function to use a dummy variable to hold the cents in case you do go over 99 while adding them together.

function "+"(Left, Right: in Price_Type) return Price_type is  
   Result : Price_Type; 
   Cents_With_Overflow : Natural;
begin
   Result.Dollars      := Left.Dollars + Right.Dollars;
   Cents_With_Overflow := Left.Cents + Right.Cents;
   
   -- If your cents are higher than 100, then we 
   -- need to increment dollars and adjust the cents
   -- count
   if Cents_With_Overflow  > 99 then
      Result.Dollars := Result.Dollars + 1;
      Result.Cents   := Cents_With_Overflow - 100;
   else
      Result.Cents   := Cents_With_Overflow;
   end if;

   return Result;
end "+";

Upvotes: 5

Related Questions