Ada Text_IO Put printing out after Get - ada

I am trying to get a character input from the user in this format:
Player 1: a
This is my code:
Ada.Text_IO.Put("Player"&Integer'Image(board.turn)&": ");
Ada.Text_IO.Get(Item => move);
Now, when I run my program this is what happens:
a
Player 1:
For some odd reason, the GET is appearing before the PUT... I tried flipping their positions and it still occurs the same way.
I recently upgraded my AdaCore GNAT from 2012 to 2014 and I didn't have this issue in 2012...
Am I missing something?
Please help!
These are my with/use if you need them:
with Ada.Text_IO, Ada.Characters.Handling;
with Ada.Exceptions; use Ada.Exceptions;
USE Ada, Ada.Text_Io;
NEW
Here is more code... Don't worry about the AI stuff...
Full code:
PROCEDURE Main IS
PACKAGE board is new connectfour;
USE board;
begin
PUT(" ********** CONNECT-FOUR *********"); Put_Line("");
AI.start;
while (not board.isFull) loop
if AIwin = true then goto Win; end if;
Put_Line(""); DELAY 0.5;
Put("Player"&Integer'Image(board.turn)&": ");
Get(move);
if move='0' then goto Quit; end if;
Put_Line("");
if board.Move(move) = true then goto Win; end if;
board.print; DELAY 0.5;
AI.print;
end loop;
<<Win>>
Put_Line("");
Put_Line("PLAYER"&Integer'Image(board.turn)&" IS THE WINNER!");
<<Quit>>
AI.stop;
Put_Line("");
if move='0' then
Put_Line("PLAYER"&Integer'Image(board.turn)&" HAS FORFEIT!");
if board.turn = 1 then
Put_Line("PLAYER 2 IS THE WINNER!");
else
Put_Line("PLAYER 1 IS THE WINNER BY DEFAULT!");
end if;
end if;
end Main;

The standard output may be being buffered. Try
Ada.Text_IO.Put("Player"&Integer'Image(board.turn)&": “);
Ada.Text_IO.Flush;
Ada.Text_IO.Get(Item => move);
(later)
Well, that wasn’t the answer. I just tried
with Ada.Text_IO;
procedure Borovez is
Move : Character;
begin
Ada.Text_IO.Put ("Player" & Integer'Image (42) & ": ");
-- Ada.Text_IO.Flush;
Ada.Text_IO.Get (Item => Move);
end Borovez;
on GNAT GPL 2014/Windows 7 and it worked exactly as expected.
You’re going to need to edit your question to include a Minimal, Complete, and Verifiable example.

Related

Gnat 2020 non-preemptive tasking windows

I am trying to achieve true non-preemptive tasking using gnat 2020 CE on a windows 10 environment. I have placed this in the gnat.adc file:
pragma Task_Dispatching_Policy(Non_Preemptive_FIFO_Within_Priorities);
Without this gnat.adc setting, the tasks switched back and forth a great deal, as you would expect with preemptive tasking. Putting the pragma in the gnat.adc file seemed to affect the granularity of the task switching on my test program below, in that it lengthened the time that each task executed consecutive loops, but they still switched over to each other eventually. Here is the test program:
with Ada.Text_IO; Use Ada.Text_Io;
procedure Test is
Task Type One is
End;
Task Type Two;
Task body One is
x : Integer := 0;
Begin
put_line("one");
Loop
x:=x+1;
if x > 10000000 Then
exit;
end if;
End Loop;
Put_line("Task one done, x=" & x'img);
End;
Task body Two is
x : Integer := 0;
Begin
put_line("two");
Loop
x:=x+1;
if x > 1000 Then
exit;
end if;
End Loop;
Put_line("Task two done, x=" & x'img);
End;
a : One;
B : two;
begin
Null;
End;
Here is the compile line:
gnatmake -gnat2012 -gnatX -f -g test.adb -gnatwA -I. -I.. -D obj
And here is the output:
one
two
Task two done, x= 1001
Task one done, x= 10000001
I expected the opposite, that task one would execute first, which it did, but that it would also finish first because there's no reason for it to yield to two without preemption. It looks to me like I am not actually getting non-preemptive tasking, and I would like to know why.
Thanks in advance.
edit
After looking at Jeffery's comment, I found the 2012 attribute 'with CPU', and produced test code :
With System.Multiprocessors; use System.Multiprocessors;
with Ada.Text_IO; Use Ada.Text_Io;
procedure Test is
Task Type One with Cpu=>1 is
End;
Task Type Two with Cpu=> 1 is
end;
x,y : integer := 0;
limit : integer := 1000000;
Task body One is
Begin
put_line("one");
Loop
if y > 0 then
raise tasking_error;
end if;
x:=x+1;
if x > limit Then
exit;
end if;
End Loop;
Put_line("Task one done, x=" & x'img);
Exception
When others =>
put_line("task one died, x=" & x'img);
End;
Task body Two is
Begin
put_line("two");
Loop
y:=y+1;
if y > limit Then
exit;
end if;
End Loop;
Put_line("Task two done, y=" & y'img);
Exception
When others =>
put_line("task two died");
End;
a : One;
B : two;
begin
put_line(Number_Of_CPUs'img & " cpu's");
While (x < limit+1) or (y < limit+1) loop
Delay 0.0;
End Loop;
put_line("main done, x " & x'img & " y " & y'img);
End;
which produces output
one
two
24 cpu's
task one died, x= 310528
Task two done, y= 1000001
^C
(of course, I have to ctl-c out since main never finishes.)
This happens whether or not I have the scheduling pragma in gnat.adc. Does Windows just not respect processor assignment and/or the scheduling pragma?

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;

Starting tasks again

I recently started Ada programming and now I'm stuck.
I created a program with multiple tasks. The main-task is managing incoming communication and as a consequence starts working-tasks or transfers data to the working-tasks.
The working-tasks are all of the same kind but with different identifiers.
They do their work and should finish after that. For example:
task body Access_Protected is
begin
accept Start(foo: in Integer; foo2: out Integer)
do something
end Start;
while Go_loop loop
select
accept Quit do
Go_loop := false;
end Quit;
or
accept Insert(foo3: in Integer)
do something
if something = 0 then
Go_loop := false;
end if;
end Insert;
or delay 2.0;
end select;
end loop;
end Access_Protected;
I understand that the working-task should be terminated when the Go_loop is finished. Am I right?
It works to start the task one time but when the main-task tries to restart the working-task by calling the Start procedure, nothing happens.
Can someone please tell me which point I am missing.
A task and subprogram are somewhat related in that when the body is completed the construct ends, this is to say that the construct ends with it's appropriate end; in the case of a procedure control returns to the caller, in the case of a function the exception PROGRAM_ERROR is raised, and in the case of a task the controlling "thread" terminates.
What's happening in your particular problem, it seems, boils down to the following:
Package Example is
Task Type Message_Task is
Entry Execute;
End Message_Task;
End Example;
Package Body Example is
Task Body Message_Task is
Use Ada.Text_IO;
Begin
accept Execute do
Put_Line( "Rendezvous!" );
end Execute;
delay 0.2; -- Stub delay.
Put_Line( "Finishing Task." );
-- Task Ends Here.
End Message_Task;
End Example;
--...
Test : Example.Message_Task;
--...
Test.Execute;
-- Test.Execute can't be accepted here because it can only accept "Execute"
-- the one time, as per the body's definition.
The reason that this really is like your problem is because, likewise once you say "X.Start(1,2)" another call to Start doesn't reset the position of the task's execution back up to that accept.
If you wanted the task to "stay alive" for further processing you could do one of two options.
Option 1 -- set up a 'protocol':
Package Example is
Task Type Message_Task is
Entry Initialization;
Entry Execute;
Entry Quit;
End Message_Task;
End Example;
Package Body Example is
Task Body Message_Task is
Use Ada.Text_IO;
Has_quit : Boolean := False;
Begin
Main:
loop
select
accept Initialization do
null;
end Initialization;
accept Execute do
null;
end Execute;
or
accept Quit do
Has_Quit := True;
end Quit;
end select;
Exit Main when Has_Quit;
end loop Main;
End Message_Task;
End Example;
Option 2 -- Allow termination.
Package Example is
Task Type Message_Task is
Entry Initialization;
Entry Execute;
End Message_Task;
End Example;
Package Body Example is
Task Body Message_Task is
Use Ada.Text_IO;
Has_quit : Boolean := False;
Begin
accept Initialization do
null;
end Initialization;
Main:
loop
select
accept Execute do
null;
end Execute;
or
terminate;
end select;
end loop Main;
End Message_Task;
End Example;
The subtle difference is Option 2 gets rid of the Quit entry, allowing the task to 'rest' on the terminate alternative while Option 1 is more explicit in control (and required in some cases), but requiring that Initialization & Execute be called in pairs.
A task only runs until it reaches the end of its main sequence of statements (ignoring various technicalities).
If you want a task to do something, and then pause until it receives an external trigger, you should put a loop around the statements you have in the task body.

"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);

On keydown in Ada

I would need to execute some function when the user presses the "escape" key in my Ada program. I know we can retrieve what he enters thanks to get_line but it's not exactly what I need to do.
Indeed, I don't want to stop the program until he enters "escape".
First, is it possible ?
It is possible to get the characters without the need to press enter using :
Ada.Text_IO.Get_Immediate (Answer)
with Answer, a Character.
And the escape key is ASCII 27, so you can check whether Character'Pos(Answer) equals 27 or not. Also, as suggested in the comments, you can also compare Answer to Ada.Characters.Latin_1.ESC.
Here is an example of a program that display "Yeah!!!1!!1!" in a loop until the key ESC is pressed.
with Ada.Characters.Latin_1;
with Ada.Text_IO;
procedure Test is
Finished : Boolean := False;
task Escape_Task;
task body Escape_Task is
Answer : Character;
begin
loop
Ada.Text_IO.Get_Immediate(Answer);
if Answer = Ada.Characters.Latin_1.ESC then
Finished := True;
exit;
end if;
end loop;
end Escape_Task;
begin
while not finished loop
Ada.Text_IO.Put_Line("Yeahh!!!1!!1!");
end loop;
end Test;

Resources