I have weird problem with data handling. I need to pick data from the user form, and handle it (generate xml).
The data is for example this:
2000;AC;1;60;5;5;Do your setup - meaning voltage, voltage type, test current, test time, ramp-up time, rampdown time, and user prompt.
I want to decide how to assemble my xml file based on the last value. If it is zero, there will be shorter xml assembly, while when there is text, there will be user prompt assembly of xml taggery.
So I explode the input into array, and check the value by:
If (empty($xplodline[6]) == true) {do this;}
else {do that;}
The problem is, that it always only does "that", and never "this", even when there is 0 in the $xplodline[6] as intended.
So I put echo $xplodline[6]; into {do that;} to see what´s happening.
The zero is echoed, (and while this action is in the cycle, I get other $xplodline[6]s from the cycle), and I see there is a space between the zero in the $xplodline[6] and next $xplodline[6] iteration. When I look into user form or temporary cleaned file with these values, there is no space between. Where could it come from?
When I put another array divider into the user form to make it ;0; there is no space, and If statement works well.
Here is the original data from the temporary cleaned file:
2000;AC;1;60;5;5;0
2000;AC;1;60;5;5;Set your cables for X10
2000;AC;1;60;5;5;Set your cables for X10
Any idea?
Ok, here is the code:
$stringer = fopen($tempfile, "r");
while(!feof($stringer)){
$oneline = fgets($stringer) ;
$xplodline = explode(";",$oneline) ;
$range01 = "gross" ;
$rampup = "100" ;
$rampdown = "100" ;
$rampupfunction = "false" ;
$rampdownfunction = "false" ;
$currentrange = "_1mA" ;
$assy01 = "1" ;
if ($xplodline[0] >= 3000) {$range01 = "gross" ;}
else {$range01 = "klein" ;}
if (empty($xplodline[4]) == false) {$rampupfunction = "true" ; $rampup = round($xplodline[0] / $xplodline[4]) ;}
if (empty($xplodline[5]) == false) {$rampdownfunction = "true" ;$rampdown = round($xplodline[0] / $xplodline[5]) ;}
if ($xplodline[2] < 1) {$currentrange = "_1mA";}
if ($xplodline[2] >= 1 && $xplodline[2] < 10) {$currentrange = "_10mA";}
if ($xplodline[2] >= 10 && $xplodline[2] < 100) {$currentrange = "_100mA";}
if (empty($xplodline[6]) == true) {$assy01 = $xmltestbegin.$xplodline[0]."V ".$xplodline[1].$xmltype.$xplodline[1].$xmlrange.$range01.$xmlrampup.$rampupfunction.$xmlrampdown.$rampdownfunction.$xmlcurrentrange.$currentrange.$xmlvoltage.$xplodline[0].$xmlrampupspeed.$rampup.$xmlrampdownspeed.$rampdown.$xmltesttime.$xplodline[3].$xmlcurrent.$xplodline[2].$xmlballast ;}
else {$assy01 = $xmlpromptbegin.$xplodline[6].$xmlpromptend.$xmltestbegin.$xplodline[0]."V ".$xplodline[1].$xmltype.$xplodline[1].$xmlrange.$range01.$xmlrampup.$rampupfunction.$xmlrampdown.$rampdownfunction.$xmlcurrentrange.$currentrange.$xmlvoltage.$xplodline[0].$xmlrampupspeed.$rampup.$xmlrampdownspeed.$rampdown.$xmltesttime.$xplodline[3].$xmlcurrent.$xplodline[2].$xmlballast ;}
file_put_contents ( $filename, $assy01, FILE_APPEND );
}
fclose($stringer);
My function works ok, every If except the last one, works...
From http://php.net/manual/en/function.fgets.php
Reading ends when length - 1 bytes have been read, or a newline (which is included in the return value), or an EOF (whichever comes first). If no length is specified, it will keep reading from the stream until it reaches the end of the line.
In short, there's always going to be a newline character in your last array entry. Clean it up by doing
$oneline = rtrim(fgets($stringer));
You can also consider:
$stringer = fopen($tempfile, "r");
while(!feof($stringer)){
$xplodline = fgetcsv($stringer,0,";");
//Rest of code as normal
which would let PHP handle the file as a CSV style file.
Related
I'm currently writing a simple Battleships game in PHP. At the start of the game, I generate three ship positions on a 5 x 5 board, with each ship occupying one square:
function generate_three_battleships($ships){
for ($n=0; $n<3; $n++){
// Generate new position, returned from function as string
$ship_position = generate_new_position();
// Check to ensure that the position is not already occupied - if so, recast
if (in_array($ship_position, $ships)){
$ship_position = generate_new_position();
}//if
// Assign position to array
array_push($ships, $ship_position);
}//for
}//generate_three_battleships
Each position is represented as a two-digit string, which represent cartesian coordinates (so for example, "32" represents y = 3, x = 2). This task is handled by the generate_new_position function:
When the game starts, the user will enter in their guesses for rows and columns:
function generate_new_position(){
// Generate x and y coordinates - cast to string for storage
$ship_row = (string)random_pos();
$ship_col = (string)random_pos();
$ship_position = $ship_row.$ship_col;
return $ship_position;
}//generate_new_position
The user then enters their guesses for rows and columns, and the game will check to see if there is a ship there:
// Generate battleships
generate_three_battleships($ships);
for($turn=1; $turn <= GUESSES; $turn++){
// First check to see if all ships have been sunk. If not, proceed with the game
if ($ships_sunk < 3){
$guess_row = (string)readline("Guess a row: ");
$guess_col = (string)readline("Guess a column: ");
$guess = $guess_row.$guess_col; // format guesses as strings
if(($guess_row=="") || ($guess_col=="") || ($guess_row < 0) || ($guess_col < 0) || ($guess_row >= BOARDSIZE) || ($guess_col >= BOARDSIZE)){
print("Oops, that's not even in the ocean. \n");
}
else if(array_search($guess, $ships) != false){
print("Congratulations! You sunk one of my battleships!\n");
$board[$guess_row][$guess_col] = "X";
$ships_sunk++;
}
}
However, the in_array function is consistently returning false for every guess, even if that guess is actually in the $ships array. I can't see where I am going wrong, as I have explicitly cast everything to string. Am I missing something obvious?
As some people have asked, the output of var_dump on $ships after generate_three_battleships has executed is as follows:
array(3) {
[0]=>
string(2) "12"
[1]=>
string(2) "30"
[2]=>
string(2) "03"
}
Unfortunately I don't have a complete answer because I am missing some information to understand what the problem is.
You can debug what's going on by printing the contents of the array using var_dump to see the actual contents of $ships and maybe forcing generate_new_position to always return the same value.
If you can't solve this problem yourself, could you post the contents of $ships (using var_dump) before and after the for loop?
<?php
session_start();
if(isset($_SESSION['enter']))
$_SESSION['enter']=$_SESSION['enter']+1;
else
$_SESSION['enter']=1;
if ($_SESSION['enter']=7) {
unset($_SESSION['enter']);
$_SESSION['enter']=1; // here I want to count from beginning if there are seven enters
}
$enter = $_SESSION['enter'];
$enter = sprintf("%03d", $enter);
echo $enter; //keep always 001
?>
So, I want to count page enters from 1 to 7 and then back to 1... and so on, but in the above case it always stays on 1.
Any help.
if ($_SESSION['enter']=7) {
==, not =
This is your problem:
if ($_SESSION['enter']=7) {
You are not comparing the values, but assigning it and that always returns a true value, causing the code after it to run.
Just change it to:
if ($_SESSION['enter']===7) {
In this case you can also skip the if and do:
$_SESSION['enter'] = ($_SESSION['enter'] % 7) + 1;
in your first if statement. More about the modulus operator.
I am trying to create a hit counter that once it reaches a certain number (in this case, 5), it will no longer display the amount of hits. This is my code:
<?php
$count = ("hits.txt");
$hits = file($count);
$hits[0] ++;
$fp = fopen($count , "w");
fputs($fp , "$hits[0]");
fclose($fp);
if ($hits > 5) {
echo "More than 5 hits";
}
else {
echo $hits[0];
}
?>
What am I doing wrong?
You are overcomplicating things. It would be much easier to do it like this:
$hits = file_get_contents('hits.txt');
++$hits;
file_put_contents('hits.txt', $hits);
if($hits > 5) {
echo 'Over 5!';
}
// else etc
As for your current code, the problem is that you don't test the number of hits with the correct syntax $hits[0] -- which you already use in fputs -- but with the wrong $hits instead. Remember that due to the way file works, $hits itself is an array. PHP will happily let you compare an array to an integer, and there are rules that define how the comparison works, but don't go there.
You need $hits[0] > 5:
if ($hits[0] > 5) {
echo "More than 5 hits";
}
The array value $hits when compared against a number 5 is compared as the string Array rather than the value of the array's first item. The string Array is always greater than 5.
More or less everything. In addition to other answers this
fputs($fp , "$hits[0]");
won't work as expected, you want either "{$hits[0]}" or $hits[0] (no quotes).
That is, if you don't care about concurrent access.
I already have the pieces mapped out in the array and it prints just fine
$board = array(
array('1','rs','1','rs','1','rs','1','rs'),
array('rs','1','rs','1','rs','1','rs','1'),
array('1','rs','1','rs','1','rs','1','rs'),
array('rs','bs','rs','bs','rs','bs','rs','bs'),
array('bs','rs','bs','rs','bs','rs','bs','rs'),
array('2','bs','2','bs','2','bs','2','bs'),
array('bs','2','bs','2','bs','2','bs','2'),
array('2','bs','2','bs','2','bs','2','bs')
);
1 = black pieces
2 = red pieces
rs = red square
bs = black square
this code parse the input of a player : example FROM F2 into (0,0) coordinates
function parseSquareFrom($square) {
if (strlen($square) != 2) {
return FALSE;
}
$coords = array(ord('A') - ord($square[0]), $square[1] - 1);
// Perform bounds-checking.
if ($coords[0] < 0 || $coords[0] > 7 || $coords[1] < 0 || $coords[1] > 7) {
return FALSE;
}
return $coords;
}
I have repeated the same function for the TO input ( to where the player wants to move the piece
my question is this next code a valid way to move with the functions above
$board[$coords1[0]-1][$coords1[1]+1] = $board[$coords[0]][$coords[1]];
$board[$coords[0]][$coords[1]] = 0;
//eating action
$board[$coords1[0]][$coords1[1]] = 0;
$board[$coords1[0]-2][$coords1[1]+2] = $board[$coords[0]][$coords[1]];
$way = ($_POST['way'] === 'up')? 1:-1;
$way = ($_POST['way'] === 'down')? -1:+1;
//if player is 'up' then the value of $way is 1 so
$board[$x+(-1*$way)][$y+(1*$way)] = $board[$coords[0]][$coords[1]]; // position 2,2 becomes 1,3
//if player is not 'up' then the value of $way is -1 so
$board[$x+(-1*$way)][$y+(1*$way)] = $board[$coords[0]][$coords[1]]; // position 2,2 becomes 3,1
I plan to have a function to update the tile movements in the screen so the piece moves as the it highlights the piece as is moving to the next square
this is using serialize into file to hold start positions, movements, kings and queens positions
I'm going to assume that $coords is a $_POST variable like a suggested on the first part of this question. If that's the case, the first part of your code is correct:
$board[$coords1[0]-1][$coords1[1]+1] = $board[$coords[0]][$coords[1]];
$board[$coords[0]][$coords[1]] = 0;
This moves a piece diagonally one step up-right in the board.
The second part on the other hand skips the actual 'eating' action. Unless, the location specified by the user is the one where the enemy piece is. In which case you code would work.
As for the bound-checking you do, you're not being bullet-proof since adding 2 in the eating move, while a piece is next to a border would result in your code trying to place the piece out of the board. So you could check bounds, depending on the move, so if the move is a standard diagonal one, you should check that the ending position is within the limits, not the starting one since you are assuming that piece is in a correct position before.
I think you have a few issues
$board[$coords1[0]-1][$coords1[1]+1] = $board[$coords[0]][$coords[1]];
if $coords[1] == 7 (which appears to be allowed) then $coords[1]+1 == 8 which is out of bounds. Let alone the coords +/- 2 we see later.
You probably don't want that 'bs'/'rs' in your storage, all of that can be inferred.
$getSquareColor = function($x,$y){return ($x+$y)/2 == 1 ? 'red' : 'black';} //or better yet, const or enum
function getSquareColor($x, $y) //alternatively
{
if ( ($x+$y) % 2 == 0) return 'black';
else return 'red';
}
ps - if you drop those dollar signs the function is just as good in javascript
I have a 1.2GB file that contains a one line string.
What I need is to search the entire file to find the position of an another string (currently I have a list of strings to search).
The way what I'm doing it now is opening the big file and move a pointer throught 4Kb blocks, then moving the pointer X positions back in the file and get 4Kb more.
My problem is that a bigger string to search, a bigger time he take to got it.
Can you give me some ideas to optimize the script to get better search times?
this is my implementation:
function busca($inici){
$limit = 4096;
$big_one = fopen('big_one.txt','r');
$options = fopen('options.txt','r');
while(!feof($options)){
$search = trim(fgets($options));
$retro = strlen($search);//maybe setting this position absolute? (like 12 or 15)
$punter = 0;
while(!feof($big_one)){
$ara = fgets($big_one,$limit);
$pos = strpos($ara,$search);
$ok_pos = $pos + $punter;
if($pos !== false){
echo "$pos - $punter - $search : $ok_pos <br>";
break;
}
$punter += $limit - $retro;
fseek($big_one,$punter);
}
fseek($big_one,0);
}
}
Thanks in advance!
Why don't use exec + grep -b?
exec('grep "new" ext-all-debug.js -b', $result);
// here we have looked for "new" substring entries in the extjs debug src file
var_dump($result);
sample result:
array(1142) {
[0]=> string(97) "3398: * insert new elements. Revisiting the example above, we could utilize templating this time:"
[1]=> string(54) "3910:var tpl = new Ext.DomHelper.createTemplate(html);"
...
}
Each item consists of string offset in bytes from the start of file and the line itself, separated with colon.
So after this you have to look inside the particular line and append the position to the line offset. I.e.:
[0]=> string(97) "3398: * insert new elements. Revisiting the example above, we could utilize templating this time:"
this means that "new" occurrence found at 3408th byte (3398 is the line position and 10 is the position of "new" inside this line)
$big_one = fopen('big_one.txt','r');
$options = fopen('options.txt','r');
while(!feof($options))
{
$option = trim(fgets($options));
$position = substr($big_one,$option);
if($position)
return $position; //exit loop
}
the size of the file is quite large though. you might want to consider storing the data in a database instead. or if you absolutely can't, then use the grep solution posted here.