Now I am dealing with PHP but I`ve stucked with a strange issue:
I am making a simple foo for string length:
function slen($str) {
$len;
for ( $len=0; $str[$len]; $len++ ) {
/* while tehre is a symbol in $str continue counting, old C metnod */
}
return (int)$len;
}
it`s on as a code, and outputs the length but it booms with an PHP warning message :
PHP Notice: Uninitialized string offset: 3 in /home/ilian/Desktop/SERVER/ex4.php on line 5
And on my line 5 is the for loop initialization. So I got that PHP might be confusing by not knowing what kind of variables it checks for TRUE in that array because it can be
"Array", "HELLO", "MESS", 50 and length is 4 which is correct, but in the case I aam checking a simple string for length. Any easygoing explanation?
The problem is that at some point your condition ($str[$len]) will try to access an offset beyond the end of the string. That's your stopping condition, but that stopping condition throws the notice, since accessing an undefined offset is considered an error (and rightly so). You'll need to check whether the offset exists using isset($str[$len]), which does not throw a notice.
You don't have to write a function to get the length of a string, PHP has this built in for you in several internal functions:
strlen - Length of a string
mb_strlen - Length of a string which may have multi-byte characters within it
count - Length of an array or count of items in an object
If all you need is to count how long a string is, go with strlen, for arrays you'd use count. Much better than rolling your own.
Related
Debugging legacy code and I have a strange issue. The legacy code is being moved to PHP 7.2. I don't know which version of PHP it was originally written for but it does work in PHP 5.6.
Below is my example of the problem...
$variable = '';
$variable['key'] = 'Hello World!';
echo $variable['key'] // H
When I echo $variable['key'] it only gets the first character from the value. I know now that it is because $variable is initially declared as a string.
But why does this work in PHP 5.6? What can I do to make this work in 7.2 without trawling through thousands of lines of code?
Is there a directive like strict_types I can use?
From php.net
Warning
Writing to an out of range offset pads the string with spaces. Non-integer types are converted to integer. Illegal offset type emits E_NOTICE. Only the first character of an assigned string is used. As of PHP 7.1.0, assigning an empty string throws a fatal error. Formerly, it assigned a NULL byte.
http://php.net/manual/en/language.types.string.php#language.types.string.substr
So "key" is converted to 0, and the first character is set.
Because this is a char type, only "H" is set from the given string.
$variable = '';
$variable['key'] = 'Hello World!';
echo $variable;
echo $variable['key'];
If you change your code to the above you can see better what happens.
So the text 'ello World!' is lost and gone in PHP >= 7.1 because you set the first character, the type stays string.
In php 5.6 you will get
Notice: Array to string conversion in /in/N2poP on line 6
So in prior versions you overwrite the complete variable, and the initial empty string would be gone, PHP simply creates a new array. This behavior only happens with an empty string!
This is also noted in the documentation:
http://php.net/manual/en/language.types.string.php#language.types.string.substr
Note: As of PHP 7.1.0, applying the empty index operator on an empty
string throws a fatal error. Formerly, the empty string was silently
converted to an array.
The easiest solution would be removing the $variable = ''; part, it's invalid anyway and never used in your legacy code. or by replacing it with $variable = [];
Because this behavior only happens with an empty string in php < 7.1 you could use a regular expression to find all places where you should refactor to fix the issue.
I'll try to explain it.
i have a array:
$arrayTime = array(0=>"07",1=>"09", 3=>"13", 4=>"15", 5=>"17", 6=>"19");
Here you can see that is not defined offset 2
and now i need for my array and on offset 2 push number 0(for example)
I tried use this:
if($arrayTime[$i]==""){
$arrayTime[$i]=0;
}
Yes it works but 50 to 50 array looks like this:
$arrayTime = array(0=>"07",1=>"09", 3=>"13", 4=>"15", 5=>"17", 6=>"19",2=>"0");
but on the line where is the if it throws an error:
Notice: Undefined offset: 2 in C:\wamp\www\xxx.php on line 10
So i need same result, but without error.
Thanks for your help all :)
First of all, it doesn't throw an error. It gives you a warning about a possible bug in your code.
if($arrayTime[$i]==""){}
This attempts to access $arrayTime[$i] to retrieve a value to compare against your empty string.
The attempt to read and use a non-existing array index to get a value for comparison is the reason why it throws the warning as this is usually unexpected. When the key does not exist null is used instead and the code continues executing.
if(null == ""){} // this evaluates to true.
Because you are comparing against an empty string "", your answer would be empty():
if(empty($arrayTime[$i])){}
It means you are expecting a key not to exist and at the same time you are checking the value for emptyness. See the type comparison table to see what is and what is not considered 'empty'.
The same rules apply to isset() and is_null(), it wont throw the notice if the key does not exist. So choose the function that best serves your needs.
Keep in mind that by using any of these functions you are checking the value and not if the key exists in the array. You can use array_key_exists() for that.
if(array_key_exists($i, $arrayTime)){}
to add zeroes to your non-defined indexes without getting a Notice you should evaluate if the desired index to compare exists, so instead of comparing directly try checking the existence of the index first by using isset method, checking if the variable is defined and isn't NULL.
So your code to validate should look like this:
//check for the index before tryin' to acces it
if( !isset($arrayTime[$i]) ){
$arrayTime[$i]=0;
}
Hope it works for you.
I am dealing with a strange problem in PHP 5.2.6, serializing objects.
Apparently, PHP stores protected variables members with an asterix ahead of its name. That is normal and correct, however, look at the following example:
O:18:"object__songChords":1:{s:9:"*chords"}
*chords does not contain 9 characters, but 7 (with the asterix).
Naturally, i assumed that there is some misunderstanding on my side, and that PHP just counts the quotes, but when i compare this to other strings stored, i find that this is not the case.
Bottomline is that PHP fails to unserialize these objects, although the classes have not changed.
Notice: unserialize(): Error at offset 43 of 867 bytes in ...
Can anyone offer some insight on this?
EDIT (providing the class)
class object__songChords {
protected $chords;
protected $lyrics;
}
Please note that i stripped the above serialization example for the sake of simplicity – the actual serialization string of course contains both properties.
The count is not off, there are two \0 null characters separating the *, one on each side:
$o = new object__songChords;
echo addslashes(serialize($o));
Yields:
O:18:\"object__songChords\":2:{s:9:\"\0*\0chords\";N;s:9:\"\0*\0lyrics\";N;}
So currently I'm trying to fix up some old code for a stats server for a game (that is definitely outdated, and has been replaced recently with a new version). MUCH of the code is deprecated, so it's kind of guesswork on fixing it right, but I found a section thats completely broken that I have no idea how to fix, and it's causing a fatal error.
The code is as follows
for ($i=0; $i<$armyCount; $i++)
{
$summary['total']['time'] += $armies[0]['time'.$i];
$summary['total']['win'] += $armies[0]['win'.$i];
$summary['total']['loss'] += $armies[0]['loss'.$i];
$summary['total']['score'] += $armies[0]['score'.$i];
$summary['total']['best'] += $armies[0]['best'.$i];
$summary['total']['worst'] += $armies[0]['worst'.$i];
$summary['total']['brnd'] += $armies[0]['brnd'.$i];
}
The errors I get are as follows
Notice: Uninitialized string offset: 0 in C:\xampp\htdocs\dontneedthis\playerstats.inc.php on line 136
Fatal error: Cannot use string offset as an array in C:\xampp\htdocs\dontneedthis\playerstats.inc.php on line 136
I've seen similar questions asked, and seen how they were resolved, but I don't fully understand how it was done, so don't quite know how to go about fixing this one. Any assistance would be awesome, and I fully intend to release the bugfixed and fully working code (whenever I get that done) to the community that remains.
It looks like your $armies[0]['time'.$i] is initialized as an empty string and not as an array (likely $armies= "").
Notice: Uninitialized string offset: 0
That means that php tries to access your string-variable $armies as an array. If the string is non-empty then this would result in getting single letters from that string. But it seems that $armies is an empty string and so getting the letter with index 0 is not possible.
Fatal error: Cannot use string offset as an array
means that the result of the operation above (which showed the notice) cannot be accessed as an array. Remember that $armies is a astring and the first letter of the string was accessed and the result of this attempt will be accessed as an array.
Try resolving how the $armies variable is filled and why its filled the wrong way.
$armies is an empty string, and you are treating it as any array, in an unrecoverable way.
Show us what $armies should look like, what you get when you var_dump($armies);, and the code from where you assigned it, and we'll help you work out what went wrong.
As many of you already know, PHP 5.4 alpha has been released. I have a question regarding the following.
Simplified string offset reading.
$str[1][0] is now a legal construct.
How exactly does $str[1][0] work?
EDIT: http://php.net/releases/NEWS_5_4_0_alpha1.txt
It just means that when reading a string offset PHP returns a string again, on which you again can access an offset. (And on that access yet another offset. It gets funny with $str[0][0][0][0][0][0])
Before PHP 5.4 you would get an "Cannot use string offset as an array" error.
This is a side effect, and was mentioned in the proposal here:
http://php.markmail.org/thread/yiujwve6zdw37tpv
The feature is speed/optimization of string offsets.
Hi,
Recently I noticed that reading of
string offset is performed in two
steps. At first special string_offset
variant of temporary_variable is
created in
zend_fetch_dimension_address_read()
and then the real string value is
created in
_get_zval_ptr_var_string_offset().
I think we can create the real string
in the first place. This makes 50%
speed-up on string offset reading
operation and allows to eliminate some
checks and conditional brunches in VM.
The patch is attached (don't forget to
regenerate zend_vm_execute.h to test
it). However it changes behavior in
one bogus case. The following code now
will emit "b" (currently it generates
a fatal error - cannot use string
offset as an array).
$str = "abs";
var_dump($str[1][0]);
I think it's not a problem at all. "b"
makes sense because "abs"[1] -> "b"
and "b"[0] -> "b".
I'm going to commit the patch in case
of no objections.
Thanks. Dmitry.
This can actually create some interesting bugs when you upgrade code from php 5.3 to 5.4.
In 5.3 this construct would return false:
$array = array("This is a string");
echo isset($array[0][0][0]);
In 5.4 this would return true.