comp.lang.ada
 help / color / mirror / Atom feed
* get_line
@ 1998-06-05  0:00 Steve Dyrdahl
  1998-06-05  0:00 ` get_line Samuel Mize
  1998-06-06  0:00 ` get_line Dale Stanbrough
  0 siblings, 2 replies; 37+ messages in thread
From: Steve Dyrdahl @ 1998-06-05  0:00 UTC (permalink / raw)



I have a problem that seems fairly simple.

Suppose the following:

type name_array is array (1..10) of string (1..15);

names  : name_array;
length : natural;


Then:

for I in name_array'range loop
   get_line (names(I),length);
end loop;


The problem (on our Unix system anyway) is that if the user types more
characters than the string will hold.  The "leftover" characters are still
left in the input buffer and will be read on the next execution of the
loop.

I am wondering if there is a clean solution for flushing the input buffer
to avoid this problem.  Obviously I could write my own version of get_line
to avoid this problem, but I try to avoid reinventing the wheel whenever
possible.

Steve Dyrdahl





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

* Re: get_line
  1998-06-05  0:00 get_line Steve Dyrdahl
@ 1998-06-05  0:00 ` Samuel Mize
  1998-06-17  0:00   ` get_line Hans Marqvardsen
  1998-06-06  0:00 ` get_line Dale Stanbrough
  1 sibling, 1 reply; 37+ messages in thread
From: Samuel Mize @ 1998-06-05  0:00 UTC (permalink / raw)



In article <Pine.OSF.3.95.980605111447.22858A-100000@esus.cs.montana.edu>,
Steve Dyrdahl  <dyrdahl@esus.cs.montana.edu> wrote:

>The problem (on our Unix system anyway) is that if the user types more
>characters than the string will hold.  The "leftover" characters are still
>left in the input buffer and will be read on the next execution of the
>loop.

This isn't Unix, it's Ada.

>I am wondering if there is a clean solution for flushing the input buffer

Get_Line stops reading if you ran out of space in your string buffer.  So,
you need to check for that, and call Skip_Line:

      Get_Line (S, Last);
      if Last = S'Last then
        Skip_Line;
      end if;

You could put this into a procedure, that will then behave as you expected
Get_Line to do.

If you want to avoid a possible exception on end of file, use:

      if Last = S'Last and then not End_Of_File then

Here's another useful wheel for you, if you have web access: Deja News,
http://www.dejanews.com .  I did a "power search" (lets you search a
specific newsgroup) in comp.lang.ada with "+get_line +end +line" and got
53 matching postings, of which at least five answered your question.
(After that I quit reading them.)

I don't point this out to be pissy about frequently asked questions
-- OK, well, not JUST to be pissy.  I use Deja News all the time for
this kind of question, and it's not only useful for reducing the
bandwidth, it's a MUCH faster way to get your answer.

(The plus sign means "must include this word", otherwise you get, e.g.,
posts that include "get_line" and "end" but not "line").

No affiliation with Deja News, YMMV, no warranty express or implied.

Best,
Sam Mize

-- 
Samuel Mize -- smize@imagin.net (home email) -- Team Ada
Multi-part MIME message: " ", " ", " " (hands waving)
Fight Spam - see http://www.cauce.org/




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

* Re: get_line
  1998-06-05  0:00 get_line Steve Dyrdahl
  1998-06-05  0:00 ` get_line Samuel Mize
@ 1998-06-06  0:00 ` Dale Stanbrough
  1998-06-06  0:00   ` get_line Robert Dewar
  1998-06-06  0:00   ` get_line Matthew Heaney
  1 sibling, 2 replies; 37+ messages in thread
From: Dale Stanbrough @ 1998-06-06  0:00 UTC (permalink / raw)



Samuel Mize writes:

"Get_Line stops reading if you ran out of space in your string buffer. 
So,
 you need to check for that, and call Skip_Line:
 
       Get_Line (S, Last);
       if Last = S'Last then
         Skip_Line;
       end if;
 
 You could put this into a procedure, that will then behave as you
expected
 Get_Line to do.


Well, no, not quite always. If there are the exact number of characters
in the input as will fit in the string, then it will automatically skip
the end of line. The code above would then skip the following line as
well.

The solution is to read the characters in char by char. It is
unfortunate that Get_Line has such a weak postcondition.

Dale




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

* Re: get_line
  1998-06-06  0:00 ` get_line Dale Stanbrough
@ 1998-06-06  0:00   ` Robert Dewar
  1998-06-06  0:00   ` get_line Matthew Heaney
  1 sibling, 0 replies; 37+ messages in thread
From: Robert Dewar @ 1998-06-06  0:00 UTC (permalink / raw)



Dale said

<<The solution is to read the characters in char by char. It is
unfortunate that Get_Line has such a weak postcondition.
>>

By far the best programming technique here is to read the line into a giant
buffer that is sure to be long enough, and then program what you want done
with the string depending on the length.

Reading it in directly as in the original program is clearly bad practice,
since it leaves undefined junk if the string is too short.





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

* Re: get_line
  1998-06-06  0:00 ` get_line Dale Stanbrough
  1998-06-06  0:00   ` get_line Robert Dewar
@ 1998-06-06  0:00   ` Matthew Heaney
  1998-06-07  0:00     ` get_line Dale Stanbrough
  1998-06-18  0:00     ` get_line Robert I. Eachus
  1 sibling, 2 replies; 37+ messages in thread
From: Matthew Heaney @ 1998-06-06  0:00 UTC (permalink / raw)



Dale Stanbrough <dale@goanna.cs.rmit.edu.au> writes:

> Well, no, not quite always. If there are the exact number of characters
> in the input as will fit in the string, then it will automatically skip
> the end of line. The code above would then skip the following line as
> well.

I don't think the statement above is correct.

If there are the same number of characters in the input line as the
input buffer, Get_Line will NOT do an end-of-line automatically.  The
next Get_Line will in fact return 0 as the value of last.  (It's the 2nd
call the Get_Line that consumes the end-of-line.)

The test to make sure all of the text on the line has been
consumed is

   Last < Input_Buffer'Last

which means "you have read all the text on the current line."

To use this predicate, you'll have to make your buffer size 1 more than
the advertised maximum.

These issues and techniques are described in John Barnes' book.

> The solution is to read the characters in char by char. It is
> unfortunate that Get_Line has such a weak postcondition.

I don't think a character-by-character read is required.

Yes, it probably seems weird that you have to allocate an extra
character in your input buffer.  But you just have to do that in order
to make the test 

   if Last < Line'Last then ...;

Here is a little program that illustrates how to properly read a
maximum-sized input line.

Note that when the input is equal to the max length (5), the line
terminator is consumed, as expected.  (This is because the actual buffer
has length 6.)

Lines larger than the advertised max length are flagged as too long, and
the rest of the input line is consumed.


with Ada.Text_IO; use Ada.Text_IO;

procedure Test_Get_Line is

   Max_Length : constant Positive := 5;

   Line : String (1 .. Max_Length + 1);
   Last : Natural;

begin

   loop
      Put ("Ready: ");
      Get_Line (Line, Last);
      exit when Last = 0;

      if Last < Line'Last then
         Put_Line ("Entry '" & Line (1 .. Last) & "' is OK.");
      else
         Skip_Line;
         Put_Line ("Entry was too long.");
      end if;
   end loop;

end Test_Get_Line;


$ test_get_line
Ready: 1
Entry '1' is OK.
Ready: 12
Entry '12' is OK.
Ready: 123
Entry '123' is OK.
Ready: 1234
Entry '1234' is OK.
Ready: 12345
Entry '12345' is OK.
Ready: 123456
Entry was too long.
Ready: 1234567
Entry was too long.
Ready: 123456
Entry was too long.
Ready: 12345
Entry '12345' is OK.
Ready: 1234
Entry '1234' is OK.
Ready: 123
Entry '123' is OK.
Ready: 12
Entry '12' is OK.
Ready: 1
Entry '1' is OK.
Ready: 




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

* Re: get_line
  1998-06-07  0:00     ` get_line Dale Stanbrough
@ 1998-06-06  0:00       ` Matthew Heaney
  0 siblings, 0 replies; 37+ messages in thread
From: Matthew Heaney @ 1998-06-06  0:00 UTC (permalink / raw)



Dale Stanbrough <dale@goanna.cs.rmit.edu.au> writes:

> Yes you are correct. I didn't write exactly what i should have, I can 
> now see! What i should have said is "if you do read in exactly the number
> of characters as are in the buffer, then you really don't know what
> situation you are in - you can still never tell if a skip_line was
> called".

I'm still confused by your answer.

I'm confused, because you definately can tell what state you're in, if
the buffer size is the same as the number of input characters, because
the rule for this case is "No, skip line is NOT called."

This very issue was the subject of an AI.

To determine when you're finished consuming all the text on a line, the
definitive test is

  if Last < Line'Last then
    <all done>
  else
    <there's more to read, possibly just a line terminator>
  end if;

Which is why I said to make the Line'Last greater than the maximum
number of input characters: so you can write that predicate.  I like to
do this:

declare
   Max_Length : constant Positive := <whatever>;
   Line : String (1 .. Max_Length + 1);
   Last : Natural;
begin
   Get_Line (Line, Last);

   if Last <= Max_Length then
      <we got all the input, including the line terminator>
   else
      <input line is too long for buffer; handle error>
   end if;
end;

If the user enters Max_Length characters, then all is well, and
Skip_Line is called automatically.

If the user enters more than max_length characters, then Skip_Line is
definately NOT called.  This you know, because the language says so.











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

* Re: get_line
  1998-06-06  0:00   ` get_line Matthew Heaney
@ 1998-06-07  0:00     ` Dale Stanbrough
  1998-06-06  0:00       ` get_line Matthew Heaney
  1998-06-18  0:00     ` get_line Robert I. Eachus
  1 sibling, 1 reply; 37+ messages in thread
From: Dale Stanbrough @ 1998-06-07  0:00 UTC (permalink / raw)



Matthew Heaney writes:

"If there are the same number of characters in the input line as the
 input buffer, Get_Line will NOT do an end-of-line automatically.  The
 next Get_Line will in fact return 0 as the value of last.  (It's the 2nd
 call the Get_Line that consumes the end-of-line.)
 
 The test to make sure all of the text on the line has been
 consumed is
 
    Last < Input_Buffer'Last
 
 which means "you have read all the text on the current line."
 
 To use this predicate, you'll have to make your buffer size 1 more than
 the advertised maximum."


Yes you are correct. I didn't write exactly what i should have, I can 
now see! What i should have said is "if you do read in exactly the number
of characters as are in the buffer, then you really don't know what
situation you are in - you can still never tell if a skip_line was
called".

Dale




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

* Re: get_line
  1998-06-05  0:00 ` get_line Samuel Mize
@ 1998-06-17  0:00   ` Hans Marqvardsen
  1998-06-18  0:00     ` get_line John McCabe
  0 siblings, 1 reply; 37+ messages in thread
From: Hans Marqvardsen @ 1998-06-17  0:00 UTC (permalink / raw)



Samuel Mize wrote:
> 
> Here's another useful wheel for you, if you have web access: Deja News,
> http://www.dejanews.com .  I did a "power search" (lets you search a
> specific newsgroup) in comp.lang.ada with "+get_line +end +line" and got
> 53 matching postings, of which at least five answered your question.
> (After that I quit reading them.)
> 
> I don't point this out to be pissy about frequently asked questions
> -- OK, well, not JUST to be pissy.  I use Deja News all the time for
> this kind of question, and it's not only useful for reducing the
> bandwidth, it's a MUCH faster way to get your answer.

Thank you very much for this most useful tip.  Your tip just solved a
similar, but different,  problem for me. -- Regrettably, I did not 
see your tip in time to avoid one more futile posting, Hans.




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

* Re: get_line
  1998-06-17  0:00   ` get_line Hans Marqvardsen
@ 1998-06-18  0:00     ` John McCabe
  1998-06-21  0:00       ` get_line Robert Dewar
  0 siblings, 1 reply; 37+ messages in thread
From: John McCabe @ 1998-06-18  0:00 UTC (permalink / raw)



Hans Marqvardsen <hm@ddre.dk> wrote:
>Samuel Mize wrote:

>> I don't point this out to be pissy about frequently asked questions
>> -- OK, well, not JUST to be pissy.  I use Deja News all the time for
>> this kind of question, and it's not only useful for reducing the
>> bandwidth, it's a MUCH faster way to get your answer.
>
>Thank you very much for this most useful tip.  Your tip just solved a
>similar, but different,  problem for me. -- Regrettably, I did not 
>see your tip in time to avoid one more futile posting, Hans.

While this is (of course) a useful tip, it is not always possible some 
companies provide access to newsgroups but not web sites.

Now if there is a means of accessing dejanews through a newsgroup I may 
be interested.

-- 
Best Regards
John McCabe

=====================================================================
Not necessarily my company or service providers opinions.
=====================================================================






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

* Re: get_line
  1998-06-06  0:00   ` get_line Matthew Heaney
  1998-06-07  0:00     ` get_line Dale Stanbrough
@ 1998-06-18  0:00     ` Robert I. Eachus
  1 sibling, 0 replies; 37+ messages in thread
From: Robert I. Eachus @ 1998-06-18  0:00 UTC (permalink / raw)



In article <m3zpfqu68v.fsf@mheaney.ni.net> Matthew Heaney <matthew_heaney@acm.org> writes:

 > The test to make sure all of the text on the line has been
 > consumed is

 >    Last < Input_Buffer'Last

 > which means "you have read all the text on the current line."

 > To use this predicate, you'll have to make your buffer size 1 more than
 > the advertised maximum.

   There is another (non-obvious) way to do this which doesn't require
the odd buffer size:

   Text_IO.Get_Line(Some_Buffer,Length);
   if Ada.Text_IO.Col(Ada.Text_IO.Current_Input) /= 1
   then -- Skip Line was not called.
     Ada.Text_IO.Skip_Line;
   end if;
 
   This always works, assuming that the buffer is of non-zero length,
because Skip_Line always sets the column to one.  (Incidently there is
a typographic error in the RM at A.10.5(27), at least in the versions
I have.  The indentation is incorrect. The paragraph should be
outdented to full width as it is in Ada 83 RM 14.3.4(26).)
--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




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

* Re: get_line
  1998-06-18  0:00     ` get_line John McCabe
@ 1998-06-21  0:00       ` Robert Dewar
  0 siblings, 0 replies; 37+ messages in thread
From: Robert Dewar @ 1998-06-21  0:00 UTC (permalink / raw)



John said

<<While this is (of course) a useful tip, it is not always possible some
companies provide access to newsgroups but not web sites.
>>

This is a silly policy, and one that will waste your time and other
peoples time. If you are reading newsgroups, it is essential to have
access to deja news. If your company is deathly afraid that you might
spend time looking at "Live XXXX Girls" etc, there are tools to limit
Web access to limited sites :-)





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

* GET LINE
@ 1999-07-02  0:00 babefan
  1999-07-02  0:00 ` czgrr
  0 siblings, 1 reply; 37+ messages in thread
From: babefan @ 1999-07-02  0:00 UTC (permalink / raw)


how do you use the get line?  have a string to display.
thanks




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

* Re: GET LINE
  1999-07-02  0:00 GET LINE babefan
@ 1999-07-02  0:00 ` czgrr
  0 siblings, 0 replies; 37+ messages in thread
From: czgrr @ 1999-07-02  0:00 UTC (permalink / raw)


In article <gg3f3.15$id6.15497@ratbert.tds.net>,
  babefan@mailexcite.com wrote:
> how do you use the get line?  have a string to display.
> thanks

If you post some code which you are trying to get to work, then perhaps
we can help you out.

Cheers,
czgrr

--
No email, please - reply to the newsgroup.
My opinions are not necessarily those of my
employer.
Use any suggestions at your own risk.


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




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

* Get_Line
@ 2002-10-29 20:24 Justin Birtwell
  2002-10-29 20:55 ` Get_Line David C. Hoos
                   ` (3 more replies)
  0 siblings, 4 replies; 37+ messages in thread
From: Justin Birtwell @ 2002-10-29 20:24 UTC (permalink / raw)


Hi,

I'm having some strange behavior with Get_Line.  In a procedure called
GetData I call Get_Line to receive input from the command line. The first
time this function is called it behaves fine prompting the user for input.
The second time it runs  the execution passes through Get_Line and no prompt
appears on the command line.  Upon doing a little research in the Ref Man.
I found a statement that talks about if Get_Line finds a line terminator it
automatically returns.  But how can this be?   Here's the statement from the
RM.

<< A string read by Get or written by Put can extend over several lines. An
implementation is allowed to assume that certain external files do not
contain page terminators, in which case Get_Line and Skip_Line can return as
soon as a line terminator is read. >>

But I'm not reading from a file?  I'm reading from the command line?  Does
anyone understand this behavior?

Sincerely,
Justin

P.s.  Here's a few statements leading up to the problem...

   procedure Getdata(P_Num_Of_Points: out Natural) is
      Last:Natural:=0;
      Buffer:String(1..80):=(1..80=>Character'val(0));
      l_Num:Integer;
      --Answer:Character;
   begin

      --get input
      --are there any invalid characters
      --is it a valid number anyway?
      --does the user want to use this number?
         Ada.Text_Io.Put_Line("Enter between 1 and 6 Balloons to create in
the box. ");
      loop
         begin

                                           ---This line gets skipped
returning with an empty buffer!!!!!!!
         if Jb.Stringfunctions.Is_Integer(Buffer(Buffer'First..Last)) then







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

* Re: Get_Line
  2002-10-29 20:24 Get_Line Justin Birtwell
@ 2002-10-29 20:55 ` David C. Hoos
  2002-10-30  1:30 ` Get_Line Jeffrey Carter
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 37+ messages in thread
From: David C. Hoos @ 2002-10-29 20:55 UTC (permalink / raw)


What you're calling the "command line" is _not_ the command
line once your program starts.  It's the standard-input file, unless
you've called Ada.Text_IO.Set_Output to set it to something else.

So.. yes, you are reading from a file.

----- Original Message -----
From: "Justin Birtwell" <jbirtwell@yahoo.com>
Newsgroups: comp.lang.ada
To: <comp.lang.ada@ada.eu.org>
Sent: Tuesday, October 29, 2002 2:24 PM
Subject: Get_Line


> Hi,
>
> I'm having some strange behavior with Get_Line.  In a procedure called
> GetData I call Get_Line to receive input from the command line. The first
> time this function is called it behaves fine prompting the user for input.
> The second time it runs  the execution passes through Get_Line and no
prompt
> appears on the command line.  Upon doing a little research in the Ref Man.
> I found a statement that talks about if Get_Line finds a line terminator
it
> automatically returns.  But how can this be?   Here's the statement from
the
> RM.
>
> << A string read by Get or written by Put can extend over several lines.
An
> implementation is allowed to assume that certain external files do not
> contain page terminators, in which case Get_Line and Skip_Line can return
as
> soon as a line terminator is read. >>
>
> But I'm not reading from a file?  I'm reading from the command line?  Does
> anyone understand this behavior?
>
> Sincerely,
> Justin
>
> P.s.  Here's a few statements leading up to the problem...
>
>    procedure Getdata(P_Num_Of_Points: out Natural) is
>       Last:Natural:=0;
>       Buffer:String(1..80):=(1..80=>Character'val(0));
>       l_Num:Integer;
>       --Answer:Character;
>    begin
>
>       --get input
>       --are there any invalid characters
>       --is it a valid number anyway?
>       --does the user want to use this number?
>          Ada.Text_Io.Put_Line("Enter between 1 and 6 Balloons to create in
> the box. ");
>       loop
>          begin
>
>                                            ---This line gets skipped
> returning with an empty buffer!!!!!!!
>          if Jb.Stringfunctions.Is_Integer(Buffer(Buffer'First..Last)) then
>
>
>
>
> _______________________________________________
> comp.lang.ada mailing list
> comp.lang.ada@ada.eu.org
> http://ada.eu.org/mailman/listinfo/comp.lang.ada
>




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

* Re: Get_Line
  2002-10-29 20:24 Get_Line Justin Birtwell
  2002-10-29 20:55 ` Get_Line David C. Hoos
@ 2002-10-30  1:30 ` Jeffrey Carter
  2002-10-30 13:33   ` Get_Line Justin Birtwell
  2002-10-30 14:44 ` Get_Line Preben Randhol
  2002-10-31 21:55 ` Get_Line Matthew Heaney
  3 siblings, 1 reply; 37+ messages in thread
From: Jeffrey Carter @ 2002-10-30  1:30 UTC (permalink / raw)


Justin Birtwell wrote:
> Hi,
> 
> I'm having some strange behavior with Get_Line.  In a procedure called
> GetData I call Get_Line to receive input from the command line. The first
> time this function is called it behaves fine prompting the user for input.
> The second time it runs  the execution passes through Get_Line and no prompt
> appears on the command line.  Upon doing a little research in the Ref Man.
> I found a statement that talks about if Get_Line finds a line terminator it
> automatically returns.  But how can this be?   Here's the statement from the
> RM.
> 
> << A string read by Get or written by Put can extend over several lines. An
> implementation is allowed to assume that certain external files do not
> contain page terminators, in which case Get_Line and Skip_Line can return as
> soon as a line terminator is read. >>
> 
> But I'm not reading from a file?  I'm reading from the command line?  Does
> anyone understand this behavior?
> 
> Sincerely,
> Justin
> 
> P.s.  Here's a few statements leading up to the problem...
> 
>    procedure Getdata(P_Num_Of_Points: out Natural) is
>       Last:Natural:=0;
>       Buffer:String(1..80):=(1..80=>Character'val(0));
>       l_Num:Integer;
>       --Answer:Character;
>    begin
> 
>       --get input
>       --are there any invalid characters
>       --is it a valid number anyway?
>       --does the user want to use this number?
>          Ada.Text_Io.Put_Line("Enter between 1 and 6 Balloons to create in
> the box. ");
>       loop
>          begin
> 
>                                            ---This line gets skipped
> returning with an empty buffer!!!!!!!
>          if Jb.Stringfunctions.Is_Integer(Buffer(Buffer'First..Last)) then

This hardly gives us enough information for a precise reply. There is no 
call to Get_Line here; even if there was, we don't have the information 
to reason about the environment in which it is operating (due to other 
I/O that preceeds the call). However, questions such as this arise often 
enough that we can make an educated guess.

First, what you call the command line is a file called Standard_Input, 
so you are reading from a file. The Text_IO subprograms that do not take 
a File parameter read from Current_Input, which is Standard_Input unless 
you have changed it.

Second, if Get_Line returns Last < Buffer'First, then you've read an 
empty line. I assume this is what you mean by "an empty buffer". There 
are a number of ways this can happen. If a previous call to Get_Line 
returns Last = Buffer'Last, then that call has not skipped a line 
terminator, and that line terminator is still there, waiting to be 
skipped, probably by your next call to Get_Line. If your input line is 
exactly Buffer'Length characters long, then all that's you've left is 
the line terminator, resulting in an empty line to read next time.

Another source of empty lines is using Get from an instantion of one of 
the Ada.Text_IO generic packages such as Integer_IO. This do not skip a 
line terminator. They also cause other difficulties, so reading into a 
string first is a good ides.

You can skip the next line terminator by calling Skip_Line. Another 
approach is to use a function (often called Get_Line) that reads an 
entire line and skips the line terminator, and returns a String:

function Get_Line
    (File : Ada.Text_IO.File_Type := Ada.Text_IO.Current_Input)
return String;

This ensures that line terminators are always skipped. This is not 
something that comes with the language, so you'll either have to write 
your own or find one from somewhere else. One source is the PragmAda 
Reusable Components, which has such a function:

http://home.earthlink.net/~jrcarter010/pragmarc.htm

-- 
Jeff Carter
"Your mother was a hamster and your father smelt of elderberries."
Monty Python & the Holy Grail




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

* Re: Get_Line
  2002-10-30  1:30 ` Get_Line Jeffrey Carter
@ 2002-10-30 13:33   ` Justin Birtwell
  2002-10-30 14:40     ` Get_Line Preben Randhol
                       ` (2 more replies)
  0 siblings, 3 replies; 37+ messages in thread
From: Justin Birtwell @ 2002-10-30 13:33 UTC (permalink / raw)


Jeffery,

Thank you for your detailed response.  First I apologize for not including
the call to Get_Line() in my original post.  I'd like to make reparations by
providing the correct code at the tail of this post.

I'm running this code on my laptop (WinXP), but I don't want to write
non-portable code, meaning code that will only run on the Win32 platform.  I
believe that your assessment about the line terminator behavior with
Get_Line is the cause of the problem.  I tried calling Skip_Line immediately
after the call but with seeming no affect.  I'm going to try to find the
packages you have referred to.

Once again, thank you.  I was not aware of this phenomenon and I know it
would have taken me much effort to discover it in the RM.  If you can think
of any other approach to the problem I welcome your response.

sincerely,
Justin

P.S.  Here's my original code.

   procedure Getdata(P_Num_Of_Points: out Natural) is
      Last:Natural:=0;
      Buffer:String(1..80):=(1..80=>Character'val(0));
      l_Num:Integer;
      --Answer:Character;
   begin

      --get input
      --are there any invalid characters
      --is it a valid number anyway?
      --does the user want to use this number?
         Ada.Text_Io.Put_Line("Enter between 1 and 6 Balloons to create in
the box. ");
      loop
         begin
         Ada.Text_IO.New_Line;
            Ada.Text_Io.Get_Line(Buffer,Last);  --Here's the cause of the
problem.

    --I just added this code to see if calling Skip_Line would fix the
problem, but alas, to no effect.
            if(Buffer'First>Last) then
               Ada.Text_Io.Skip_Line;
            end if;









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

* Re: Get_Line
  2002-10-30 13:33   ` Get_Line Justin Birtwell
@ 2002-10-30 14:40     ` Preben Randhol
  2002-10-30 17:09     ` Get_Line Jean-Pierre Rosen
  2002-10-30 18:08     ` Get_Line Jeffrey Carter
  2 siblings, 0 replies; 37+ messages in thread
From: Preben Randhol @ 2002-10-30 14:40 UTC (permalink / raw)


Justin Birtwell wrote:
>     --I just added this code to see if calling Skip_Line would fix the
> problem, but alas, to no effect.


>             if(Buffer'First>Last) then

Why do you use () in the if ? Now what you should do is:

              if Buffer'Last = Last then
                 Ada.Text_Io.Skip_Line;
              end if;

What happens is that if the line you typed is longer than 80 chars as
your buffer is defined the then the get_line will only get the first 80
and next time it will get the rest until the newline. If you do as above
it will ignore any characters after the first eighty and skip to the
next line.

-- 
Preben Randhol  --------------------  http://www.pvv.org/~randhol
�.., chaos is found in greatest abundance wherever order is being
sought. It always defeats order, because it is better organized.�
                            -- Interesting Times, Terry Pratchett



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

* Re: Get_Line
  2002-10-29 20:24 Get_Line Justin Birtwell
  2002-10-29 20:55 ` Get_Line David C. Hoos
  2002-10-30  1:30 ` Get_Line Jeffrey Carter
@ 2002-10-30 14:44 ` Preben Randhol
  2002-10-31 21:55 ` Get_Line Matthew Heaney
  3 siblings, 0 replies; 37+ messages in thread
From: Preben Randhol @ 2002-10-30 14:44 UTC (permalink / raw)


Justin Birtwell wrote:
> Hi,
> 
> I'm having some strange behavior with Get_Line.  In a procedure called
> GetData I call Get_Line to receive input from the command line. The first
> time this function is called it behaves fine prompting the user for input.
> The second time it runs  the execution passes through Get_Line and no prompt
> appears on the command line.  Upon doing a little research in the Ref Man.

This is because your Put_Line is outside the loop.

> 
>    procedure Getdata(P_Num_Of_Points: out Natural) is
>       Last:Natural:=0;
>       Buffer:String(1..80):=(1..80=>Character'val(0));
>    begin
>       Ada.Text_Io.Put_Line("Enter between 1 and 6 Balloons to ..."); 
>       loop
>          begin
> 
>                                            ---This line gets skipped


-- 
Preben Randhol  --------------------  http://www.pvv.org/~randhol
�.., chaos is found in greatest abundance wherever order is being
sought. It always defeats order, because it is better organized.�
                            -- Interesting Times, Terry Pratchett



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

* Re: Get_Line
  2002-10-30 13:33   ` Get_Line Justin Birtwell
  2002-10-30 14:40     ` Get_Line Preben Randhol
@ 2002-10-30 17:09     ` Jean-Pierre Rosen
  2002-10-30 18:08     ` Get_Line Jeffrey Carter
  2 siblings, 0 replies; 37+ messages in thread
From: Jean-Pierre Rosen @ 2002-10-30 17:09 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1122 bytes --]


"Justin Birtwell" <jbirtwell@yahoo.com> a �crit dans le message news:
4dRv9.46453$wm6.7691@nwrddc01.gnilink.net...
> Jeffery,
>
> Thank you for your detailed response.  First I apologize for not including
> the call to Get_Line() in my original post.  I'd like to make reparations
by
> providing the correct code at the tail of this post.
>
> I'm running this code on my laptop (WinXP), but I don't want to write
> non-portable code, meaning code that will only run on the Win32 platform.
I
> believe that your assessment about the line terminator behavior with
> Get_Line is the cause of the problem.  I tried calling Skip_Line
immediately
> after the call but with seeming no affect.  I'm going to try to find the
> packages you have referred to.
>
[snip]
The simplest way to make sure you start a fresh line is to call set_col(1).
It will do nothing if you are already at the start of the line, and will
return you to the start of a new line in all other cases.

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





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

* Re: Get_Line
  2002-10-30 13:33   ` Get_Line Justin Birtwell
  2002-10-30 14:40     ` Get_Line Preben Randhol
  2002-10-30 17:09     ` Get_Line Jean-Pierre Rosen
@ 2002-10-30 18:08     ` Jeffrey Carter
  2002-10-30 22:42       ` Get_Line Robert A Duff
  2002-10-31  8:53       ` Get_Line Preben Randhol
  2 siblings, 2 replies; 37+ messages in thread
From: Jeffrey Carter @ 2002-10-30 18:08 UTC (permalink / raw)


I'm afraid I still don't have enough information to give a meaningful 
answer. When and under what conditions do you exit the loop? Is the 
problem observed within a single call to Getdata, or from one call to 
the next? If the latter, we need to see all the code that is executed 
between the calls, since that may affect the state of the environment.

Justin Birtwell wrote:
>     --I just added this code to see if calling Skip_Line would fix the
> problem, but alas, to no effect.
>             if(Buffer'First>Last) then
>                Ada.Text_Io.Skip_Line;
>             end if;

This calls Skip_Line if you have read an empty line. But Get_Line will 
skip the line terminator if you read an empty line (or any line with < 
Buffer'Length characters). What you want to do is call Skip_Line if 
Get_Line has not skipped the line terminator, which happens if the input 
  is >= Buffer'Length characters:

if Last >= Buffer'Last then
    Ada.Text_Io.Skip_Line;
end if;

-- 
Jeff Carter
"All citizens will be required to change their underwear
every half hour. Underwear will be worn on the outside,
so we can check."
Bananas




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

* Re: Get_Line
  2002-10-30 18:08     ` Get_Line Jeffrey Carter
@ 2002-10-30 22:42       ` Robert A Duff
  2002-10-31  0:26         ` Get_Line Chad R. Meiners
  2002-10-31  8:53       ` Get_Line Preben Randhol
  1 sibling, 1 reply; 37+ messages in thread
From: Robert A Duff @ 2002-10-30 22:42 UTC (permalink / raw)


Jeffrey Carter <jrcarter@acm.org> writes:

> ...What you want to do is call Skip_Line if
> Get_Line has not skipped the line terminator, which happens if the input
> is >= Buffer'Length characters:
> ...

This group seems to get an endless series of posts indicating confusion
about Get_Line.  Jeffrey Carter and others kindly give helpful answers,
which is good.

But isn't the *real* problem that the design of Text_IO is broken?  For
example, why is there no Get_Line function:

    function Get_Line(...) return String;

that returns the entire contents of the next line, no matter how long it
is, and without fussing about with fixed-length (i.e. wrong length!)
buffers?

- Bob



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

* Re: Get_Line
  2002-10-30 22:42       ` Get_Line Robert A Duff
@ 2002-10-31  0:26         ` Chad R. Meiners
  2002-10-31  0:44           ` Get_Line Robert A Duff
  0 siblings, 1 reply; 37+ messages in thread
From: Chad R. Meiners @ 2002-10-31  0:26 UTC (permalink / raw)



"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
news:wcc3cqn35wu.fsf@shell01.TheWorld.com...
> But isn't the *real* problem that the design of Text_IO is broken?  For
> example, why is there no Get_Line function:
>
>     function Get_Line(...) return String;
>
> that returns the entire contents of the next line, no matter how long it
> is, and without fussing about with fixed-length (i.e. wrong length!)
> buffers?

I wouldn't say broken.  Do you really want Ada.Text_IO to contain functions
with side-effects?

Put_Line (Get_Line & Get_Line);  -- Do you want to encourage this in the
standard?

-CRM





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

* Re: Get_Line
  2002-10-31  0:26         ` Get_Line Chad R. Meiners
@ 2002-10-31  0:44           ` Robert A Duff
  2002-10-31 10:32             ` Get_Line John English
                               ` (2 more replies)
  0 siblings, 3 replies; 37+ messages in thread
From: Robert A Duff @ 2002-10-31  0:44 UTC (permalink / raw)


"Chad R. Meiners" <crmeiners@hotmail.com> writes:

> "Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
> news:wcc3cqn35wu.fsf@shell01.TheWorld.com...
> > But isn't the *real* problem that the design of Text_IO is broken?  For
> > example, why is there no Get_Line function:
> >
> >     function Get_Line(...) return String;
> >
> > that returns the entire contents of the next line, no matter how long it
> > is, and without fussing about with fixed-length (i.e. wrong length!)
> > buffers?
> 
> I wouldn't say broken.

Why not, given that beginners have trouble with all that buffer
management?  In fact, so do experts!  How does one choose the correct
buffer size?

Whether or not you like my Get_Line idea, surely you must admit that
beginners and experts are troubled by the current Text_IO interface.

>...  Do you really want Ada.Text_IO to contain functions
> with side-effects?

Yes, given that that's the usual way in Ada to return an
arbitrary-length string.

> Put_Line (Get_Line & Get_Line);  -- Do you want to encourage this in the
> standard?

I don't think a Get_Line function *encourages* that.  I just want to
allow: 

    X: constant String := Get_Line...

----

By the way, if you're phobic of side effects, why do we have "X := new
T;" (in Ada) instead of "new(X);" (as a statement in Pascal)?  The "new"
clearly affects (or causes side-effects upon) the heap.

Does this "encourage" things like "if new T = new T then.."?

- Bob



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

* Re: Get_Line
  2002-10-30 18:08     ` Get_Line Jeffrey Carter
  2002-10-30 22:42       ` Get_Line Robert A Duff
@ 2002-10-31  8:53       ` Preben Randhol
  2002-10-31 18:04         ` Get_Line Jeffrey Carter
  1 sibling, 1 reply; 37+ messages in thread
From: Preben Randhol @ 2002-10-31  8:53 UTC (permalink / raw)


Jeffrey Carter wrote:
> This calls Skip_Line if you have read an empty line. But Get_Line will 
> skip the line terminator if you read an empty line (or any line with < 
> Buffer'Length characters). What you want to do is call Skip_Line if 
> Get_Line has not skipped the line terminator, which happens if the input 
>   is >= Buffer'Length characters:
> 
> if Last >= Buffer'Last then
          ^^
Hmm, can Last be > than Buffer'Last ?


-- 
Preben Randhol  --------------------  http://www.pvv.org/~randhol
�.., chaos is found in greatest abundance wherever order is being
sought. It always defeats order, because it is better organized.�
                            -- Interesting Times, Terry Pratchett



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

* Re: Get_Line
  2002-10-31  0:44           ` Get_Line Robert A Duff
@ 2002-10-31 10:32             ` John English
  2002-10-31 11:30               ` Get_Line Preben Randhol
  2002-10-31 17:39             ` Get_Line Warren W. Gay VE3WWG
  2002-10-31 21:46             ` Get_Line Chad R. Meiners
  2 siblings, 1 reply; 37+ messages in thread
From: John English @ 2002-10-31 10:32 UTC (permalink / raw)


Robert A Duff wrote:
> 
> Whether or not you like my Get_Line idea, surely you must admit that
> beginners and experts are troubled by the current Text_IO interface.

IMHO, the big problem with Text_IO is the line-oriented nature of the
library (a la Pascal). C-style character-oriented I/O is so much easier
to deal with!

-----------------------------------------------------------------
 John English              | mailto:je@brighton.ac.uk
 Senior Lecturer           | http://www.it.bton.ac.uk/staff/je
 Dept. of Computing        | ** NON-PROFIT CD FOR CS STUDENTS **
 University of Brighton    |    -- see http://burks.bton.ac.uk
-----------------------------------------------------------------



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

* Re: Get_Line
  2002-10-31 10:32             ` Get_Line John English
@ 2002-10-31 11:30               ` Preben Randhol
  2002-10-31 13:10                 ` Get_Line John English
  0 siblings, 1 reply; 37+ messages in thread
From: Preben Randhol @ 2002-10-31 11:30 UTC (permalink / raw)


John English wrote:
> Robert A Duff wrote:
>> 
>> Whether or not you like my Get_Line idea, surely you must admit that
>> beginners and experts are troubled by the current Text_IO interface.
> 
> IMHO, the big problem with Text_IO is the line-oriented nature of the
> library (a la Pascal). C-style character-oriented I/O is so much easier
> to deal with!

Why?

-- 
Preben Randhol  --------------------  http://www.pvv.org/~randhol
�.., chaos is found in greatest abundance wherever order is being
sought. It always defeats order, because it is better organized.�
                            -- Interesting Times, Terry Pratchett



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

* Re: Get_Line
  2002-10-31 11:30               ` Get_Line Preben Randhol
@ 2002-10-31 13:10                 ` John English
  0 siblings, 0 replies; 37+ messages in thread
From: John English @ 2002-10-31 13:10 UTC (permalink / raw)


Preben Randhol wrote:
> 
> John English wrote:
> > Robert A Duff wrote:
> >>
> >> Whether or not you like my Get_Line idea, surely you must admit that
> >> beginners and experts are troubled by the current Text_IO interface.
> >
> > IMHO, the big problem with Text_IO is the line-oriented nature of the
> > library (a la Pascal). C-style character-oriented I/O is so much easier
> > to deal with!
> 
> Why?

Example: copying a text file involves either processing characters
and calling End_Of_Line to know when to call New_Line, or using
Get_Line and checking received buffer sizes to know when to call
New_Line. You can't just stream characters without regard to line
breaks.

It's also hard to deal with multi-line strings. In C, these just have
embedded '\n' characters. In Ada, you can't just use '\n' (or ASCII.LF)
because although it'll work on Unix systems, you have to use ASCII.CR
on Macs and ASCII.CR & ASCII.LF on Windows (whereas C libraries will
translate to/from '\n' automatically). So you can't just treat a line
break as just another character in a portable way.

-----------------------------------------------------------------
 John English              | mailto:je@brighton.ac.uk
 Senior Lecturer           | http://www.it.bton.ac.uk/staff/je
 Dept. of Computing        | ** NON-PROFIT CD FOR CS STUDENTS **
 University of Brighton    |    -- see http://burks.bton.ac.uk
-----------------------------------------------------------------



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

* Re: Get_Line
  2002-10-31  0:44           ` Get_Line Robert A Duff
  2002-10-31 10:32             ` Get_Line John English
@ 2002-10-31 17:39             ` Warren W. Gay VE3WWG
  2002-10-31 21:46             ` Get_Line Chad R. Meiners
  2 siblings, 0 replies; 37+ messages in thread
From: Warren W. Gay VE3WWG @ 2002-10-31 17:39 UTC (permalink / raw)



Robert A Duff wrote:
> "Chad R. Meiners" <crmeiners@hotmail.com> writes:
> 
> 
>>"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
>>news:wcc3cqn35wu.fsf@shell01.TheWorld.com...
>>
>>>But isn't the *real* problem that the design of Text_IO is broken?  For
>>>example, why is there no Get_Line function:
>>>
>>>    function Get_Line(...) return String;
>>>
>>>that returns the entire contents of the next line, no matter how long it
>>>is, and without fussing about with fixed-length (i.e. wrong length!)
>>>buffers?
>>
>>I wouldn't say broken.
> 
> 
> Why not, given that beginners have trouble with all that buffer
> management?  In fact, so do experts!  How does one choose the correct
> buffer size?
> 
> Whether or not you like my Get_Line idea, surely you must admit that
> beginners and experts are troubled by the current Text_IO interface.
> 
> 
>>...  Do you really want Ada.Text_IO to contain functions
>>with side-effects?

I would say no -- at least as much as is practical.

Consider a different interface:

with Ada.Strings.Unbounded;

...

    declare
       use Ada.Strings.Unbounded;
       Line : Unbounded_String;
    begin
       ...
       Get_Line(F,Line);  -- Non-standard Get_Line() here

Here Line can be returned as short or as long as required.  If you
later want a "native string", then add:

       declare
          S : String := To_String(Line);
       begin
          ...

-- 
Warren W. Gay VE3WWG
http://home.cogeco.ca/~ve3wwg




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

* Re: Get_Line
  2002-10-31  8:53       ` Get_Line Preben Randhol
@ 2002-10-31 18:04         ` Jeffrey Carter
  2002-11-01 11:18           ` Get_Line Preben Randhol
  0 siblings, 1 reply; 37+ messages in thread
From: Jeffrey Carter @ 2002-10-31 18:04 UTC (permalink / raw)


Preben Randhol wrote:
 > Jeffrey Carter wrote:
 >
 >> if Last >= Buffer'Last then
 >
 > ^^ Hmm, can Last be > than Buffer'Last ? [from a call to Get_Line to
 > read Buffer]

It shouldn't. It might if your memory gets hit by a cosmic ray. But I
usually code like this because

1. It's defensive coding. If I assume Last <= Buffer'Last, the code may
go haywire if Last is ever > Buffer'Last. This isn't a very good
example, but if I'm calculating something that determines when to exit a
large loop, and I KNOW it will always be <= Exit_Value, and I exit when
it's = Exit_Value, and then 4 years later someone incorrectly modifies
the code so it becomes > Exit_Value trying to get it to exit sooner,
then you have an infinite loop. If I exit when it's >= Exit_Value, it's
more likely to be correct. The value has grown faster than expected, but
it's still time to exit the loop.

2. [Last < Buffer'Last => Get_Line has skipped a line terminator] =>
[not (Last < Buffer'Last) => it has not skipped one] => [Last >=
Buffer'Last => it has not skipped one]. Since I want to call Skip_Line
when Get_Line has not skipped a line terminator, I use the last condition.

-- 
Jeff Carter
"If you think you got a nasty taunting this time,
you ain't heard nothing yet!"
Monty Python and the Holy Grail




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

* Re: Get_Line
  2002-10-31  0:44           ` Get_Line Robert A Duff
  2002-10-31 10:32             ` Get_Line John English
  2002-10-31 17:39             ` Get_Line Warren W. Gay VE3WWG
@ 2002-10-31 21:46             ` Chad R. Meiners
  2002-11-01 16:59               ` Get_Line Robert A Duff
  2 siblings, 1 reply; 37+ messages in thread
From: Chad R. Meiners @ 2002-10-31 21:46 UTC (permalink / raw)



"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
news:wccd6prv3mk.fsf@shell01.TheWorld.com...

> Why not, given that beginners have trouble with all that buffer
> management?  In fact, so do experts!

I have never had trouble with Ada.Text_IO.  It was rarely the cause of
confusion with students I tutored in an introductory programming course.  In
fact when I began TA'ing for an introductory programming course that used
c++, the students had more problems which were rooted in a misunderstanding
of c++'s stream I/O operators.

> How does one choose the correct buffer size?

 :-) Well you look at your problem requirements and derive a number that is
suitable for most cases and deal with larger strings in a well defined
manner.  That sort of answer is something that is addressed in a second
semester computer science course.  :-)

> Whether or not you like my Get_Line idea, surely you must admit that
> beginners and experts are troubled by the current Text_IO interface.

I am neither for or against using a Get_Line function.  I have used similar
functions myself in various cases.
I will admit that people like to expect more from Ada.Text_IO then is
reasonable.   Ada.Text_IO could benefit from some extension, and perhaps a
sister package that allows the character based I/O John English mention
(although Stream_IO should do in a pinch).  However I would not go so far as
saying troubled.  Does Ada.Text_IO's design cause angst among the general
Ada community?  I don't think so.

>
> Yes, given that that's the usual way in Ada to return an
> arbitrary-length string.

But this is a case where the side effect is of crucial importance!  Warren's
suggestion to build a Get_Line for Unbounded_Strings is a much better way to
handle the side effect on the I/O buffer.

> > Put_Line (Get_Line & Get_Line);  -- Do you want to encourage this in the
> > standard?
>
> I don't think a Get_Line function *encourages* that.  I just want to
> allow:
>
>     X: constant String := Get_Line...
>
> ----

Yes it does, see below.

> By the way, if you're phobic of side effects, why do we have "X := new
> T;" (in Ada) instead of "new(X);" (as a statement in Pascal)?

You do realize you are begging the question.  For instance, if you wanted to
defame my character a little more, you could have written, "By the way, if
you've finished beating your dog, why do we have ..."

>  The "new"
> clearly affects (or causes side-effects upon) the heap.
>
> Does this "encourage" things like "if new T = new T then.."?

Commutative operators are a bad example.  I am not against the use of
side-effect when they don't lead to nasty surprises.  It is obvious that the
Get_Line function is the type a function where the side-effect leads to
nasty surprises.

Do_Something (new T, new T, new T);

raises a mental alert, but

Do_Something (Get_Line, Get_Line, Get_Line);

does not.  The horrible tragedy is that the first example is more likely to
not depend on the order in which the parameters are allocated while the
second example will very likely carry some dependence on the order the
functions are called.

-CRM





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

* Re: Get_Line
  2002-10-29 20:24 Get_Line Justin Birtwell
                   ` (2 preceding siblings ...)
  2002-10-30 14:44 ` Get_Line Preben Randhol
@ 2002-10-31 21:55 ` Matthew Heaney
  3 siblings, 0 replies; 37+ messages in thread
From: Matthew Heaney @ 2002-10-31 21:55 UTC (permalink / raw)



"Justin Birtwell" <jbirtwell@yahoo.com> wrote in message
news:B7Cv9.32984$iV1.11543@nwrddc02.gnilink.net...
>
> I'm having some strange behavior with Get_Line.  In a procedure called
> GetData I call Get_Line to receive input from the command line. The first
> time this function is called it behaves fine prompting the user for input.
> The second time it runs  the execution passes through Get_Line and no
prompt
> appears on the command line.  Upon doing a little research in the Ref Man.
> I found a statement that talks about if Get_Line finds a line terminator
it
> automatically returns.  But how can this be?

You might want to read my get_line article at adapower:

http://www.adapower.com/lang/get_line.html

Get_Line indicates that the entire line has been consumed by returning fewer
characters in the read request than are available in the buffer.

For example:

declare
  Max_Length : constant := 80;
  Line : String (1 .. Max_Length + 1);
  Last : Natural;
begin
  Get_Line (Line, Last);

  if Last < Line'Last then
     --entire line was consumed
  else
     --entire line was NOT consumed
  end if;
end;

There are two approaches for handling the case that not all input was
consumed:

1) decide by fiat that the input was too long, and demand that the user
enter something shorter:

Line : String (1 .. Max_Length + 1);
Last : Natural;

Read_Response:
loop
   Put ("ready: ");

   Get_Line (...);

   exit when Last < Line'Last;

   Skip_Line;

   Put_Line ("input too long; try again");
end loop Read_Response;


2) simply copy what you read into an unbounded string, and then consume the
rest of the line as necessary:

Input : Unbounded_String;

Put ("ready: ");

Read_Response:
loop
   declare
      ...
   begin
      Get_Line (...);

      Append (Input, Line (Line'First .. Last));

      exit when Last < Line'Last;
   end;
end Read_Response;


These two techniques will satisfy the majority of most programmers' needs.






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

* Re: Get_Line
  2002-10-31 18:04         ` Get_Line Jeffrey Carter
@ 2002-11-01 11:18           ` Preben Randhol
  0 siblings, 0 replies; 37+ messages in thread
From: Preben Randhol @ 2002-11-01 11:18 UTC (permalink / raw)


Jeffrey Carter wrote:
> 
> 1. It's defensive coding. If I assume Last <= Buffer'Last, the code may
[..]

I agree with you.

-- 
Preben Randhol  --------------------  http://www.pvv.org/~randhol
�.., chaos is found in greatest abundance wherever order is being
sought. It always defeats order, because it is better organized.�
                            -- Interesting Times, Terry Pratchett



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

* Re: Get_Line
  2002-10-31 21:46             ` Get_Line Chad R. Meiners
@ 2002-11-01 16:59               ` Robert A Duff
  2002-11-01 21:04                 ` Get_Line Chad R. Meiners
  0 siblings, 1 reply; 37+ messages in thread
From: Robert A Duff @ 2002-11-01 16:59 UTC (permalink / raw)


"Chad R. Meiners" <crmeiners@hotmail.com> writes:

> "Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
> news:wccd6prv3mk.fsf@shell01.TheWorld.com...
> > Why not, given that beginners have trouble with all that buffer
> > management?  In fact, so do experts!
> 
> I have never had trouble with Ada.Text_IO.  It was rarely the cause of
> confusion with students I tutored in an introductory programming course.

>...  Does Ada.Text_IO's design cause angst among the general
> Ada community?  I don't think so.

Well, maybe your students didn't have trouble.  Maybe that means you're
a good teacher.  But I know I've seen *many* questions about
Text_IO.Get_Line and related stuff on c.l.a. over the years.
And this stuff *ought* to be simple -- I'm not surprised when
a beginner is confused about discriminated tasks or something,
but when folks are confused about how to read in a line of text,
I think that indicates something wrong with the language.

> > By the way, if you're phobic of side effects, why do we have "X := new
> > T;" (in Ada) instead of "new(X);" (as a statement in Pascal)?
> 
> You do realize you are begging the question.  For instance, if you wanted to
> defame my character a little more, you could have written, "By the way, if
> you've finished beating your dog, why do we have ..."

Sorry, I didn't mean to defame your character.  I was just making an
analogy between side-effects in character-stream-reading functions,
and allocators, where for the latter we happily use function-call-like
notation.

> Do_Something (new T, new T, new T);
> 
> raises a mental alert, but
> 
> Do_Something (Get_Line, Get_Line, Get_Line);
> 
> does not.  The horrible tragedy is that the first example is more likely to
> not depend on the order in which the parameters are allocated while the
> second example will very likely carry some dependence on the order the
> functions are called.

OK, that convinces me that my analogy was poor.

Still, the reason "Do_Something (Get_Line, Get_Line, Get_Line);" is
wrong is that Ada does not define evaluation order.  The mere
*existence* of a Get_Line function should not cause people to write
that.

I actually think that Ada *should* define the evaluation order,
precisely because the above example can cause bugs.  Alternatively,
the language should forbid such examples at compile time, rather
than just giving wrong answers.  I realize that Ada has no mechanism for
having such compile-time checking, because the compiler doesn't know
which global variables a given function reads and writes.

- Bob



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

* Re: Get_Line
  2002-11-01 16:59               ` Get_Line Robert A Duff
@ 2002-11-01 21:04                 ` Chad R. Meiners
  2002-11-01 23:32                   ` Get_Line Matthew Heaney
  0 siblings, 1 reply; 37+ messages in thread
From: Chad R. Meiners @ 2002-11-01 21:04 UTC (permalink / raw)



"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
news:wccy98d2plj.fsf@shell01.TheWorld.com...
> Well, maybe your students didn't have trouble.  Maybe that means you're
> a good teacher.  But I know I've seen *many* questions about
> Text_IO.Get_Line and related stuff on c.l.a. over the years.
> And this stuff *ought* to be simple -- I'm not surprised when
> a beginner is confused about discriminated tasks or something,
> but when folks are confused about how to read in a line of text,
> I think that indicates something wrong with the language.

I see.  I think the problem is that (simple) problems rarely actually call
for a programs to just get a line of text.  Often people think they need to
get a line of text and parse it, but they could just parse the line directly
with Ada.Text_IO's generic data type facilities.  I agree though that
reading an arbitrarily size string takes some work in Ada, but I would
expect this since Ada doesn't natively support resizable arrays.  This
doesn't mean we should sit back and be content with Ada.Text_IO when we
could extend it to make reading in a line a little more friendly, but we
should leave the side-effects out of the functions within Ada.Text_IO.
Would you be happy with the following instead?

type Line is private;

procedure Get_Line (File : File_Type; Item : out Line);

function  To_String (Item : Line) return String;


> Sorry, I didn't mean to defame your character.  I was just making an
> analogy between side-effects in character-stream-reading functions,
> and allocators, where for the latter we happily use function-call-like
> notation.

Okay, I didn't think you meant to defame; I was just making sure of your
intent.


> OK, that convinces me that my analogy was poor.
>
> Still, the reason "Do_Something (Get_Line, Get_Line, Get_Line);" is
> wrong is that Ada does not define evaluation order.  The mere
> *existence* of a Get_Line function should not cause people to write
> that.

My concern is that when students are learning a new language they sometimes
adopt a favorite part of the language and then proceed to try to use that
part whenever possible.  A Get_Line function has that certain appeal to it
that would make it a good candidate for such abuse especially if the student
knows c++.

> I actually think that Ada *should* define the evaluation order,
> precisely because the above example can cause bugs.  Alternatively,
> the language should forbid such examples at compile time, rather
> than just giving wrong answers.  I realize that Ada has no mechanism for
> having such compile-time checking, because the compiler doesn't know
> which global variables a given function reads and writes.

I would definitively like to see warnings generated when possible! ;-)

-CRM





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

* Re: Get_Line
  2002-11-01 21:04                 ` Get_Line Chad R. Meiners
@ 2002-11-01 23:32                   ` Matthew Heaney
  2002-11-02  0:28                     ` Get_Line Chad R. Meiners
  0 siblings, 1 reply; 37+ messages in thread
From: Matthew Heaney @ 2002-11-01 23:32 UTC (permalink / raw)



"Chad R. Meiners" <crmeiners@hotmail.com> wrote in message
news:apuqd0$103i$1@msunews.cl.msu.edu...
>
> Would you be happy with the following instead?
>
> type Line is private;
>
> procedure Get_Line (File : File_Type; Item : out Line);
>

You already have a resizable string type, so you'd be better off using that.
The easiest solution would be to create a child of Ada.Strings.Unbounded:

with Ada.Text_IO;
package Ada.Strings.Unbounded.Text_IO is
   procedure Get_Line (File : File_Type; Item : out Unbounded_String);
end;

> function  To_String (Item : Line) return String;

Note that this isn't terribly efficient, for the same reasons
Ada.Strings.Unbounded is inefficient.  At least GNAT has
Ada.Strings.Unbounded.Aux, which allows you to get at the internal string
directly.

In C++, I can return a reference.  Something like:

class C
{
public:
   const std::string& f() const;
//...
};

The closest thing in Ada is to use an access type:

type Line_Type is private;

type String_Access is access all String;

function To_String_Access (Line : Line_Type) return String_Access;

and then you could:

declare
   S : String renames To_String_Access (Line).all;  --no copying
begin

You could tighten the safety by being able to decorate the access type, e.g.

type String_Access (<>) is limited access all String;

which would prevent users from holding on to a copy of the access value
returned by the selector function (forcing them to do a rename, as above).

All the Charles containers use this technique, to allow in-place
manipluation of container elements.  So you typically have a pair of
functions:

   function Element (Container : Container_Type)
     return Element_Type;

   generic
     type Element_Access is access all Element_Type;
   function Generic_Element (Container : Container_Type)
     return Element_Access;

This is analogous to the iterator dereference operators:

   value_type& operator*() const;

which allows you to do this:

   int& histogram = *iter;
   ++histogram;

This kind of in-place manipulation is awkward without references.  In my
container example above, you'd have:

declare
   Histogram : Integer renames To_Access (Iterator).all;
begin
   Histogram := Histogram + 1;
end;

See the Charles page for more info:

http://home.earthlink.net/~matthewjheaney/charles/charles-vectors-unbounded.
html

http://home.earthlink.net/~matthewjheaney/charles/index.html

Matt








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

* Re: Get_Line
  2002-11-01 23:32                   ` Get_Line Matthew Heaney
@ 2002-11-02  0:28                     ` Chad R. Meiners
  0 siblings, 0 replies; 37+ messages in thread
From: Chad R. Meiners @ 2002-11-02  0:28 UTC (permalink / raw)



"Matthew Heaney" <mheaney@on2.com> wrote in message
news:us63nof66esp1b@corp.supernews.com...
>
> "Chad R. Meiners" <crmeiners@hotmail.com> wrote in message
> news:apuqd0$103i$1@msunews.cl.msu.edu...
> >
> > Would you be happy with the following instead?
> >
> > type Line is private;
> >
> > procedure Get_Line (File : File_Type; Item : out Line);
> >
>
> You already have a resizable string type, so you'd be better off using
that.
> The easiest solution would be to create a child of Ada.Strings.Unbounded:

The line type wasn't meant to be resizeable like Unbounded_String it was
meant to only resize at an input read.

> The closest thing in Ada is to use an access type:
>
> type Line_Type is private;
>
> type String_Access is access all String;
>
> function To_String_Access (Line : Line_Type) return String_Access;
>
> and then you could:
>
> declare
>    S : String renames To_String_Access (Line).all;  --no copying
> begin
>
> You could tighten the safety by being able to decorate the access type,
e.g.
>
> type String_Access (<>) is limited access all String;
>
> which would prevent users from holding on to a copy of the access value
> returned by the selector function (forcing them to do a rename, as above).

Yes that would a better approach.  I was just brainstorming.  Thank you for
your input.

-CRM





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

end of thread, other threads:[~2002-11-02  0:28 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-06-05  0:00 get_line Steve Dyrdahl
1998-06-05  0:00 ` get_line Samuel Mize
1998-06-17  0:00   ` get_line Hans Marqvardsen
1998-06-18  0:00     ` get_line John McCabe
1998-06-21  0:00       ` get_line Robert Dewar
1998-06-06  0:00 ` get_line Dale Stanbrough
1998-06-06  0:00   ` get_line Robert Dewar
1998-06-06  0:00   ` get_line Matthew Heaney
1998-06-07  0:00     ` get_line Dale Stanbrough
1998-06-06  0:00       ` get_line Matthew Heaney
1998-06-18  0:00     ` get_line Robert I. Eachus
  -- strict thread matches above, loose matches on Subject: below --
1999-07-02  0:00 GET LINE babefan
1999-07-02  0:00 ` czgrr
2002-10-29 20:24 Get_Line Justin Birtwell
2002-10-29 20:55 ` Get_Line David C. Hoos
2002-10-30  1:30 ` Get_Line Jeffrey Carter
2002-10-30 13:33   ` Get_Line Justin Birtwell
2002-10-30 14:40     ` Get_Line Preben Randhol
2002-10-30 17:09     ` Get_Line Jean-Pierre Rosen
2002-10-30 18:08     ` Get_Line Jeffrey Carter
2002-10-30 22:42       ` Get_Line Robert A Duff
2002-10-31  0:26         ` Get_Line Chad R. Meiners
2002-10-31  0:44           ` Get_Line Robert A Duff
2002-10-31 10:32             ` Get_Line John English
2002-10-31 11:30               ` Get_Line Preben Randhol
2002-10-31 13:10                 ` Get_Line John English
2002-10-31 17:39             ` Get_Line Warren W. Gay VE3WWG
2002-10-31 21:46             ` Get_Line Chad R. Meiners
2002-11-01 16:59               ` Get_Line Robert A Duff
2002-11-01 21:04                 ` Get_Line Chad R. Meiners
2002-11-01 23:32                   ` Get_Line Matthew Heaney
2002-11-02  0:28                     ` Get_Line Chad R. Meiners
2002-10-31  8:53       ` Get_Line Preben Randhol
2002-10-31 18:04         ` Get_Line Jeffrey Carter
2002-11-01 11:18           ` Get_Line Preben Randhol
2002-10-30 14:44 ` Get_Line Preben Randhol
2002-10-31 21:55 ` Get_Line Matthew Heaney

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