http://qs321.pair.com?node_id=255195

nedals has asked for the wisdom of the Perl Monks concerning the following question:

$var = 1234;
$var = "1234";
Is there a function/test in Perl that can tell the difference between the above number or string?

I tried this but the answer is always numeric.
use POSIX;
print isdigit($var) ? "numeric\n" : "string\n";

Replies are listed 'Best First'.
Re: Test for number or string
by Abigail-II (Bishop) on May 03, 2003 at 00:32 UTC
    The answer to this question is found in the manual page perlop, in particular the section Bitwise String Operators.

    Here's a program that might help you:

    use strict; use warnings; my $num = 1234; my $str = "1234"; print $num | "2861", "\n"; print $str | "2861", "\n"; __END__ 4095 3:75

    Abigail

      Some specificity: To explain Abigail's answer, one must understand the characteristics of strings and numbers in perl. Although to the external world, strings and numbers are handled basically the same, certain operators that use the context of a number vs. string to give you a result. The most notable and used ones are the Bitwise String Operators.

      By using the properties of Bitwise string operators, one can find out whether a certain scalar is a string or not. Abigail-II didn't provide the exact code to deduce whether something's a string (I can't tell you why: Perhabs because of lack of knowledge, and more probably because of a desire to impart knowledge without giving away too much.)

      Since, bitwise operators are a little bit hard to understand(and understanding them doesn't mean you'll be able to figure out how to find a string- although you probably will), I'll just give you the explicit code to do it. Just enter your number:
      sub is_numeric { ($_[0] & ~ $_[0]) eq "0"; }

      Gyan Kapur
      gyan.kapur@rhhllp.com
        Perfect. ++
        Maybe, after all this discussion, I'll find out that I don't really need it. But many thanks!
Re: Test for number or string
by broquaint (Abbot) on May 03, 2003 at 02:19 UTC
Re: Test for number or string
by nedals (Deacon) on May 03, 2003 at 00:01 UTC
    I had a feeling someone would ask..
    I want to create a backup .txt file for an mySQL database table which can be easily uploaded via a custom script. The script requires that strings be single quoted, but not the numbers. One or more of the fields could contain an all numeric field that I want to save as a quoted string.
    ie: zip=94566 or 94566-1234.
    The .txt file is loaded into the database using..
    INSERT INTO table VALUES($fileline);
      If you are using DBI use placeholders. You might find this node helpful.

      Apart from that using placeholders is almost certainly the way to go, I think that your reasoning is slightly flawed.

      Either you know that this $var contains the value that is maintained as a string field, or you don't. Perl doesn't store the quotes internally and whenever you load a variable, the initial value of the variable is always a string. It doesn't get converted to its binary form until you use it in a numeric context, at which point perl will convert the ascii representation to the binary numeric form. If you then imediately use it in a string context, perl will convert it back. Any simple test you tried to apply for either form is going to always be true because perl will supply the form you are asking for.

      You don't say at which point in the process you are trying to make the determination.

      When you are writing it to the text file, or when you read it back?

      In the former case, you should be able to determine the type of the field from the table schema.

      In the latter case, assuming you wrote the string quoted, you could simply not strip them off when you read the file in, and then you would know which was which. ie.

      if( substr($var, 0, 1) eq "'" ) { print "It's a string\n" }

      HTH?

        In the former case, you should be able to determine the type of the field from the table schema.
        I could indeed do that (see below) but I was trying to simplify things. I tried INSERTing into the database without the quotes and it would not save the data. I do understand your point regarding Perl's handling of strings and numbers.
Re: Test for number or string
by Anonymous Monk on May 02, 2003 at 23:50 UTC

    The question is: Why do you need to know? In what circumstance will perl not do the right thing that requires you to differenciate between them?

Re: Test for number or string
by nedals (Deacon) on May 03, 2003 at 00:39 UTC
    Thanks for the node but I don't think placeholders will solve the problem. I could use them (again I think) to insert the lines.

    Let me expand a little further. The '$fileline" contains a record... (id,'name','address',..... for example) which is build by my script. This is then downloaded and saved as backup. On the upload side, the only thing my script knows is the table name. The $fileline contains the correct number of fields to be inserted. I don't believe that the placeholder will insert the appropiate quotes in each of the fields.

    My current solution involves getting a DESCRIPTION of the table to deterime which fields contain strings (varchar) and then inserting the quotes on the download side. Pretty long-winded

      This is exactly the problem placeholders are intended to solve. With placeholders, you just mark where you want to insert data into your SQL statement and the database interface layers take care of passing that data to the database where it belongs. I always use placeholders and have never had to worry about quoting.

      Look in the Tutorials section. There are plenty of tutorials that explain how to use DBI with placeholders.

      Also, you'll get faster and more accurate answers to your questions if you give all the details you can up front instead of being miserly with information about what you are really trying to do.

      90% of every Perl application is already written.
      dragonchild
        Too true :)
        I guess I thought there would be a simple answer to the original question.

        UPDATE
        Let me make sure I understand what you are saying.

        I can easily download my data with no quotes in the form...

        id,name,address,etc

        Now I upload this same data using something like this...
        my $sql = "INSERT INTO tablename VALUES(?)"; my $sth = $dbh->prepare($sql); foreach my $record (@filedata) { $sth->execute($record); }
        ... and I don't have to worry about quotes, etc.?