Jump to content

Array[] or array() or wha?


GaryM
Go to solution Solved by kicken,

Recommended Posts

I dont understand arrays in PHP and its necessary to finally fess up and ask for help.

It seems so trivial,, but I've spent Whole DAYS trying to make sense of this.  (I came from assemble language programming).

 

I am receiving UDP packets of a known size. in this case, 4 bytes of binary data.  It gets unpacked ( I dont know why. I cut and pasted this simple parser from an example).   All I want is the array[0] byte.  I'm trying to avoid complex loops and pointers.

// First lets grab a data packet and put our few bytes into the variable $buf

        while(1)  {
           socket_recvfrom($socket, $buf, 16, 0, $from, $port);  
           // Easy! but the UDP data in $buf is binary not useful like this. 

           //Convert to array of decimal values
           $array = unpack("C*", $buf);    // 'C' tells unpack to make unsigned chars from the binary.

           //Convert decimal values to ASCII characters:

           $chr_array = array();          // wait a second. What is happening here?
                                          
           for ($i = 0; $i < count($array); $i++)
             {
              $chr_array[] = chr($array[$i]);    // Whats going on here?  Anyone?
             }
              
           //  So now I can assume the first byte of this $chr_array[] is my prize, right?

           $mychr = chr_array[0];

           //  Nope.  Looking at $chr_array[0] either reveals a zero or the actual word "Array", depending on how late I've stayed up.
            
           print_r($array);  //   This is my debugger. It shows SOMETHING is working.

           echo "Received $mychr from remote $address $from and remote port $port" . PHP_EOL;
        }

        socket_close($sock);

Output of above code... assuming the value read was 60 decimal:

Array
(
    [1] => 60
    [2] => 0
    [3] => 0
    [4] => 0
)
Received  0 from remote address nnn.nnn.nnn.nnn and remote port 8888

 

So print_r knows what to do, the last line of my code doesn't.   Any help would be appreciated, as this goes to the heart of my issue of being mystified by how PHP makes and processes arrays.   Its clearly not just a string of numbers.

 

I'm trying to pull ONE printable number from that buffer.  Halp!
 

Link to comment
Share on other sites

To be clearer than Ignace was:

 

What does this line do:

 

$mychr = chr_array[0];

If you had php error checking turned on you would have seen this by now. (See my signature)

 

And - why do your array print show indices beginning with 1 and not 0? I've never used unpack() but something seems odd here.

Link to comment
Share on other sites

I'm using notepad++. 

Its nice for highlighting things but that doesn't tell me what the function does.  (does it?  I don't believe it does)

 

I'm sorry I wasn't clear.  I dont know what this function is doing. I dont know what the error looks like, and I dont know why the print_r thing skips a zero.

 

I'm not asking for anyone to write my code.  I'm certain there is an easy way to get data out of an array. 

I dont know what array() does, beyond the man page. Its a function but the author is assigning it to a $variable??  How does that even work? 

 

I understand print_r is showing us a breakdown of the array's contents.  How do I get the first (or second, whatever) out of the array without using print_r ??  I wish to operate on the byte (or char) programmatically, rather than look at it.

 

Whats missing the '$'?  Where  ?

 

I set up the error checking as ginerjm recommended but it means nothing to me.  Because I dont know arrays?

 

Here's the output:

 

Notice: Undefined offset:  0 in /home/pool/public_html/socket_recvfrom.php on line 24
Notice: Undefined offset:  0 in /home/pool/public_html/socket_recvfrom.php on line 27
Array
(
    [1] => 249
    [2] => 0
    [3] => 0
    [4] => 0
)
Received  0 from remote address nnn.nnn.nnn.nnn and remote port 8888

 

Because of PHP's "gender fluidity" with variable casting, I'm not sure if the zero being output is a CHAR, INT, One-Byte-String... 
 

 

        for ($i = 0; $i < count($array); $i++)
           {
             $chr_array[] = chr($array[$i]);     // line 24

                if($i == '0')  {
                  $mychr = chr($array[$i]);         // line 27
                }

           }

"Undefined offset" makes no sense to me.    How do I define it?

Again, I do well with most parts of PHP but arrays ...

 

Link to comment
Share on other sites

The code makes no sense, so there isn't anything we can tell you other than: Get rid of it. Copying and pasting random snippets from the Internet will definitely not teach you proper PHP, and it may not even be allowed. Just because the code is online doesn't mean it's in the public domain.

 

If you want to learn PHP, write your own code. And start small. It doesn't make sense to implement a complex network script when you have no idea how the language basics work. Start with something like Codeacademy, write simple test scripts and then slowly move to more advanced tasks.

Link to comment
Share on other sites

A variable is a simple storage holder. You create var $x and you assign it a value. Then you use that variable wherever you need that value. Or you do a calculation and assign the answer to the var $x and use it later on. Simple right?

 

An array is a way of gathering a collection of data items under one Name. Say you want to create an array of your vital statistics, that is - name, age, address, sex. So you create an array and assign it values with either numbers (assigned sequentially as you make additions to it) or "names" (that you assign as you make additions). Here's a sample:

 

$stats = array(); // define the array
$stats[] = 'Bob';
$stats[] = 39;
$stas[] = '5 Main St.';
$stats[] = 'Male';

A print_r of this array would give you

0 = Bob
1 = 39
2 - 5 Main St.
3 = Male

Or an associative array (names):

$stats = array(); // define the array
$stats['name'] = 'Bob';
$stats['age'] = 39;
$stas['addr'] = '5 Main St.';
$stats['gender'] = 'Male';

This would give you:

name = Bob
age = 39
addr = 5 Main St.
gender = Male

To reference a specific element of an array (that's what they are called - elements) you reference it by the array name ($stats) and the index you want (the thing in the brackets). Use a number for the sequential array form or a quoted string for an associative array.

 

So to get the address you ask for $stats['addr'] or $stats[2]. Obviously the associative format works better in this case. To look at all of the contents in the whole array you can do this:

foreach ($stats as $k=>$v)
{
echo "$k = $v<br>";
}

What this says is "take the array $stats and loop thru it calling each index value $k and each corresponding value $v and output each pair on a line by itself.

 

If this doesn't help then you REALLY need to knuckle down and do some reading. Arrays are a basic structure of EVERY programming language (well, maybe not assembly code) and should be mastered - as much as mastering means to such a simple concept.

Edited by ginerjm
Link to comment
Share on other sites

So a old dad and his son were talking on the porch.

 

Dad says, "Your mother and I have been going to the memory clinic for us old timers.  I think its helping."

 

Son:  "oh? Whats it called?"

 

Dad:  "Um.. well darn.  Its a flower.   Usually red but they come in other colors... Um... thorny... uh..."

 

Son:  A rose?

 

Dad: "YES! That's it!    - Hang on"   He turns to the door and shouts "Hey Rose - Whats the name of that memory clinic we go to?"

 

=================================

 

Okay, Jacques1:  I did what you said, with the exception of copying jinerjm's example, only to avoid any typos.   This is otherwise an original work.

 

jinerjm... The following code works just fine.   Thank you guys!

        while(1)  {
           $r = socket_recvfrom($socket, $buf, 16, 0, $from, $port);   // reads at most 16 bytes.  I only need 1.

           //Convert to array of decimal values
           $array = unpack("C*", $buf);   //  unpack() smells like split() from my perl days.

           foreach ($array as $k=>$v)     // "$array as $k=>$v"?   I'm lost on this one.  Anyone care to explain??
              {
               echo "$k = $v \n";   // console output for testing.  \n instead of <BR>
              }
        }


I hope the above snippet can be of use to the next person trying to read UDP datagrams from the web.

 

Also whats a good non-eclipse IDE ?   Preferably free.

Thank you very much!

Edited by GaryM
Link to comment
Share on other sites

The code is still nonsense. That unpack() stuff you've taken from the Stackoverflow post does absolutely nothing useful.

 

The full datagram is already in $buf. It's a PHP string, so you can access any character/byte you want directly via its index. Again: Learn the basics.

 

 

 

I think jinerjm's above post on arrays should be a forum sticky

 

There are thousands of PHP tutorials, videos and free courses just one Google search away (I've already pointed you to one).

Link to comment
Share on other sites

You would be better to go to php.net (The direct source for php into) and check over the functions. People even give examples on them. 

 

They (php.net) even provide you where you can download a free database to check MySQL functions (use PDO or mysqli) and it called world.sql (I believe).

 

What I do is have a folder (I call it phpSandbox) where I put all my learning and testing scripts in.

 

Here's just one of many scripts I have written over the years.

<?php
include 'lib/includes/connect/connect.php';

$db_options = [
    /* important! use actual prepared statements (default: emulate prepared statements) */
    PDO::ATTR_EMULATE_PREPARES => false
    /* throw exceptions on errors (default: stay silent) */
    , PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
    /* fetch associative arrays (default: mixed arrays)    */
    , PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ
];
if (filter_input(INPUT_POST, submit)) {

    $pdo = new PDO('mysql:host=' . DATABASE_HOST . ';dbname=world;charset=utf8', DATABASE_USERNAME, DATABASE_PASSWORD, $db_options);

    $query = 'SELECT Name, CountryCode, District, Population FROM city WHERE CountryCode=:CountryCode ORDER BY District'; // Set the Search Query:

    $stmt = $pdo->prepare($query); // Prepare the query:

    $result = $stmt->execute([':CountryCode' => filter_input(INPUT_POST, countryCode)]); // Execute the query with the supplied user's parameter(s):
}
?>
<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Database Search</title>
        <link rel="stylesheet" href="lib/css/reset.css">
        <link rel="stylesheet" href="lib/css/grids.css">
        <link rel="stylesheet" href="lib/css/searchstyle.css">
    </head>
    <body>
        <div class="container seachBackground">
            <form id="searchForm" action="search.php" method="post">
                <label for="searchStyle">search</label>
                <input id="searchStyle" type="text" name="countryCode" value="" placeholder="Enter Country Code (For Exampe : USA)..." tabindex="1" autofocus>
                <input type="submit" name="submit" value="submit" tabindex="2">
            </form>
        </div>
        <div <?= $result ? 'class="turnOn" ' : 'class="turnOff" '; ?>>
            <table id="search" summary="Cities Around the World!">
                <thead>
                    <tr>
                        <th scope="col">City</th>
                        <th scope="col">Country Code</th>
                        <th scope="col">District / State</th>
                        <th scope="col">Population</th>
                    </tr>
                </thead>
                <tbody>
                    <?php
                    if ($result) {
                        while ($record = $stmt->fetch()) {
                            echo "<tr>";
                            echo '<td>' . $record->Name . "</td>";
                            echo '<td>' . $record->CountryCode . "</td>";
                            echo '<td>' . $record->District . "</td>";
                            echo '<td>' . $record->Population . "</td>";
                            echo "</tr>";
                        }
                    }
                    ?>
                </tbody>
            </table>
        </div>

    </body>
</html>

I personally would NOT go to a forum and grab scripts that other people are asking help on, for you don't know where exactly they are at with their problem(s) or that if they are committed in resolving their problem. I have seen many people who post for help on their problems and never acknowledge they have resolved the issue. Do you really want to copy a script from someone like that? I know I wouldn't. Another thing that I have learned over the last couple of years, is while you might belong to many help forums the key to getting a resolution is to post on only ONE forum and have plenty of patience. People who answer you questions are doing out of their desire to help people and they too have other important things that have to get done first. Someone will eventually answer you question. One last thing make your topic relevant to your problem, something like "I am having a problem with updating in PHP PDO?". While that might even be a little vague, it's way better than "HELP! I Have a Problem". 

Edited by Strider64
Link to comment
Share on other sites

Nonsense code or not, it works now and I've logged thousands of bytes without error.

Removing the unpack() line and adjusting for variable names, I'm back where I was before I showed up here.

 

The nonsense code I have came from PHP.net

Jacques1
Show us, please.  How would a guru such as yourself, unpack that binary data?  You give comments and criticism freely.  can you even do it?

Again, what IDE are the cool kids here using?

  • Like 1
Link to comment
Share on other sites

  • Solution

If you're just after the numerical value of the first byte, then you can simply do:

$byte = ord($buf[0]);
echo $byte;
Strings in PHP can be treated like an array and you can access the individual bytes directly by using the appropriate index. ord will give you the numeric value of a byte. There's no need for unpack at all in this code. If you want all the bytes you can do a for loop over the length of the string and run ord on each byte individually. Edited by kicken
Link to comment
Share on other sites

kicken... that works beautifully.  I knew it was simple.   I had forgotten about ord() - the anti chr().

Thanks everyone.

I still want to know what IDE (not eclipse) do you guys recommend.  (I've had a botched eclipse install on this PC and I gave up trying to fix it.)

Edited by GaryM
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.