Comparing data in record with the user's input? - ada

Updated question. In this code, I have defined a record type that holds a bunch of data for a specific species. I want to write an if statement that compares the user's input for "Specied_Type" with the data that already exists in "Species_Type (Human, Elf, ....)". Any suggestions?
My code:
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO;
procedure Hero is
type Species_Type is(Human, Elf, Lizardman, Halfling); --Line 8
type Eye_Type is (Blue, Green, Brown, Gray, Black);
package Species_Type_IO is new Enumeration_IO (Species_Type);
use Species_Type_IO;
package Eye_Type_IO is new Enumeration_IO (Eye_Type); use Eye_Type_IO;
type Hero_Type is
record
Name: Unbounded_String;
Age: Integer;
Gender:Unbounded_String;
weight: Float;
Haircolor: Unbounded_String;
Species: Species_Type;
Eyecolor: Eye_Type;
end record;
A: Hero_Type;
Procedure Get(Item: out Hero_Type) is
begin
Put("Name: "); Item.Name:= Get_Line;
Put_Line("Name: " & Item.Name);
Put("Age: "); Get(Item.Age); Put("Age: " & Integer'Image (Item.Age));
New_Line;
Put("Species: "); Get(Item.Species); Put("Species: ");
Put(Item.Species, set => Lower_Case); New_Line;
Put("Eye color: "); Get(Item.Eyecolor); Put_Line("Color:
"&Eye_Type'Image(Item.Eyecolor));
if Item.Species /= A.Species then --Does not seem right
Put("Wrong input"); end if;
begin
Get(A);
end Hero;

Related

Using multidimensional array in Ada

In this code, I need help writing a multidimensional array with a range between 2020-01-01 to 2119-12-31.
My code works but as you see there are no arrays in it. How can I write this code with only arrays?
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
Procedure Date is
type date_type is record
Str : string (1..8);
Length : Natural := 0; end record;
A: date_type;
begin
loop
Put ("Enter a date between 2020-01-01 to 2119-12-31 : ");
Get_Line (A.Str, A.Length);
exit when A.Length = 8;
Put_Line ("Wrong input. Try again.");
end loop;
Put_Line (A.Str (1 .. 4) & "-" & A.Str (5 .. 6) & "-" & A.Str (7 .. 8));
end Date;
Perhaps, rather than a multi-dimensional array you should consider using a record such as
type Year_Number is range 1900..3000;
type Month_Number is range 1..12;
type Day_Number is range 1..31;
type Date_Rec is record
Year : Year_Number;
Month : Month_Number;
Day : Day_Number;
end record;
subtype Year_String is string (1..4);
subtype Month_String is string (1..2);
subtype Day_String is string (1..2);
function To_Date (Yr : Year_String; Mnth : Month_String; Dy : Day_String)
return Date_Rec is
Result : Date_Rec;
begin
Result.Year := Year_Number'Value (Yr);
Result.Month := Month_Number'Value (Mnth);
Result.Day := Day_Number'Value (Dy);
return Result;
end To_Date;
You can now pass around instances of Date_
Rec doing whatever you want with the date.
If you go this far then you might want to consider using the Time type described in Ada Language Reference Manual sections 9.6 and 9.6.1.
You haven't asked a reasonable question here because "I want to use arrays" is not a good reason to use an array.
"This problem can be best solved with an array ... but how do I deal with ... ?" would be a reasonable question, but you haven't stated a problem,let alone one that needs an array.
This is important because "using an array" is thinking in the solution domain, like "using a chisel". It's not the way to think about programming in Ada, (or IMO in any language).
Try thinking in the problem domain first : instead of "I want to use a chisel", I think "I want to recess this hinge so the door fits precisely" and a chisel is the neatest way of doing the job.
Then "How can I best validate a date?" would be one reasonable question, or "how can I store events that happen on each day for 100 years?"
The answer to the first question is probably in the Ada.Calendar package. Possibly the Value function in Ada.Calendar.Formatting, with an exception handler to catch incomprehensible strings and make the user try again.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Calendar;
with Ada.Calendar.Formatting;
procedure date is
Date : Ada.Calendar.Time;
Done : Boolean;
begin
loop
Put ("Enter a date between 2020-01-01 to 2119-12-31 : ");
Done := TRUE;
declare
A : String := Get_Line & " 12:00:00";
begin
Date := Ada.Calendar.Formatting.Value(A); -- validate it's a date
Done := Ada.Calendar.Year(Date) >= 2020
and Ada.Calendar.Year(Date) < 2120; -- validate correct range
exception
when Constraint_Error => Done := False; -- Formatting.Value failed
end;
exit when Done;
Put("Try Again : ");
end loop;
end date;
The answer to the second is probably a 1-dimensional array indexed by Day_Count from Ada.Calendar.Arithmetic but let's use the wrong tool : a 3D array indexed by your range of years, Month_Number and Day_Number from the Ada.Calendar base package.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Calendar; use Ada.Calendar;
with Ada.Calendar.Formatting;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
procedure date is
Date : Ada.Calendar.Time;
Done : Boolean := TRUE;
Event_Array : array(2020 .. 2119,
Ada.Calendar.Month_Number,
Ada.Calendar.Day_Number) of Unbounded_String;
begin
Event_Array := (others => (others => (others => Null_Unbounded_String)));
Event_Array(2020,11,3) := To_Unbounded_String("nothing much");
loop
Put ("Enter a date between 2020-01-01 to 2119-12-31 : ");
Done := TRUE;
declare
A : String := Get_Line & " 12:00:00";
begin
Date := Ada.Calendar.Formatting.Value(A);
Done := Ada.Calendar.Year(Date) >= 2020
and Ada.Calendar.Year(Date) < 2120;
exception
when Constraint_Error => Done := False;
end;
exit when Done;
Put("Try Again : ");
end loop;
Put_Line("Today " & Ada.Calendar.Formatting.Image(Date) & " : " &
To_String(Event_Array(Year(Date), Month(Date), Day(Date))) & " happened");
end date;
Test with the string 2020-11-03

Ada - How do you read an array from a single line of input?

My question is pretty simple, I have input that looks like this...
0 0 0 1 1 1 -1 -1 -1 1
And I need to store these values into an array but I can't figure it out. This is what I have so far...
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
type arr is array(1..10) of Integer;
Data : arr;
begin
for I in 1..arr'Length loop
Data(I) := Integer'Value(Get_Line);
end loop;
end Main;
I know this wrong and it's pretty obvious why this isn't working. I'm trying to store multiple values into a single integer, I need a way to iterate over the input or load all the values at once. How would you do this in Ada?
You can use Get_Line to get the whole line as a string and then Ada.Integer_Text_IO to parse the string:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Hello is
Line : String := Get_Line;
Value : Integer;
Last : Positive := 1;
begin
while Last < Line'Last loop
Get(Line(Last..Line'Last),Value,Last);
Put_Line(Value'Image); -- Save the value to an array here instead
Last := Last + 1; -- Needed to move to the next part of the string
end loop;
end Hello;
After that, you can load the values into an array in the loop or however you like.
Example output:
$gnatmake -o hello *.adb
gcc -c hello.adb
gnatbind -x hello.ali
gnatlink hello.ali -o hello
$hello
0
0
0
1
1
1
-1
-1
-1
1
EDIT: Adding a recursive option that is more general. This will read a line from STDIN and recursively concatenate the values into an array. It uses the secondary stack to do so in GNAT.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_Io;
procedure Hello is
-- Need an array return type
type Integer_Array is array (Positive range <>) of Integer;
-- Recursive function
function Get_Ints return Integer_Array is
Value : Integer;
begin
-- Read from STDIN using Integer_Text_IO;
Get(Value);
-- Concatinate recursively
return Integer_Array'(1 => Value) & Get_Ints;
exception
-- I found different exceptions with different versions
-- of GNAT, so using "others" to cover all versions
when others =>
-- Using Ada2012 syntax here. If not using Ada2012
-- then just declare the Empty variable somewhere
-- and then return it here
return Empty : Integer_Array(1..0);
end Get_Ints;
Result : Integer_Array := Get_Ints;
begin
Put_Line("Hello, world!");
Put_Line(Integer'Image(Result'Length));
for E of Result loop
Put(Integer'Image(E) & " ");
end loop;
end Hello;
If you know that you have 10 elements to read, it can be done a little more simply like this:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Hello is
A: array (1..10) of Integer;
begin
for V of A loop
Get(V);
end loop;
for I in A'Range loop
Put(I, 5);
Put(": ");
Put(A(I), 5);
New_Line;
end loop;
end Hello;
If you don't actually know how many elements to read in advance, please update the question.
Even though this already was answered, I'd like to add a couple improvements to Jere's answer.
It is more Ada-like to terminate the recursion using End_Of_File rather than an exception. Plus, it makes the program clearer.
Also, using tail-call recursion instead of normal recursion allows the compiler to perform some optimization.
function Get_Ints(input : in File_Type) return Integer_Array is
function Get_Ints_Rec(accumulator : in Integer_Array) return Integer_Array is
value : Integer;
begin
if End_Of_File(input) then
return accumulator;
else
begin
Get(input, value);
exception
when Data_Error => -- problem when reading
if not End_Of_Line(input) then
Skip_Line(input);
end if;
return Get_Ints_Rec(acc);
end;
return Get_Ints_Rec(accumulator & (1 => value));
end if;
end Get_Ints_Rec;
acc : constant Integer_Array(1 .. 0) := (others => 0);
begin
return Get_Ints_Rec(acc);
end Get_Ints;

Why is my Ada program not outputting correctly?

Let me start by saying this is the first ada program I have ever created. I have no idea how it works, and my assignment is incredibly simple. However, the output is not working correctly. It works with the first variable, but not with the next two. It also prints the first variable weird. Here is my code:
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
Author, Title, Pages: String := " ";
begin
Put("Enter Author: ");
Get(Author);
Put("Enter Title: ");
Get(Title);
Put("Enter number of pages: ");
Get(Pages);
Put("Author: ");
Put(Author);
New_Line;
Put("Title: ");
Put(Title);
New_Line;
Put("Number of pages: ");
Put(Pages);
end Main;
The goal is simply to enter information about a book and the program reads it out to you. This is the output:
Enter Author: john
Enter Title: Enter number of pages: Author: j
Title: o
Number of pages: h
Side note, I couldn't get page numbers to work as an integer. The get and put methods just gave errors. That isn't important but if anyone can help make that an integer I would appreciate it.
Here's a possible solution:
with Ada.Text_IO;
procedure Text_Input is
type Page_Count is range 1 .. 10_000;
package Page_Count_Text_IO is new Ada.Text_IO.Integer_IO (Page_Count);
function Get_Line (Message : in String) return String;
function Get_Line (Message : in String) return Page_Count;
function Get_Line (Message : in String) return String is
begin
Ada.Text_IO.Put (Message);
return Ada.Text_IO.Get_Line;
end Get_Line;
function Get_Line (Message : in String) return Page_Count is
begin
return Result : Page_Count do
Ada.Text_IO.Put (Message);
Page_Count_Text_IO.Get (Result);
if Ada.Text_IO.Get_Line /= "" then
raise Constraint_Error
with "Page count followed by extra characters.";
end if;
end return;
end Get_Line;
Author : constant String := Get_Line ("Enter author: ");
Title : constant String := Get_Line ("Enter title: ");
Pages : constant Page_Count := Get_Line ("Enter number of pages: ");
begin
Ada.Text_IO.Put_Line ("Author: " & Author);
Ada.Text_IO.Put_Line ("Title: " & Title);
Ada.Text_IO.Put_Line ("Number of pages:" & Page_Count'Image (Pages));
end Text_Input;
Notice that I've made the Get_Line function for Page_Count check that you don't have any trailing garbage on the line, where you enter the number of pages.
I hope you don't disagree with my estimate that John will never write a single book of more than 10'000 pages. :-)

"ADA.FLOAT_IO" is not a predefined library unit

Why do i get this error?
"ADA.FLOAT_IO" is not a predefined library unit
I've never written anything in ADA before, simply i have no idea what i'm doing. I use GNAT to compile.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Float_IO; use Ada.Float_IO;
with Ada.Numerics.Elementary_Functions;
use Ada.Numerics.Elementary_Functions;
procedure MAIN is
A,B,C:Float;
W : Float;
Re, Im:Float;
begin
Put("Give A");Get(A);
Put("Give B");Get(B);
Put("Give C");Get(C);New_Line;
if A=0.0 then
Put_Line("It is not second degree polynomial");
else
W:=B*B - 4.0*A*C;
Re:=B/(2.0*A); Im:=Sqrt(Abs(W))/(2.0*A);
Put("dif = "); Put(W);New_Line;
if W<0.0 then
Put_Line("Complex ");
Put("x1 = ");Put(-Re);Put(" -j ");Put(Im);Put(" ");
Put("x2 = ");Put(-Re);Put(" +j ");Put(Im);New_Line;
else
Put_Line("Real");
Put("x1 = ");Put(-Re-Im);Put(" ");
Put("x2 = ");Put(-Re+Im);
end if;
end if;
end MAIN;
IIRC Float_IO is a child of Text_IO: Ada.Text_IO.Float_IO. Furthermore, that's a generic package. I guess you want Ada.Float_Text_IO, which is defined as
package Ada.Float_Text_IO is new Ada.Text_IO.Float_IO (Float);

Ada - Is there a function to make a character or unbounded string to lower case?

Is there a way to accept user input whether it is a character or an unbounded string and convert it to lower case?
newLine, N: unbounded_string;
M: string(1..26);
len: integer;
new_line; new_line;
put("What is your favorite color?");
new_line;
put("Answer:");
get_line(newLine);
get_line(M,len);
N := to_unbounded_string(to_lower(M));
put_line(N);
And for my input: If i type BLUE the put_line(N); will return blue#�hw�
For Character and fixed length String, there is Ada.Characters.Handling.To_Lower RM A.3.2
Also, similar function exists for Wide_Character, Wide_String, Wide_Wide_Character and Wide_Wide_String in Ada.Wide_Characters.Handlingand Ada.Wide_Wide_Characters.Handling
with Ada.Strings;
with Ada.Strings.Maps.Constants;
with Ada.Strings.Unbounded;
with Ada.Text_IO;
with Ada.Text_IO.Unbounded_IO;
procedure Change_Case is
S : Ada.Strings.Unbounded.Unbounded_String;
begin
Ada.Text_IO.Put_Line("Enter a string: ");
S := Ada.Strings.Unbounded.To_Unbounded_String(Ada.Text_IO.Get_Line);
Ada.Text_IO.Unbounded_IO.Put_Line(S);
Ada.Strings.Unbounded.Translate(S, Ada.Strings.Maps.Constants.Lower_Case_Map);
Ada.Text_IO.Unbounded_IO.Put_Line(S);
Ada.Strings.Unbounded.Translate(S, Ada.Strings.Maps.Constants.Upper_Case_Map);
end Change_Case;

Resources