comp.lang.ada
 help / color / mirror / Atom feed
* Newbie Question: Integer_IO an Data_error
@ 2009-03-26 21:57 Zachary Kline
  2009-03-26 22:18 ` Tim Rowe
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Zachary Kline @ 2009-03-26 21:57 UTC (permalink / raw)


Hi all,
I'm quite new to the world of Ada, and currently trying to come to grips
with it.
I wrote for my own amusement a simple number-guessing game, which
works mostly as I intended.  The problem comes when handling
exceptions.  I can handle the case where a user typed a number too large
or too small: that's a Constraint_Error, and I just prompt again and
read another guess.  The problem comes with Data_errors: if I try to
handle that case the same way, we get a seemingly infinite loop.
I'm using Gnat 4.24 on Slackware Linux, if that matters.
Code for the procedure in question is below:
        procedure Get_Guess (Target : out Guess) is
        begin
           Put ("Your guess: ");
           Get(Target);
        exception when Constraint_Error => Put_Line ("Please, numbers from one to a hundred only.");
           Put ("Your guess: ");
           Get (Target);
           when Data_Error => Put_Line ("Numbers only, please.");
              Put ("Your guess: ");
              Get (Target);
                      when others => raise;
        end Get_Guess;
Any advice would be greatly appreciated.
Best and thanks,
Zack.
-- 
Love:
When you like to think of someone on days that begin with a morning.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Newbie Question: Integer_IO an Data_error
  2009-03-26 21:57 Newbie Question: Integer_IO an Data_error Zachary Kline
@ 2009-03-26 22:18 ` Tim Rowe
  2009-03-26 23:57   ` Zachary Kline
                     ` (2 more replies)
  2009-03-27  5:15 ` anon
  2009-03-27  8:54 ` Dmitry A. Kazakov
  2 siblings, 3 replies; 9+ messages in thread
From: Tim Rowe @ 2009-03-26 22:18 UTC (permalink / raw)


Zachary Kline wrote:
> The problem comes with Data_errors: if I try to
> handle that case the same way, we get a seemingly infinite loop.


I'm an Ada newbie too, but the first thing I wonder is what Get does 
with the input characters if they don't match the expected type. I 
wonder whether it leaves them on the input stream -- in which case 
subsequent attempts to read the input will try to read the same 
characters each time. Until somebody who knows what they're talking 
about comes along (won't be long) I'd try doing a string Get after a 
failed numeric get, to see what's still in the input stream.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Newbie Question: Integer_IO an Data_error
  2009-03-26 22:18 ` Tim Rowe
@ 2009-03-26 23:57   ` Zachary Kline
  2009-03-27  0:23     ` Tim Rowe
  2009-03-27  0:03   ` Adam Beneschan
  2009-03-27  8:59   ` Jean-Pierre Rosen
  2 siblings, 1 reply; 9+ messages in thread
From: Zachary Kline @ 2009-03-26 23:57 UTC (permalink / raw)


This works, after a fashion.  I suspec the problem does indeed have to
do with the input stream.  The solution of doing a string get seems
needlessly hack-ish.
That being said, I'm sure a simpler approach exists, though I can't find
a function to flush the stream.
Thanks much,
Zack.

-- 
Love:
When you like to think of someone on days that begin with a morning.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Newbie Question: Integer_IO an Data_error
  2009-03-26 22:18 ` Tim Rowe
  2009-03-26 23:57   ` Zachary Kline
@ 2009-03-27  0:03   ` Adam Beneschan
  2009-03-27  0:19     ` Zachary Kline
  2009-03-27  8:59   ` Jean-Pierre Rosen
  2 siblings, 1 reply; 9+ messages in thread
From: Adam Beneschan @ 2009-03-27  0:03 UTC (permalink / raw)


On Mar 26, 3:18 pm, Tim Rowe <spamt...@tgrowe.plus.net> wrote:
> Zachary Kline wrote:
> > The problem comes with Data_errors: if I try to
> > handle that case the same way, we get a seemingly infinite loop.
>
> I'm an Ada newbie too, but the first thing I wonder is what Get does
> with the input characters if they don't match the expected type. I
> wonder whether it leaves them on the input stream -- in which case
> subsequent attempts to read the input will try to read the same
> characters each time. Until somebody who knows what they're talking
> about comes along (won't be long)

I'm sure you're right, that it won't be long.  In the meantime, you're
stuck with me.

Anyway, A.10.8(8) says that Get (in Integer_IO), when Width=0, "reads
the longest possible sequence of characters matching the syntax of a
numeric literal without a point".  [I presume they mean "decimal
point" and aren't making any commentary about whether the number you
read will be useful or not.]  The way I interpret this, if the first
character in the input stream (past any leading blanks) is something
other than a digit or a sign, the longest possible sequence is zero
characters.  It's not 100% clear, since a zero-character sequence
doesn't match the syntax of a numeric literal either, but that's what
I think should happen.  So if it can't read any integer, it will leave
everything in the input stream (other than leading blanks).  I think
that if there's a sign followed by garbage, it will swallow up the
sign before raising Data_Error, though.

So this does result in an "infinite" loop, although that won't happen
the way the OP coded it:

         exception when Constraint_Error => Put_Line ("Please, numbers
from one to a hundred only.");
           Put ("Your guess: ");
           Get (Target);
           when Data_Error => Put_Line ("Numbers only, please.");
              Put ("Your guess: ");
              Get (Target);

The Get calls that appear in the exception handler are *not*
controlled by the exception handlers.  So if another Constraint_Error
or Data_Error occurs in those Get calls, it won't loop back and
execute the same exception handler, but will rather look for an
*outside* exception handler that catches the exceptions, or die if
there isn't one.  To write this properly, you'll need to write a loop,
perhaps

      Ch : Character;
   begin
      Input_Loop:
      loop
          begin
             Put ("Your guess: ");
             Get (Target);
             exit Input_Loop;
          exception
             when Constraint_Error =>
                Put_Line ("Please, numbers from one to a hundred
only");
             when Data_Error =>
                Put_Line ("Numbers only, please");
                Get (Ch);  -- or something else
          end;
      end loop Input_Loop;
   end Get_Guess;

 I'd try doing a string Get after a
> failed numeric get, to see what's still in the input stream.

Get(Ch) would eat the next character in the input stream if there's a
Data_Error; more likely, you'd want to say Skip_Line to throw away
everything in the rest of the line, but that depends on how you want
the program to work.

                               -- Adam



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Newbie Question: Integer_IO an Data_error
  2009-03-27  0:03   ` Adam Beneschan
@ 2009-03-27  0:19     ` Zachary Kline
  0 siblings, 0 replies; 9+ messages in thread
From: Zachary Kline @ 2009-03-27  0:19 UTC (permalink / raw)


Adam Beneschan <adam@irvine.com> writes:
> Get(Ch) would eat the next character in the input stream if there's a
> Data_Error; more likely, you'd want to say Skip_Line to throw away
> everything in the rest of the line, but that depends on how you want
> the program to work.
This does precisely what I was looking for.  Thanks, Adam.  The program
now works as expected and intended.
Hopefully Ada will continue to be as ellegant and expressive as it has
so far.  I like it.
Thanks again,
Zack.
-- 
Love:
When you like to think of someone on days that begin with a morning.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Newbie Question: Integer_IO an Data_error
  2009-03-26 23:57   ` Zachary Kline
@ 2009-03-27  0:23     ` Tim Rowe
  0 siblings, 0 replies; 9+ messages in thread
From: Tim Rowe @ 2009-03-27  0:23 UTC (permalink / raw)


Zachary Kline wrote:
> This works, after a fashion.  I suspec the problem does indeed have to
> do with the input stream.  The solution of doing a string get seems
> needlessly hack-ish.

The string Get was for diagnosis, not to leave in the final code!



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Newbie Question: Integer_IO an Data_error
  2009-03-26 21:57 Newbie Question: Integer_IO an Data_error Zachary Kline
  2009-03-26 22:18 ` Tim Rowe
@ 2009-03-27  5:15 ` anon
  2009-03-27  8:54 ` Dmitry A. Kazakov
  2 siblings, 0 replies; 9+ messages in thread
From: anon @ 2009-03-27  5:15 UTC (permalink / raw)


You must use Skip_Line procedure and remove all Gets within the 
exception handlers!

with Ada.Text_IO ;
use Ada.Text_IO ;

function test return integer is -- just for the fun of it

  type Guess is new Integer ;
  package I_IO is new  Ada.Text_IO.Integer_IO ( Guess ) ;
  use I_IO ;

  procedure Get_Guess (Target : out Guess) is
    begin
      new_line ;
      Put ("Your guess: ");
      Get(Target);
    exception 
      when Constraint_Error => 
           Put_Line ("Please, numbers from one to a hundred only.");
      when Data_Error => 
           Put_Line ("Numbers only, please.");
      when others => 
           raise ;
    end Get_Guess;


  Temp : Guess := 0 ;

begin

  loop 
    begin 
      Get_Guess ( Temp ) ;
      Put_Line ("Done");
      exit when temp = 6 ;
    exception
      when others => 
          Put_Line ("Bad Data");
          return -7 ;
    end ;
    Skip_Line ;
  end loop ;

  return 0 ;

exception
  when others => 
    return -1 ;
end test ;




In <873ad0ueva.fsf@babel.localdomain>, Zachary Kline <kline.zachary@gmail.com> writes:
>Hi all,
>I'm quite new to the world of Ada, and currently trying to come to grips
>with it.
>I wrote for my own amusement a simple number-guessing game, which
>works mostly as I intended.  The problem comes when handling
>exceptions.  I can handle the case where a user typed a number too large
>or too small: that's a Constraint_Error, and I just prompt again and
>read another guess.  The problem comes with Data_errors: if I try to
>handle that case the same way, we get a seemingly infinite loop.
>I'm using Gnat 4.24 on Slackware Linux, if that matters.
>Code for the procedure in question is below:
>        procedure Get_Guess (Target : out Guess) is
>        begin
>           Put ("Your guess: ");
>           Get(Target);
>        exception when Constraint_Error => Put_Line ("Please, numbers from one to a hundred only.");
>           Put ("Your guess: ");
>           Get (Target);
>           when Data_Error => Put_Line ("Numbers only, please.");
>              Put ("Your guess: ");
>              Get (Target);
>                      when others => raise;
>        end Get_Guess;
>Any advice would be greatly appreciated.
>Best and thanks,
>Zack.
>-- 
>Love:
>When you like to think of someone on days that begin with a morning.




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Newbie Question: Integer_IO an Data_error
  2009-03-26 21:57 Newbie Question: Integer_IO an Data_error Zachary Kline
  2009-03-26 22:18 ` Tim Rowe
  2009-03-27  5:15 ` anon
@ 2009-03-27  8:54 ` Dmitry A. Kazakov
  2 siblings, 0 replies; 9+ messages in thread
From: Dmitry A. Kazakov @ 2009-03-27  8:54 UTC (permalink / raw)


On Thu, 26 Mar 2009 14:57:13 -0700, Zachary Kline wrote:

> I wrote for my own amusement a simple number-guessing game, which
> works mostly as I intended.  The problem comes when handling
> exceptions.  I can handle the case where a user typed a number too large
> or too small: that's a Constraint_Error, and I just prompt again and
> read another guess.  The problem comes with Data_errors: if I try to
> handle that case the same way, we get a seemingly infinite loop.

A general advise is that when you read user input do not parse it as you
read. That cannot work.

Instead of that, read the whole line and then parse the string obtained,
using Ada.Text_IO.Integer_IO (or something better):

   type Guess is new Integer;
   package Guess_IO is new Ada.Text_IO.Integer_IO (Guess);

   use Guess_IO;
   function Get_Guess return Guess is
      Result : Guess;
   begin
      loop
         Put ("Your guess:");
         declare
            Line : constant String := Get_Line;
            Last : Positive;
         begin
            Get (Line, Result, Last);
            if Last = Line'Last then
               return Result;
            end if;
            Put_Line ("Unrecognized text after the number");
         exception
            when Constraint_Error =>
               Put_Line ("Out of range");
            when Data_Error =>
               Put_Line ("Not a number");
            when End_Error =>
               Put_Line ("Nothing found");
         end;
      end loop;
   end Get_Guess;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Newbie Question: Integer_IO an Data_error
  2009-03-26 22:18 ` Tim Rowe
  2009-03-26 23:57   ` Zachary Kline
  2009-03-27  0:03   ` Adam Beneschan
@ 2009-03-27  8:59   ` Jean-Pierre Rosen
  2 siblings, 0 replies; 9+ messages in thread
From: Jean-Pierre Rosen @ 2009-03-27  8:59 UTC (permalink / raw)


Tim Rowe a �crit :
> Zachary Kline wrote:
>> The problem comes with Data_errors: if I try to
>> handle that case the same way, we get a seemingly infinite loop.
> 
> 
> I'm an Ada newbie too, but the first thing I wonder is what Get does
> with the input characters if they don't match the expected type. I
> wonder whether it leaves them on the input stream -- in which case
> subsequent attempts to read the input will try to read the same
> characters each time. Until somebody who knows what they're talking
> about comes along (won't be long) I'd try doing a string Get after a
> failed numeric get, to see what's still in the input stream.

When a character is incorrect, the current position stays on it, to
allow you to do a Get(Char) and see what happened. OTOH, it means that
you must do a skip_line to get rid of the remaining of the line, and get
a fresh one. A typical reading loop is:

loop
   begin
      Get (N);
      exit;    -- OK, no exception
   exception
      when Data_Error =>
         Skip_Line;
         Put_Line ("Error, try again");
   end;
end loop;

-- 
---------------------------------------------------------
           J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr



^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2009-03-27  8:59 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-26 21:57 Newbie Question: Integer_IO an Data_error Zachary Kline
2009-03-26 22:18 ` Tim Rowe
2009-03-26 23:57   ` Zachary Kline
2009-03-27  0:23     ` Tim Rowe
2009-03-27  0:03   ` Adam Beneschan
2009-03-27  0:19     ` Zachary Kline
2009-03-27  8:59   ` Jean-Pierre Rosen
2009-03-27  5:15 ` anon
2009-03-27  8:54 ` Dmitry A. Kazakov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox