Numeric or character ?

Discussion in 'Perl Misc' started by John Cecere, Jul 19, 2005.

  1. John Cecere

    John Cecere Guest

    Since

    if ("aaa" == 0) {
    print "true\n";
    }

    will print true, how does one go about testing a value as an integer. For example, the user enters data:

    $a=<STDIN>;

    The user might accidentally type in character data, but I need to perform a test to see if what they entered is a number between 0
    and 255, and return a bad status for anything else. Doing this:

    if ($a < 0 || $a > 255)

    won't catch character data.

    What's the _simple_ way of doing this ?

    Thanks,
    John Cecere
     
    John Cecere, Jul 19, 2005
    #1
    1. Advertising

  2. John Cecere <> wrote in
    news:dbjr71$4bn$:

    > Since
    >
    > if ("aaa" == 0) {
    > print "true\n";
    > }
    >
    > will print true, how does one go about testing a value as an integer.
    > For example, the user enters data:
    >
    > $a=<STDIN>;
    >
    > The user might accidentally type in character data,


    You seem to be unaware that everything that is stored in $a
    at this point is *character* data. If the user enters 110,
    $a will contain the string consisting of the characters '1',
    '1', and '0', not the integer 110.

    > need to perform a test to see if what they entered is a number
    > between 0 and 255, and return a bad status for anything else.
    > Doing this:
    >
    > if ($a < 0 || $a > 255)


    Of course not, you have a string in $a and you are comparing it
    to a number, and therefore it is subject to all the conditions of
    number to string conversion in Perl.

    BTW, the variables $a and $b are special in Perl
    (see perldoc -f sort). You should not use them willy-nilly.

    > What's the _simple_ way of doing this ?


    In general, one checks if input conforms to a certain format by
    using an appropriate regex match. In this case, it is a very
    simple one:

    #!/usr/bin/perl

    use strict;
    use warnings;

    my $input;

    $| = 1;

    do {
    print "Please enter and integer between 0 and 255: ";
    $input = <STDIN>;
    } until $input =~ /^(\d\d?\d?)$/ and 0 + $1 < 256;

    print "You entered: $input\n";

    __END__

    For more general numeric formats, see

    <URL:http://search.cpan.org/~abigail/Regexp-Common-2.120/lib/Regexp/Common/number.pm>

    Sinan

    --
    A. Sinan Unur <>
    (reverse each component and remove .invalid for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Jul 19, 2005
    #2
    1. Advertising

  3. Abigail <> wrote in
    news::

    > A. Sinan Unur () wrote on MMMMCCCXL September
    > MCMXCIII in <URL:news:Xns9698B4F254690asu1cornelledu@127.0.0.1>:
    > //
    > // BTW, the variables $a and $b are special in Perl
    > // (see perldoc -f sort). You should not use them willy-nilly.
    >
    > I use $a and $b willy-nilly all the time, and I have never ran into
    > trouble. While it is possible to create code that might do something
    > unexpected, it takes a bit of an effort to do so.


    True, but I have a knack for unintentionally discovering the complicated
    steps to produce unlikely scenarios while doing somthing completely
    mundane.

    Sinan

    --
    A. Sinan Unur <>
    (reverse each component and remove .invalid for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Jul 20, 2005
    #3
  4. John Cecere wrote:
    > Since
    >
    > if ("aaa" == 0) {
    > print "true\n";
    > }
    >
    > will print true, how does one go about testing a value as an integer.
    > For example, the user enters data:
    > $a=<STDIN>;
    >
    > The user might accidentally type in character data,


    Well, I hope he does. How could he type anything that is not a character?

    > but I need to
    > perform a test to see if what they entered is a number between 0 and
    > 255, and return a bad status for anything else.


    First of all I suggest to get your terminology right. The user enters a
    sequence of characters. You want to restrict this to digits. And then Perl
    can interpret a sequence of digits as a number. While this might seem to be
    nitpicking it actually helps immensely to partition your problem in the
    right way.

    Having said that, is there anything wrong with the answer given in the FAQ?
    perldoc -q number:
    "How do I determine whether a scalar is a number/whole/integer/float?"

    > Doing this:
    > if ($a < 0 || $a > 255)
    >
    > won't catch character data.


    By some definiton of "character" which has nothing to do with the standard
    definition of character.
    Of course it doesn't because you are comparing the numerical value of a
    scalar. If you want to test the characters of string (yes, even digits are
    characters) then use a function that uses strings or characters, e.g.
    pattern matching or substr or pos or similar.

    > What's the _simple_ way of doing this ?


    Maybe the way as suggested in the FAQ?

    jue
     
    Jürgen Exner, Jul 20, 2005
    #4
  5. > In general, one checks if input conforms to a certain format by
    > using an appropriate regex match. In this case, it is a very
    > simple one:
    >
    > #!/usr/bin/perl
    >
    > use strict;
    > use warnings;
    >
    > my $input;
    >
    > $| = 1;


    I'm just being interested: is there any specific reason why you make output unbuffered here? I think it's not necessary for this script but maybe something has escaped me...

    >
    > do {
    > print "Please enter and integer between 0 and 255: ";
    > $input = <STDIN>;
    > } until $input =~ /^(\d\d?\d?)$/ and 0 + $1 < 256;
    >
    > print "You entered: $input\n";
     
    Sven-Thorsten Fahrbach, Jul 26, 2005
    #5
  6. John Cecere

    Anno Siegel Guest

    Sven-Thorsten Fahrbach <> wrote in comp.lang.perl.misc:
    > > In general, one checks if input conforms to a certain format by
    > > using an appropriate regex match. In this case, it is a very
    > > simple one:
    > >
    > > #!/usr/bin/perl
    > >
    > > use strict;
    > > use warnings;
    > >
    > > my $input;
    > >
    > > $| = 1;

    >
    > I'm just being interested: is there any specific reason why you make
    > output unbuffered here? I think it's not necessary for this script but
    > maybe something has escaped me...


    Autoflushing (which is more to the point than "unbuffered") isn't
    exactly needed here, but it's convenient to have. Its main purpose
    is to match the flushing behavior of STDOUT and STDERR so that messages
    on both appear on the screen when they are printed, not when a buffer
    happens to overflow. Otherwise, error messages and normal output may
    appear out of sequence, which can be confusing.

    I put "$| = 1" in all my scripts (not modules), and only take it out
    when the script happens to do mass IO via STDOUT (as in a filter).

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Jul 27, 2005
    #6
  7. On 27 Jul 2005 10:00:22 GMT
    -berlin.de (Anno Siegel) wrote:

    > Sven-Thorsten Fahrbach <> wrote in comp.lang.perl.misc:
    > > > In general, one checks if input conforms to a certain format by
    > > > using an appropriate regex match. In this case, it is a very
    > > > simple one:
    > > >
    > > > #!/usr/bin/perl
    > > >
    > > > use strict;
    > > > use warnings;
    > > >
    > > > my $input;
    > > >
    > > > $| = 1;

    > >
    > > I'm just being interested: is there any specific reason why you make
    > > output unbuffered here? I think it's not necessary for this script but
    > > maybe something has escaped me...

    >
    > Autoflushing (which is more to the point than "unbuffered") isn't
    > exactly needed here, but it's convenient to have. Its main purpose
    > is to match the flushing behavior of STDOUT and STDERR so that messages
    > on both appear on the screen when they are printed, not when a buffer
    > happens to overflow. Otherwise, error messages and normal output may
    > appear out of sequence, which can be confusing.
    >
    > I put "$| = 1" in all my scripts (not modules), and only take it out
    > when the script happens to do mass IO via STDOUT (as in a filter).


    Okay, I know what it does, I just wasn't aware that this was kind of a custom among some programmers. When I need unbuffered output I let it go to STDERR usually which is unbuffered (or autoflushed if you prefer) by default.
     
    Sven-Thorsten Fahrbach, Jul 27, 2005
    #7
  8. John Cecere

    Anno Siegel Guest

    Sven-Thorsten Fahrbach <> wrote in comp.lang.perl.misc:
    > On 27 Jul 2005 10:00:22 GMT
    > -berlin.de (Anno Siegel) wrote:
    >
    > > Sven-Thorsten Fahrbach <> wrote in

    > comp.lang.perl.misc:


    [...]

    > > > I'm just being interested: is there any specific reason why you make
    > > > output unbuffered here? I think it's not necessary for this script but
    > > > maybe something has escaped me...

    > >
    > > Autoflushing (which is more to the point than "unbuffered") isn't
    > > exactly needed here, but it's convenient to have. Its main purpose
    > > is to match the flushing behavior of STDOUT and STDERR so that messages
    > > on both appear on the screen when they are printed, not when a buffer
    > > happens to overflow. Otherwise, error messages and normal output may
    > > appear out of sequence, which can be confusing.
    > >
    > > I put "$| = 1" in all my scripts (not modules), and only take it out
    > > when the script happens to do mass IO via STDOUT (as in a filter).

    >
    > Okay, I know what it does, I just wasn't aware that this was kind of a
    > custom among some programmers. When I need unbuffered output I let it go
    > to STDERR usually which is unbuffered (or autoflushed if you prefer) by
    > default.


    It's not just preference. An autoflushed IO channel is still buffered,
    the buffer just doesn't fill up so much. A truly unbuffered channel
    would be very hard to use.

    Otherwise, the purpose of "$| = 1" isn't that we want STDOUT autoflushed,
    it's that there already *is* autoflushed output that merges with it,
    and the merging is smoother when both are autoflushed.

    The problem is often not visible when printing directly to the terminal,
    because terminal output is usually line buffered (another form of automatic
    flushing). When the output goes to a file or pipe, to "| more" for
    instance, the difference becomes apparent. Watch this:

    [anno4000@lublin ~/clpm]$ cat script
    #!/usr/bin/perl
    use strict; use warnings;

    $| = shift || 0;

    print "one\n";
    warn "two\n";
    print "three\n";

    [anno4000@lublin ~/clpm]$ ./script |& more
    two
    one
    three

    4000@lublin ~/clpm]$ ./script 1 |& more
    one
    two
    three

    Only in the second (autoflushed) example does the output appear in
    the sequence it is produced. That is the problem "$| = 1" avoids.

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Jul 27, 2005
    #8
  9. On 27 Jul 2005 11:56:27 GMT
    -berlin.de (Anno Siegel) wrote:
    > It's not just preference. An autoflushed IO channel is still buffered,
    > the buffer just doesn't fill up so much. A truly unbuffered channel
    > would be very hard to use.
    >
    > Otherwise, the purpose of "$| = 1" isn't that we want STDOUT autoflushed,
    > it's that there already *is* autoflushed output that merges with it,
    > and the merging is smoother when both are autoflushed.
    >
    > The problem is often not visible when printing directly to the terminal,
    > because terminal output is usually line buffered (another form of automatic
    > flushing). When the output goes to a file or pipe, to "| more" for
    > instance, the difference becomes apparent. Watch this:
    >
    > [anno4000@lublin ~/clpm]$ cat script
    > #!/usr/bin/perl
    > use strict; use warnings;
    >
    > $| = shift || 0;
    >
    > print "one\n";
    > warn "two\n";
    > print "three\n";
    >
    > [anno4000@lublin ~/clpm]$ ./script |& more
    > two
    > one
    > three
    >
    > 4000@lublin ~/clpm]$ ./script 1 |& more
    > one
    > two
    > three
    >
    > Only in the second (autoflushed) example does the output appear in
    > the sequence it is produced. That is the problem "$| = 1" avoids.


    All right, that was enlightening, though I would not consider it a 'problem' exactly. If I come across a situation where non-autoflushed output might not be desireable, I print to STDERR or set $| = 1. I don't come from a profound C background, though, so I might be a little ignorant ;-).
    Excerpt from the Camel Book: 'Contrary to popular belief, setting this [$|] variable does not turn off buffering.'
    Okey, my bad.

    SveTho
     
    Sven-Thorsten Fahrbach, Jul 27, 2005
    #9
  10. John Cecere

    Anno Siegel Guest

    Sven-Thorsten Fahrbach <> wrote in comp.lang.perl.misc:
    > On 27 Jul 2005 11:56:27 GMT
    > -berlin.de (Anno Siegel) wrote:


    [Why do some set $| = 1 routinely? Demo how STDOUT and STDERR get out
    of sequence if you don't]

    > All right, that was enlightening, though I would not consider it a
    > 'problem' exactly. If I come across a situation where non-autoflushed
    > output might not be desireable, I print to STDERR or set $| = 1.


    Sure, like everyone. The question was, why do it routinely. When working
    on a program you don't want to see, say, the error message it died with
    in front of material it has produced before it died.

    There are other reasons to use it. If you want to watch a program's
    file output through "tail -f ...", it will look jerky unless autoflushed.
    Also, if you do an improvised user dialog through STDOUT and STDIN,
    users may not see your prompt on some systems unless you autoflush
    STDOUT. So it also makes a program more portable. Under normal
    circumstances it doesn't hurt much. The exception is mass output
    which becomes inefficient. It's the only reason I can think of to
    turn it off.

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Jul 27, 2005
    #10
  11. John Cecere

    David Combs Guest

    In article <Xns9698B4F254690asu1cornelledu@127.0.0.1>,
    A. Sinan Unur <> wrote:
    >John Cecere <> wrote in
    >news:dbjr71$4bn$:
    >

    SNIP
    >
    >#!/usr/bin/perl
    >
    >use strict;
    >use warnings;
    >
    >my $input;
    >
    >$| = 1;
    >
    >do {
    > print "Please enter and integer between 0 and 255: ";
    > $input = <STDIN>;
    >} until $input =~ /^(\d\d?\d?)$/ and 0 + $1 < 256;
    >
    >print "You entered: $input\n";
    >
    >__END__

    ....

    Following Damian's new book (Perl Best Practices) (plus this group),
    might it be safer to localize $|?

    David
     
    David Combs, Aug 9, 2005
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. david
    Replies:
    7
    Views:
    11,820
    Ricardo Dominguez
    Oct 10, 2012
  2. Replies:
    5
    Views:
    982
    X-Centric
    Jun 30, 2005
  3. darrel
    Replies:
    4
    Views:
    869
    darrel
    Jul 19, 2007
  4. jobs

    int to numeric numeric(18,2) ?

    jobs, Jul 21, 2007, in forum: ASP .Net
    Replies:
    2
    Views:
    1,020
    =?ISO-8859-1?Q?G=F6ran_Andersson?=
    Jul 22, 2007
  5. Harlan Messinger
    Replies:
    2
    Views:
    717
    Andy Dingley
    Nov 19, 2007
Loading...

Share This Page