I have a task. I need to rewrite C++ code to PHP.
#include <iostream>
using namespace std;
struct Structure {
int x;
};
void f(Structure st, Structure& r_st, int a[], int n) {
st.x++;
r_st.x++;
a[0]++;
n++;
}
int main(int argc, const char * argv[]) {
Structure ss0 = {0};
Structure ss1 = {1};
int ia[] = {0};
int m = 0;
f(ss0, ss1, ia, m);
cout << ss0.x << " "
<< ss1.x << " "
<< ia[0] << " "
<< m << endl;
return 0;
}
return of a compiler is 0 2 1 0. I have rewrote this code in PHP like this:
<?php
class Structure {
public function __construct($x) {
$this->x = $x;
}
public $x;
}
function f($st, $r_st, $a, $n) {
$st->x++;
$r_st->x++;
$a[0]++;
$n++;
}
$ss0 = new Structure(0);
$ss1 = new Structure(1);
$ia = [0];
$m = 0;
f($ss0, $ss1, $ia, $m);
echo $ss0->x . " "
. $ss1->x . " "
. $ia[0] . " "
. $m . "\n";
return of this code is: 1 2 0 0. I know PHP and I know why it is returning this values. I need to understand how in C++ struct works and why a[0]++ is globally incremented. Please help to rewrite this code on PHP. I also know than there is no struct in PHP.
Difference between:
function f($st, $r_st, $a, $n)
void f(Structure st, Structure& r_st, int a[], int n)
in C++ you always specify, pass by value or by reference, but in PHP there are some pre-defined rules.
Fix for 1st output
C++ part: st is passed by value, and original value, which you pass here is not changed. r_st is passed by reference, and original value is changed.
PHP part: both arguments are passed by reference, since they are classes.
Simple fix there is to clone object st and pass it to function to mimic C++ pass-by-copy, or clone it inside function.
Fix for 3rd output
in C++ int a[] is passed as pointer, so, original value is changed, but in PHP it is passed by value, and it is unchanged outside.
Simple fix for it would be &$a instead of $a in function parameters.
PS. I'm C++ developer, so, PHP part can be inaccurate in terminology.
The ss0 and ss1 variables you are passing in are by object accessors to that function. See Objects and references
The variables passed in are by value. See Passing by Reference
Please help to rewrite this code on PHP.
Do it like this
function f($st, $r_st, &$a, $n) {
$st= clone $st; #clone to get a real copy, not a refer
$st->x++;
$r_st->x++;
$a[0]++; #&$a to simulate ia[] (use as reference)
$n++;
}
Read about references in PHP. I'm not a C++ dev.
http://php.net/manual/en/language.oop5.cloning.php
Related
This is a complete noob question.
So here is my code in C,
#include<stdio.h>
int main()
{
int I, X=4;
double I0;
double COEFF1[7];
double COEFF2[9];
/*Coefficient 1 I0*/
COEFF1[0]=0.0045813;
COEFF1[1]=0.0360768;
COEFF1[2]=0.2659732;
COEFF1[3]=1.2067492;
COEFF1[4]=3.0899424;
COEFF1[5]=3.5156229;
COEFF1[6]=1.0000000;
/*Coefficient 2 I0*/
COEFF2[0]=0.00392377;
COEFF2[1]=-0.01647633;
COEFF2[2]=0.02635537;
COEFF2[3]=-0.02057706;
COEFF2[4]=0.00916281;
COEFF2[5]=-0.00157565;
COEFF2[6]=0.00225319;
COEFF2[7]=0.01328592;
COEFF2[8]=0.39894228;
if(X>=3.75)
{
I0=COEFF2[0];
for(I=1;I<9;I++)
{
I0=(3.75/X)*I0+COEFF2[I];
printf("%i\n", I0);
}
//return I0/(sqrt(X)*exp(-X));
}
else
{
I0=COEFF1[0];
for(I=1;I<7;I++)
{
I0=I0*(X/3.75)*(X/3.75)+COEFF1[I];
}
//return I0;
}
return 0;
}
And with little housekeeping, this is my translated code in PHP,
<?php
$coeff1 =array();
$coeff2 =array();
/*Coefficient 1 $i0*/
$coeff1[0]=0.0045813;
$coeff1[1]=0.0360768;
$coeff1[2]=0.2659732;
$coeff1[3]=1.2067492;
$coeff1[4]=3.0899424;
$coeff1[5]=3.5156229;
$coeff1[6]=1.0000000;
/*Coefficient 2 $i0*/
$coeff2[0]=0.00392377;
$coeff2[1]=-0.01647633;
$coeff2[2]=0.02635537;
$coeff2[3]=-0.02057706;
$coeff2[4]=0.00916281;
$coeff2[5]=-0.00157565;
$coeff2[6]=0.00225319;
$coeff2[7]=0.01328592;
$coeff2[8]=0.39894228;
$x = 4;
if($x>=3.75)
{
$i0=$coeff2[0];
for($i=1;$i<9;$i++)
{
$i0=(3.75/$x)*$i0+$coeff2[$i];
printf($i0."<br />");
}
//return $i0/(sqrt($x)*exp(-$x));
}
else
{
$i0=$coeff1[0];
for($i=1;$i<7;$i++)
{
$i0=$i0*($x/3.75)*($x/3.75)+$coeff1[$i];
}
//return $i0;
}
?>
But why won't they generate the same result?
http://imageshack.com/a/img59/3402/98ak.jpg
Please help. I'm stuck.
%i is the format specifier for int; I0 has type double but printf is being told to interpret it as int. You should use %f for doubles instead:
printf("%f\n", I0);
Maybe this bit might be useful too.
The difference in the output of the two programs can be attributed indeed to the line
printf("%i\n", I0);
in your C program where I0 is interpreted as an integer but its bit pattern was stored as a double type which uses different logic for organizing the bits (and in the standard variation also uses a different number of bits). What the printf function does is that it just takes whatever that bit pattern was (in the length of an integer) and prints it out like it was an integer - because you told it so (%i), hence the output of the program.
PHP uses dynamic type definition so your variables are interpreted in the context in which they are used (unless sometimes forced to be a certain type by casting or using settype()).
I.e.: $a = 1; will be an integer but if you do another assignment like $a += 0.5; it will be casted into a float automatically.
I have a modified MD5 hash function which I am using in PHP and VB.NET. When I run the PHP code on my local server (WAMP) I get a different result to the VB version. I have tried running the script on phpfiddle which gives the same result as the VB version.
I am thinking the problem could lie with my PHP settings on the WAMP server?
If I run the script below on my PC running WAMP the result I get is:
e5c35f7c3dea80fc68a4031582f34c25
When I run the exact same script on phpfiddle or php sandbox the result I get is (this is the expected result):
6337a43e8cd36058e80ae8cb4f465998
Setting aside for a moment the fact that what you are doing here sounds like a bad approach what ever the actual problem is that you are trying to solve, here is a direct answer to the question.
As I already outlined in a comment above, the root cause of the problems you are having is that PHP has no concept of unsigned integers, and it handles this by converting numbers that overflow the bounds of an integer to floating point (which doesn't play nice with bitwise operations). This means that, on 32-bit systems, your code won't work correctly, as MD5 works with unsigned 32-bit integers.
You will need to ensure that your code is "binary safe" - so that all numbers are represented as if they were unsigned 32-bit integers.
To do this you will need to re-implement the addition operator, and (with your current implementation) the bindec()/hexdec() functions. It's worth noting that your current approach to certain procedures is very inefficient - all that converting to/from hex strings, and places where binary is represented as ASCII strings - but I'll gloss over that for now while I show you how to quick-fix your current implementation.
Firstly let's take a look at the addition operation:
private function binarySafeAddition($a, $b)
{
// NB: we don't actually need 64 bits, theoretically we only need 33
// but 40 bit integers are confusing enough, and 33 bits is unrepresentable
$a = "\x00\x00\x00\x00" . pack('N', $a);
$b = "\x00\x00\x00\x00" . pack('N', $b);
$carry = $a & $b;
$result = $a ^ $b;
while ($carry != "\x00\x00\x00\x00\x00\x00\x00\x00") {
$shiftedcarry = $this->leftShiftByOne($carry);
$carry = $result & $shiftedcarry;
$result ^= $shiftedcarry;
}
return current(unpack('N', substr($result, 4)));
}
private function leftShiftByOne($intAsStr)
{
$p = unpack('N2', $intAsStr);
return pack('N2', ($p[1] << 1) | (($p[2] >> 31) & 0x00000001), $p[2] << 1);
}
private function add()
{
$result = 0;
foreach (func_get_args() as $i => $int) {
$result = $this->binarySafeAddition($result, $int);
}
return $result;
}
The real nuts-and-bolts of this routine is shamelessly stolen from here. There's also a helper function to perform the left-shift, because PHP doesn't let you left-shift strings, and a convenience wrapper function, to allow us to add an arbitrary number of operands together in a single clean call.
Next lets look at the bindec() and hexdec() replacements:
private function binarySafeBinDec($bin)
{
$bits = array_reverse(str_split($bin, 1));
$result = 0;
foreach ($bits as $position => $bit) {
$result |= ((int) $bit) << $position;
}
return $result;
}
private function binarySafeHexDec($hex)
{
$h = str_split(substr(str_pad($hex, 8, '0', STR_PAD_LEFT), -8), 2);
return (hexdec($h[0]) << 24) | (hexdec($h[1]) << 16) | (hexdec($h[2]) << 8) | hexdec($h[3]);
}
Hopefully these are reasonably self explanatory, but feel free to ask about anything you don't understand.
We also need to replace all those 0xffffffff hex literals with a binary safe implementation, as these will also result in a float on 32-bit systems. Here is a safe way to get the right-most 32 bits set in an integer, that will work on 32- and 64-bit systems:
private $right32;
public function __construct()
{
$this->right32 = ~((~0 << 16) << 16);
}
There's one other method we need to re-implement, and that's rotate(). This is because it uses a right-shift, and this shifts a copy of the sign bit on from the right. This means that the left-hand side of the rotated block will end up with all it's bits set, and this is obviously not what we want. We can overcome this by creating a number with only the target bits for the right-hand side set, and ANDing the right-hand side operand with it:
private function rotate ($decimal, $bits)
{
return dechex(($decimal << $bits) | (($decimal >> (32 - $bits)) & (~(~0 << $bits) & $this->right32)));
}
When you put all this together you come up with something like this, which works for me on 32- and 64-bit systems.
Ok i wanted to create a crawler with my PHP script. Certain parts of my crawler requires real fast manipulation of strings thats why i have decided to use a C/C++ program to assist my PHP script for that particular job. The following is my code:
$op=exec('main $a $b');
echo $op;
main is the executable file generated using my C file main.c i.e main.exe. in the above operation i just made a simple C program which accepts 2 values from PHP and returns the sum of the two values. the following is how my C program in looking like
#include< stdio.h >
#include< stdlib.h >
int main(int argc, char *argv[])
{
int i=add(atoi(argv[1]),atoi(argv[2]));
printf("%d\n",i);
return 0;
}
int add(int a, int b)
{
int c;
c=a+b;
return c;
}
i tried to execute the program via the CMD main 1 1 and it returned 2....it worked! when i entered them in the php script like this,
$a=1;
$b=1;
$op=exec('main $a $b');
echo $op;
it didn't work as expected so any ideas, suggestions or anything else i need to do on my code. I would be great if you could show me an example. THANKS IN ADVANCE!!!
You should enclosed the arguments of exec with double quotes since you're passing variables. And the output of your program is in the second argument of exec.
exec("main $a $b", $out);
print_r($out);
See exec() reference.
The function atoi() cannot distinguish invalid and valid inputs.
I suggest you use strtol() instead.
#include <stdio.h>
#include <stdlib.h>
void quit(const char *msg) {
if (msg) fprintf(stderr, "%s\n", msg);
exit(EXIT_FAILURE);
}
int add(int, int);
int main(int argc, char *argv[]) {
int a, b, i;
char *err;
if (argc != 3) quit("wrong parameter count");
a = strtol(argv[1], &err, 10);
if (*err) quit("invalid first argument");
b = strtol(argv[2], &err, 10);
if (*err) quit("invalid second argument");
i = add(a, b);
printf("%d\n", i);
return 0;
}
int add(int a, int b) {
return a + b;
}
You need to create an executable ./main.
And then use this code.It works
<?php
$a=1;
$b=1;
echo exec("./main $a $b");
?>
I am trying to pass over from php a string into C++, i managed to figure out how to pass numbers, but it doesn't work for letters. Here's what i have that works for PHP
<?php
$r = 5;
$s = 12;
$x= 3;
$y= 4;
$q= "Hello World";
$c_output=`project1.exe $r $s $x $y $q`; // pass in the value to the c++ prog
echo "<pre>$c_output</pre>"; //received the sum
//modify the value in php and output
echo "output from C++ programm is" . ($c_output + 1);
?>
This sends the variables r,s,x,y, and q to the C++ programm project1.exe and IT WORKS, but the problem is that it doesn't work for the string variable $q.
Here's the code that I have in my C++ programm, it's simple:
#include<iostream>
#include<cstdlib>
#include<string>
using namespace std;
int main(int in, char* argv[]) {
int val[2];
for(int i = 1; i < in; i++) { // retrieve the value from php
val[i-1] = atoi(argv[i]);
}
double r = val[0];
double s = val[1];
double x = val[2];
double y = val[3];
double q = val[4]; // here's the problem, as soon as i try to define val[4] as a string or char, it screws up
cout << r;
cout <<s;
cout << x;
cout << y;
cout << q;
// will output to php
return 0;
}
It works, but for the string "Hello world" which i pass through $q from PHP doesn't give me the string back (i know it's defined as a double, but as soon as i try to change it to a string or a char variable the code just doesn't compile).
Please explain to me how i have to go around this problem so that $q can be processed as a string. FYI, I am a newbie to programming (6 months in).
Try not converting the final argument using atoi(argv[i]). Just keep it as argv[i].
for(int i = 1; i < in-1; i++)
{
val[i-1] = atoi(argv[i]);
}
q = argv[i];
It doesn't work for letters because you are doing atoi(..)(which converts char-string to integer) in the C++ program.
Have some means of letting the program know what to expect -- whether a number or a string. May be the first argument can help the program differentiate, like may be the following:
$c_output = `project1.exe nnsnns 1 2 string1 3 4 string2`
Then you could do:
for(int i = 0/*NOTE*/,len=strlen(argv[1]); i < len; i++) { // retrieve the value from php
if (argv[1][i] == 'n'){
//argv[2+i] must be an integer
}else if (argv[1][i] == 's'){
//argv[2+i] is a string
}
}
Of course you should check if (strlen(argv[1]) == in-2).
BTW, in the C++ code above, val is a array holding 2 ints; and you are trying to access much beyond index 1.
To pass one single string to the C++ you would do something like the following:
$output = `project1.exe $q`; //Read below.
NOTE: $q must be a single word. No spaces, no extra characters like '|', '&', or any other character which the shell might interpret differently. $q must be clean before you pass that on to C++ Program. If $q is more than one word, use quotes.
C++ Part (Just try the following, then you can modify as you go along)
cout<<argv[1]<<endl;
I have some C++ code (segment seen below), I need to convert this to another language (namely PHP). The code, as seen, uses structs, which PHP doesn't do. I know I can "kind of" emulate structs through objects/arrays, however, this isn't the same. That is not my main problem though. I need a way to implement the sizeof() function found in C++ (since PHP's sizeof() function just counts the number of elements in an array/object).
typedef unsigned long Offset;
typedef unsigned long Size;
struct Location {
Offset offset;
Size size;
};
struct Header {
unsigned long magic;
unsigned long version;
struct Location elements;
struct Location ids;
struct Location strings;
struct Location integers;
struct Location decimals;
struct Location files;
};
int Build() {
Header theheader;
theheader.magic = *((unsigned long*)"P3TF");
theheader.version = 272;
theheader.elements.offset = sizeof(theheader);
theheader.elements.size = element_offset;
theheader.ids.offset = ((theheader.elements.offset + theheader.elements.size + 15) / 16) * 16;
theheader.ids.size = ids_offset;
theheader.strings.offset = ((theheader.ids.offset + theheader.ids.size + 15) / 16) * 16;
theheader.strings.size = string_offset;
theheader.integers.offset = ((theheader.strings.offset + theheader.strings.size + 15) / 16) * 16;
theheader.integers.size = 0;
theheader.decimals.offset = ((theheader.integers.offset + theheader.integers.size + 15) / 16) * 16;
theheader.decimals.size = 0;
theheader.files.offset = ((theheader.decimals.offset + theheader.decimals.size + 15) / 16) * 16;
theheader.files.size = file_offset;
theheader.padding[0] = 0;
theheader.padding[1] = 0;
fwrite(&theheader, 1, sizeof(theheader), file_handle);
}
Can anyone please point me in the right direction on how to do this?
Any help would be appreciated.
Obviously recreating sizeof from C will be a difficult feat, as C is statically-typed and, traditionally, sizeof is evaluated at run-time by the compiler. PHP is also pretty quiet about its memory usage.
One method of dynamically grabbing the size of an object is to use memory_get_usage (official PHP reference) before and after the allocation of the object in question. Of course, you'll run into some fun calculations when you compare the two memory usage values, as storing the values into variables will allocate memory also.
This is a pretty shaky method of recreating sizeof, but if it works it works.
You could simply sum all sizes of the objects in the array or object. However, that still only gets the length of strings, etc. If you want the actual size of the binary representation of the object, you'll have to do some additional math, such as converting all ints to 32 bits (or 64) and appending a null byte to all UTF-8 strings. If you're using charsets, do make sure that they are single-byte or at least measurable in bytes.
PHP does not have a function that checks the memory size of an object.