i have problem with $length of substr function
my CODE
$string='I love stackoverflow.com';
function arabicSubStr($value,$start,$length=false){
return mb_substr($value,$start,$length,'UTF-8');
}
echo arabicSubStr($string,7);//outputs nothing
echo substr($string,7);//outputs stackoverflow.com
The reason of the problem is:
If length is given and is 0, FALSE or NULL an empty string will be returned.
So, How i can fix the problem?
i won't use strlen($string)
EDITE
I know the reason is because i've defined $length as false
And i am here to know what should i put in $length parameter to avoid this error?
i am trying to put -1 it's returns //stackoverflow.co
Since the reason you're getting an empty string is specified entirely by the content of your question (using 0, FALSE or NULL), I assume you just want a way to get the rest of the string.
In which case, I'd use something like:
function arabicSubStr ($value, $start, $length = -1) {
if ($length == -1)
$length = mb_strlen ($value, 'UTF-8') - $start;
return mb_substr ($value, $start, $length, 'UTF-8');
}
You need to do it this way since there is no sentinel value of length that means "the rest of the string". Positive numbers (and zero) will limit the size to that given, negative numbers will strip off the end of the string (as you show in your question edit).
If you really don't want to use a string length function, you could try a value of 9999 (or even higher) and hope that:
the mb_substr() function will only use it as a maximum value; and
you won't pass in any strings 10K or more.
In other words, something along the lines of:
function arabicSubStr ($value, $start, $length = 9999){
return mb_substr ($value, $start, $length, 'UTF-8');
}
Though keep in mind I haven't tested that, I don't have any PHP environments at my current location.
It's because you have $length set to false as the default parameter for your function, which effectivley means you want it to return a substring of 0 length.
Unfortunately, if you have to set the final parameter (the charset) which I imagine you do, then you have to calculate the length of the string first, so something like:
function arabicSubStr($value,$start,$length=false){
$length = ($length) ? $length : mb_strlen($value,'UTF-8') - $start;
return mb_substr($value,$start,$length,'UTF-8');
}
Related
I am trying to convert a hex string into a signed integer.
I am able to easily transfer it into an unsigned value with hexdec() but this does not give a signed value.
Edit:
code in VB - the two "AA" hex values are representative.
Dim bs(2) As Byte
bs(1) = "AA"
bs(2) = "AA"
Dim s As Short
s = BitConverter.ToInt16(bs, 1)
Check out this comment via php.net:
hexdec() returns unsigned integers. For example hexdec("FFFFFFFE") returns 4294967294, not -2. To convert to signed 32-bit integer you may do:
<?php
echo reset(unpack("l", pack("l", hexdec("FFFFFFFE"))));
?>
As said on the hexdec manual page :
The function can now convert values
that are to big for the platforms
integer type, it will return the value
as float instead in that case.
If you want to get some kind of big integer (not float), you'll need it stored inside a string... This might be possible using BC Math functions.
For instance, if you look in the comments of the hexdec manual page, you'll find this note
If you adapt that function a bit, to avoid a notice, you'll get :
function bchexdec($hex)
{
$dec = 0;
$len = strlen($hex);
for ($i = 1; $i <= $len; $i++) {
$dec = bcadd($dec, bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i))));
}
return $dec;
}
(This function has be copied from the note I linked to ; and only a bit adapted by me)
And using it on your number :
$h = 'D5CE3E462533364B';
$f = bchexdec($h);
var_dump($f);
The output will be :
string '15406319846273791563' (length=20)
So, not the kind of big float you had ; and seems OK with what you are expecting :
Result from calc.exe =
15406319846273791563
Hope this help ;-)
And, yes, user notes on the PHP documentation are sometimes a real gold mine ;-)
I've been trying to find a decent answer to this question and so I wrote this function which works well for a Hex string input, returning a signed decimal value.
public function hex_to_signed_int($hex_str){
$dec = hexdec($hex_str);
//test is value negative
if($dec & pow(16,strlen($hex_str))/2 ){ return $dec-pow(16,strlen($hex_str));}
return $dec;
}
I used this a while back to grab images from something but since I just tried using it again it is giving me this error:
Warning: str_repeat(): Second argument has to be greater than or equal to 0 in C:\inetpub\wwwroot\resource_update.php on line 121
This is the function for what its referring to so if anyone could help that would be great:
function consoleLogProgressBar($current, $size, $unit = "kb")
{
$length = (int)(($current/$size)*100);
$str = sprintf("\r[%-100s] %3d%% (%2d/%2d%s)", str_repeat("=", $length).($length==100?"":">"), $length, ($current/($unit=="kb"?1024:1)), $size/($unit=="kb"?1024:1), " ".$unit);
consoleLog($str, true);
}
Sounds like $length is returning a negative number? You could troubleshoot as follows:
$length = (int)(($current/$size)*100);
var_dump($length);
exit;
If that is in fact the case, then you could wrap it in the abs() function which will always return an absolute value:
$length = (int) abs(($current/$size)*100);
Of course, that is an ugly hack and doesn't solve the real issue. Either way, the first step is determine why $length isn't what you expect it to be.
I have a problem with this function always my mt_rand() give me the same number:
$hex = 'f12a218a7dd76fb5924f5deb1ef75a889eba4724e55e6568cf30be634706bd4c'; // i edit this string for each request
$hex = hexdec($hex);
mt_srand($hex);
$hex = sprintf("%04d", mt_rand('0','9999'));
$hex is always changed, but the result is always the same 4488.
Edit
$hex = str_split($hex);
$hex = implode("", array_slice($hex, 0, 7));
mt_srand($hex);
$number = sprintf("%04d", mt_rand('0','9999'));
http://php.net/manual/en/function.mt-srand.php
Your problem is, that you always end up with a float value in your variable $hex. And the function mt_srand() as you can also see in the manual:
void mt_srand ([ int $seed ] )
Expects an integer. So what it does is, it simply tries to convert your float value to an integer. But since this fails it will always return 0.
So at the end you always end up with the seed 0 and then also with the same "random" number.
You can see this if you do:
var_dump($hex);
output:
float(1.0908183557664E+77)
And if you then want to see in which integer it will end up if it gets converted you can use this:
var_dump((int)$hex);
And you will see it will always be 0.
Also if you are interested in, why your number ends up as float, it's simply because of the integer overflow, since your number is way too big and accoding to the manual:
If PHP encounters a number beyond the bounds of the integer type, it will be interpreted as a float instead. Also, an operation which results in a number beyond the bounds of the integer type will return a float instead.
And if you do:
echo PHP_INT_MAX;
You will get the max value of int, which will be:
28192147483647 //32 bit
9223372036854775807 //64 bit
EDIT:
So now how to fix this problem and still make sure to get a random number?
Well the first thought could be just to check if the value is bigger than PHP_INT_MAX and if yes set it to some other number. But I assume and it seems like you will always have such a large hex number.
So I would recommend you something like this:
$arr = str_split($hex);
shuffle($arr);
$hex = implode("", array_slice($arr, 0, 7));
Here I just split your number into an array with str_split(), to then shuffle() the array and after this I implode() the first 7 array elements which I get with array_slice().
After you have done this you can use it with hexdec() and then use it in mt_srand().
Also why do I only get the first 7 elements? Simply because then I can make sure I don't hit the PHP_INT_MAX value.
Haven't slept in awhile, so I'm probably missing something simple. Basically, I am taking a number and converting it to three characters. Max number of possibilities is 256*256*256 (16777216). I convert it with:
public function s_encode($num) {
$num = chr($num / 65536).chr($num / 256).chr($num % 256);
return bin2hex($num);
}
And convert it back with:
public function s_decode($hex) {
$a = pack("H*", $hex);
$b = ord(substr($a, 1, 1));
$c = ord(substr($a, 2, 1));
$d = ord(substr($a, 0, 1));
return (($d * 65536) + ($b * 256)) + $c;
}
What's strange, is this actually works. It does what I want it to, but how could it? In the first code, where I convert it to three characters, the second part of the conversion is:
chr($num / 256)
If the number is greater than 65536, this should cause an error, but it doesn't. If I were to use unpack instead of bin2hex, it will cause an error. bin2hex won't. Why and how is bin2hex so magical?
chr() only looks at the lowest 8 bits of its input:
echo "'".chr(320)."'";
yields...
'#'
as does...
echo "'".chr(64)."'";
http://ideone.com/65Itz
According to the comments in the php docs, chr will take the parameter modulo 256. Even negative integers work. bin2hex doesn't do that operation, and fails on invalid inputs.
This question already has answers here:
startsWith() and endsWith() functions in PHP
(34 answers)
Closed 8 years ago.
Example: I have a $variable = "_foo", and I want to make absolutely sure that $variable does not start with an underscore "_". How can I do that in PHP? Is there some access to the char array behind the string?
$variable[0] != "_"
How does it work?
In PHP you can get particular character of a string with array index notation. $variable[0] is the first character of a string (if $variable is a string).
You might check out the substr function in php and grab the first character that way:
http://php.net/manual/en/function.substr.php
if (substr('_abcdef', 0, 1) === '_') { ... }
Since someone mentioned efficiency, I've benchmarked the functions given so far out of curiosity:
function startsWith1($str, $char) {
return strpos($str, $char) === 0;
}
function startsWith2($str, $char) {
return stripos($str, $char) === 0;
}
function startsWith3($str, $char) {
return substr($str, 0, 1) === $char;
}
function startsWith4($str, $char){
return $str[0] === $char;
}
function startsWith5($str, $char){
return (bool) preg_match('/^' . $char . '/', $str);
}
function startsWith6($str, $char) {
if (is_null($encoding)) $encoding = mb_internal_encoding();
return mb_substr($str, 0, mb_strlen($char, $encoding), $encoding) === $char;
}
Here are the results on my average DualCore machine with 100.000 runs each
// Testing '_string'
startsWith1 took 0.385906934738
startsWith2 took 0.457293987274
startsWith3 took 0.412894964218
startsWith4 took 0.366240024567 <-- fastest
startsWith5 took 0.642996072769
startsWith6 took 1.39859509468
// Tested "string"
startsWith1 took 0.384965896606
startsWith2 took 0.445554971695
startsWith3 took 0.42377281189
startsWith4 took 0.373164176941 <-- fastest
startsWith5 took 0.630424022675
startsWith6 took 1.40699005127
// Tested 1000 char random string [a-z0-9]
startsWith1 took 0.430691003799
startsWith2 took 4.447286129
startsWith3 took 0.413349866867
startsWith4 took 0.368592977524 <-- fastest
startsWith5 took 0.627470016479
startsWith6 took 1.40957403183
// Tested 1000 char random string [a-z0-9] with '_' prefix
startsWith1 took 0.384054899216
startsWith2 took 4.41522812843
startsWith3 took 0.408898115158
startsWith4 took 0.363884925842 <-- fastest
startsWith5 took 0.638479948044
startsWith6 took 1.41304707527
As you can see, treating the haystack as array to find out the char at the first position is always the fastest solution. It is also always performing at equal speed, regardless of string length. Using strpos is faster than substr for short strings but slower for long strings, when the string does not start with the prefix. The difference is irrelevant though. stripos is incredibly slow with long strings. preg_match performs mostly the same regardless of string length, but is only mediocre in speed. The mb_substr solution performs worst, while probably being more reliable though.
Given that these numbers are for 100.000 runs, it should be obvious that we are talking about 0.0000x seconds per call. Picking one over the other for efficiency is a worthless micro-optimization, unless your app is doing startsWith checking for a living.
This is the most simple answer where you are not concerned about performance:
if (strpos($string, '_') === 0) {
# code
}
If strpos returns 0 it means that what you were looking for begins at character 0, the start of the string.
It is documented thoroughly here: http://uk3.php.net/manual/en/function.strpos.php
(PS $string[0] === '_' is the best answer)
function starts_with($s, $prefix){
// returns a bool
return strpos($s, $prefix) === 0;
}
starts_with($variable, "_");
Here’s a better starts with function:
function mb_startsWith($str, $prefix, $encoding=null) {
if (is_null($encoding)) $encoding = mb_internal_encoding();
return mb_substr($str, 0, mb_strlen($prefix, $encoding), $encoding) === $prefix;
}
To build on pinusnegra's answer, and in response to Gumbo's comment on that answer:
function has_leading_underscore($string) {
return $string[0] === '_';
}
Running on PHP 5.3.0, the following works and returns the expected value, even without checking if the string is at least 1 character in length:
echo has_leading_underscore('_somestring').', ';
echo has_leading_underscore('somestring').', ';
echo has_leading_underscore('').', ';
echo has_leading_underscore(null).', ';
echo has_leading_underscore(false).', ';
echo has_leading_underscore(0).', ';
echo has_leading_underscore(array('_foo', 'bar'));
/*
* output: true, false, false, false, false, false, false
*/
I don't know how other versions of PHP will react, but if they all work, then this method is probably more efficient than the substr route.