with ada.text_io; use ada.text_io;
with ada.integer_text_io; use ada.integer_text_io;
-- When using gnat, requires -gnato option to enable overflow checks
procedure table5 is
type Alignment is (left, center, right);
package AlignmentIO is new Ada.text_io.enumeration_IO(Alignment);
use AlignmentIO;
ColumnWidth: constant Integer := 11;
--------------------------------------------------------
-- Input one integer
--------------------------------------------------------
procedure getOneItem(
item: out Integer;
prompt: String;
lowerBound: Integer;
errorMsg: String) is
begin
loop
begin
put(prompt);
get(item);
exit when item > lowerBound;
put_line(errorMsg);
exception
when Data_Error =>
new_line;
put_line("Must enter a valid integer value.");
-- Discard anything left on input line
skip_line;
when others =>
new_line;
put_line("Unknown exception occurred.");
put_line("Bailing out!");
exit;
end;
end loop;
end getOneItem;
--------------------------------------------------------
-- Input the alignment
--------------------------------------------------------
procedure getAlignment(prompt: string; align: out Alignment) is
begin
loop
begin
put(prompt);
get(align);
exit;
exception
when Data_Error =>
put_Line("Invalid alignment");
end;
end loop;
end getAlignment;
--------------------------------------------------------
-- Input all the data
--------------------------------------------------------
procedure getData(sI, fI, sP, fP: out Integer; align: out Alignment) is
begin
getAlignment("Enter alignment: ", align);
getOneItem(sI, "Enter starting integer: ",
-1, "Integer must be non-negative");
getOneItem(fI, "Enter ending integer: ",
sI, "Ending integer must be larger than starting");
getOneItem(sP, "Enter starting power: ",
-1, "Power must be non-negative");
getOneItem(fP, "Enter ending power: ",
sP, "Ending power must be larger than starting");
end getData;
--------------------------------------------------------
-- Output the table's header rows
-- Precondition: sPow, fPow in 1 .. 99
--------------------------------------------------------
procedure putHeader(sPow, fPow: Integer; align: Alignment) is
begin
-- Start with some white space
new_line;
-- First column
if align = left then
put("I ");
for i in sPow .. fPow loop
put("I**");
put(i, 1);
if i in 1 .. 9 then
put(" ");
else
put(" ");
end if;
end loop;
elsif align = center then
put(" I ");
for i in sPow .. fPow loop
put(" I**");
put(i, 1);
if i in 1 .. 9 then
put(" ");
else
put(" ");
end if;
end loop;
else -- must be right
put(" I");
for i in sPow .. fPow loop
if i in 1 .. 9 then
put(" I**");
else
put(" I**");
end if;
put(i, 1);
end loop;
end if;
-- Columns for powers
new_line;
-- Add one to fPow to account for column for I
for i in sPow .. fPow + 1 loop
put("-----------");
end loop;
new_line;
end putHeader;
--------------------------------------------------------
-- Return the number of digits in i
--------------------------------------------------------
function length(i: Integer) return Natural is
begin
-- A quick and dirty method:
-- Subtract 1 because of the leading space
return Integer'Image(i)'length - 1;
end length;
--------------------------------------------------------
-- New procedure
-- Output v, aligned left, right, or center in ColumnWidth wide column
--------------------------------------------------------
procedure put(v: Integer; align: Alignment) is
lenV: constant Integer := length(v);
blanks: String(1..10) := (others => ' ');
numLeft, numRight: Natural;
begin
--put(v); put(lenV);
case align is
when left =>
put(v, 1);
put(blanks(1 .. ColumnWidth - lenV));
when right =>
put(blanks(1 .. ColumnWidth - lenV));
put(v, 1);
when center =>
numLeft := (ColumnWidth - lenV) / 2;
numRight := ColumnWidth - lenV - numLeft;
put(blanks(1 .. numLeft));
put(v, 1);
put(blanks(1 .. numRight));
end case;
end put;
--------------------------------------------------------
-- Output rows of the table from sInt to fInt,
-- with powers from sPow to fPow,
-- aligned as specified
--------------------------------------------------------
procedure putRows(sInt, fInt, sPow, fPow: Integer;
align: Alignment) is
tempInt: Integer;
overflow: Boolean;
begin
for i in sInt .. fInt loop
put(i, align);
for j in sPow .. fPow loop
overflow := false;
begin
tempInt := i ** j;
exception
when Constraint_Error =>
overflow := true;
end;
if not overflow then
put(tempInt, align); -- MOdified statement
else
put(" ********");
end if;
end loop;
new_line;
end loop;
end putRows;
-- Start and finish values for the rows
startI, finishI: Integer;
-- Start and finish values for the columns
startPower, finishPower: Integer;
-- Start and finish values for the columns
align: Alignment;
begin
getData(StartI, finishI, startPower, finishPower, align);
putHeader(startPower, finishPower, align);
putRows(startI, finishI, startPower, finishPower, align);
end table5;