Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Решение задачи №2
 
 автор: baston   (16.03.2010 в 20:35)   письмо автору
 
 

Не уверен, что еще принимаются решения по задачам PHP (http://www.softtime.ru/info/task.php?id_article=72). Но, так как я начинающий, то мне это интересно и полезно.
Единственно смущает, будет ли комментарий от Игоря Вячеславовича, все-таки времени-то многовато прошло...
Вот мой код:
<?php
##########################
####    Файл index.php    ####
##########################
//Функция вывода элементов массива в строки таблицы
  
function arraytotable($massive)
  {
    
//Создаем таблицу
    
echo "<table border=1 cellspacing=0 cellpadding=5 width=90%>";
    
//Проходим циклом по элементам массива
    
foreach($massive as $row)
    {
      
//Заносим в массив левую и правую части строки
      
$pieces explode("="$row);
      
//Создаем новую строку
      
echo "<tr>";
      
//Создаем левую ячейку таблицы и вставляем первый элемент массива
      
echo "<td>$pieces[0]</td>";
      
//Создаем правую ячейку таблицы и вставляем второй элемент массива
      
echo "<td>$pieces[1]</td>";
      
//Закрываем строку таблицы
      
echo "</tr>";
    }
    
// и закрываем таблицу
    
echo "</table><br><br>";
  }

//Определяем в переменную имя файла
$fn 'data.txt';
//Проверяем его существование
if(!file_exists($fn))
{
echo 
"В гостевой книге пока нет записей. Вы можете быть первым!";
}
else
{
  
//Читаем файл в массив
  
$arr file($fn);
  
//Вызываем функцию
  
arraytotable($arr);
}
//Форма ввода данных
?>

<form action="script2.php" method="post">
  Текстовое поле:<br>
  <input type="text" name="txt" size=50 value=""><br>
  Поле для комментария:<br>
  <textarea name="area" cols=39 rows=5></textarea><br><br>
  <input type="submit" name="btn" value="Отправить">
</form>

Второй скрипт:
<?php
##########################
###    Файл script2.php     ###
##########################
//Определяем в переменную имя файла
$fn 'data.txt';
//Заносим в переменные данные из полей
$txt $_POST['txt'];
$area $_POST['area'];
//Удаляем ненужные символы = в данных и
//преобразовываем специальные символы в HTML сущности
$text str_replace("=","",htmlspecialchars($txt));
$area str_replace("=","",htmlspecialchars($area));
//Образуем результирующую строку
$result "$txt=$area\r\n";
//Открываем файл записи в конец файла.
//Если не существует, то создается.
$fd = @fopen($fn"ab");
//Блокируем файл
flock($fdLOCK_EX);
//Записываем данные в файл
fwrite($fd$result);
//Закрываем файл
fclose($fd);
//Возвращаемся к таблице с данными и форме
header("Location:index.php");
?>

  Ответить  
 
 автор: cheops   (17.03.2010 в 00:54)   письмо автору
 
   для: baston   (16.03.2010 в 20:35)
 

1. Первое что бросается в глаза - это отсутствие обработки "магических кавычек", данные поступают по POST-каналу, и если режим магических кавычек включен (а часто так и бывает), то кавычки ' и " будут экранированы \' и \", т.е. данные будут искажены.
2. Немного неудобно то, что htmlspecialchars() используется перед записью в файл, а не после. Т.е. если нужно будет отредактировать информацию в исходном виде - потребуется устранять последствия работы htmlspecialchars() или редактировать прямо так с HTML-эквивалентами.
3. Если в текстовую область поместить переводы строки - скрипт работает не корректно.

Попробуете исправить с учетом замечаний ;-)?

  Ответить  
 
 автор: baston   (17.03.2010 в 14:35)   письмо автору
 
   для: cheops   (17.03.2010 в 00:54)
 

Для И.В. (cheops):
Исправил :)
1. Добавил в файл script2.php функцию проверки на активность магических кавычек.
2. Использую htmlspecialchars() непосредственно при выводе в таблицу.
3. Не уверен на 100%, но добавил trim() для переводов строк. Вроде работает (по-крайней мере, в результирующем файле data.txt нет пустых строк).

Для Trianon:
Сделал проще (на мой взгляд). Я просто в результирующий файл записываю данные в таком виде:
text1|=|text2
В этом случае, нет нужды и удалять знаки равенства, и соответственно разделяем подстроки уже по разделителю |=|

Вот итоговые скрипты:
<?php
##########################
### INDEX.PHP ###
##########################
//Функция вывода элементов массива в строки таблицы
  
function arraytotable($massive)
  {
    
//Создаем таблицу
    
echo "<table border=1 cellspacing=0 cellpadding=5 width=90%>";
    
//Проходим циклом по элементам массива
    
foreach($massive as $row)
    {
      
//Заносим в массив левую и правую части строки
      
$pieces explode("|=|"$row);
      
//Создаем новую строку
      
echo "<tr>";
      
//Создаем левую ячейку таблицы и вставляем первый элемент массива
      
echo "<td>".htmlspecialchars($pieces[0])."</td>";
      
//Создаем правую ячейку таблицы и вставляем второй элемент массива
      
echo "<td>".htmlspecialchars($pieces[1])."</td>";
      
//Закрываем строку таблицы
      
echo "</tr>";
    }
    
// и закрываем таблицу
    
echo "</table><br><br>";
  }
//Определяем в переменную имя файла
$fn 'data.txt';
//Проверяем его существование
if(!file_exists($fn))
{
echo 
"В гостевой книге пока нет записей. Вы можете быть первым!";
}
else
{
  
//Читаем файл в массив
  
$arr file($fn);
  
//Вызываем функцию
  
arraytotable($arr);
}
//Форма ввода данных
?>
<form action="script2.php" method="post">
  Текстовое поле:<br>
  <input type="text" name="txt" size=50 value=""><br>
  Поле для комментария:<br>
  <textarea name="area" cols=39 rows=5></textarea><br><br>
  <input type="submit" name="btn" value="Отправить">
</form>

<?php
##########################
###  SCRIPT2.PHP     ###
##########################
## Функция обработки "магических кавычек" (удаление слешей)
function delslashes($val)
{
  
//Получаем необработанные данные из поля без крайних пробелов
  
$result trim($_POST[$val]);
  
//Удаляем переводы строк
  
$result trim($result'\r\n');
  
//Если ф-я Magic Quotes активна, то удаляем слеши
  
if(get_magic_quotes_gpc()) $result stripslashes($result);
  return 
$result;
}
//Заносим в переменные данные из полей
$txt delslashes("txt");
$area delslashes("area");
//Образуем результирующую строку
$result "$txt|=|$area\n";
//Определяем в переменную имя файла
$fn 'data.txt';
//Открываем файл записи в конец файла.
//Если не существует, то создается.
$fd = @fopen($fn"at");
//Блокируем файл
flock($fdLOCK_EX);
//Записываем данные в файл
fwrite($fd$result);
//Закрываем файл
fclose($fd);
//Возвращаемся к таблице с данными и форме
header("Location:index.php");
?>

  Ответить  
 
 автор: Trianon   (17.03.2010 в 15:05)   письмо автору
 
   для: baston   (17.03.2010 в 14:35)
 

>3. Не уверен на 100%, но добавил trim() для переводов строк. Вроде работает (по-крайней мере, в результирующем файле data.txt нет пустых строк).

Так Вы вместе "из купели вместе с водой ребенка выплеснули".
Суть в том, что неплохо было бы сделать так, чтобы скрипт мог спокойно работать с многострочным текстом, без искажения данных и нарушений логики.


>Для Trianon:
>Сделал проще (на мой взгляд). Я просто в результирующий файл записываю данные в таком виде:
>text1|=|text2
>В этом случае, нет нужды и удалять знаки равенства, и соответственно разделяем подстроки уже по разделителю |=|

Нет. Это не решение.
Теперь внутрь текста невозможно записать разделитель |=|
Принципиально ничего не изменилось.

Даже если Вы придумаете суперпупермегасложный разделитель, я отвечу, что не получится его применить в тексте.
Подсказка. Разделитель может быть простым. А решение - на файловом уровне совместимым с тем, которое требуется исходными условиями.

  Ответить  
 
 автор: baston   (17.03.2010 в 17:18)   письмо автору
 
   для: Trianon   (17.03.2010 в 15:05)
 

>>3. Не уверен на 100%, но добавил trim() для переводов строк. Вроде работает (по-крайней мере, в результирующем файле data.txt нет пустых строк).
>
>Так Вы вместе "из купели вместе с водой ребенка выплеснули".
>Суть в том, что неплохо было бы сделать так, чтобы скрипт мог спокойно работать с многострочным текстом, без искажения данных и нарушений логики.

Тут загвоздка в том, что браузер не видит таких переводов строк как \n \r, а теги br заменяются функцией htmlspecialchars()...

  Ответить  
 
 автор: Trianon   (17.03.2010 в 17:49)   письмо автору
 
   для: baston   (17.03.2010 в 17:18)
 

>Тут загвоздка в том, что браузер не видит таких переводов строк как \n \r, а теги br заменяются функцией htmlspecialchars()...

Значит нужно написать так, чтобы не заменялись.

  Ответить  
 
 автор: baston   (17.03.2010 в 17:55)   письмо автору
 
   для: baston   (17.03.2010 в 17:18)
 

Дмитрий! По первому вашему замечанию о многострочных данных решил так:
В скрипте script2.php в функции удаления слешей я добавил выражение по замене переводов строк на тег br:
function delslashes($val)
    {
      //Получаем необработанные данные из поля без крайних пробелов
      $result = trim($_POST[$val]);
      //Если в строке есть переводы строк, то заменяем их на теги <br>
      $result = str_replace("\r\n", "<br>", $result);
      //Если ф-я Magic Quotes активна, то удаляем слеши
      if(get_magic_quotes_gpc()) $result = stripslashes($result);
      return $result;
    }

В скрипте index.php я тоже изменил логику и сделал так (создал второй массив из строк второй части и потом добавляю тег br для вывода в браузер в таблицу):
foreach($massive as $row)
    {
      //Заносим в массив левую и правую части строки
      $pieces = explode("=", $row);
      $second = explode("<br>", $pieces[1]);
      //Создаем новую строку
      echo "<tr>";
      //Создаем левую ячейку таблицы и вставляем первый элемент массива
      echo "<td>".htmlspecialchars($pieces[0])."</td>";
      echo "<td>";
      for($i=0; $i<count($second); $i++)
      {
        //Создаем правую ячейку таблицы и вставляем второй элемент массива
          echo htmlspecialchars($second[$i])."<br>";
      }
      echo "</td>";
      //Закрываем строку таблицы
      echo "</tr>";
    }

Таким образом мы решили проблему многострочных строк :)
Теперь буду думать над знаком =.

  Ответить  
 
 автор: Trianon   (17.03.2010 в 18:31)   письмо автору
 
   для: baston   (17.03.2010 в 17:55)
 

теперь Вам текстовую строку <br> не ввести.

  Ответить  
 
 автор: baston   (18.03.2010 в 13:41)   письмо автору
 
   для: Trianon   (17.03.2010 в 18:31)
 

Дмитрий, вы писали:
>...А решение - на файловом уровне совместимым с тем, которое требуется исходными условиями.
Не могли бы вы дать больше подсказок? Перебрал практически все функции по работе с файлами и строками - ничего не подходит.
Может не там ищу?
Но я не использую функции, которые удаляют html-теги, типа fgetss() или strip_tags(), так как это противоречило бы правилу "пользователь может ввести что-угодно, а мы выводим только допустимое".
Спасибо.

  Ответить  
 
 автор: Trianon   (18.03.2010 в 13:54)   письмо автору
 
   для: baston   (18.03.2010 в 13:41)
 

Как нетрудно предположить, исходные условия не предполагают применение знака равенства во вводимых полях. И хранение многострочных данных тоже не предполагают.
Грубо говоря, в файле на каждой строке может (и должен) быть один и только один символ = . Разделяющий поля в записи.

Остается лишь придумать такой расширенный синтаксис строк, в котором два и более символа = описывают все оставшиеся случаи.

  Ответить  
 
 автор: baston   (18.03.2010 в 17:27)   письмо автору
 
   для: Trianon   (18.03.2010 в 13:54)
 

Придумал так.
1) При записи данных из полей ввода в файл:
- заменяю знаки = на их HTML сущность (&#61;).
2) При выводе в браузер из файла:
- ищу регуляркой нужные мне части из строки;
- декодирую каждую часть (до знака = и после), чтобы получить из сущности натуральный знак =;
- вставляю части в ячейки таблицы (уже вновь кодированные, но знак = не кодируется).
В итоге думаю, что эта часть задачи решена :)
По многострокам пока не соображу как можно сделать. Думаю, что аналогично, но боюсь запутаться.
Вот результат (прошу покритиковать мой способ). Да, если мы вводим в поля html-cущность знака =, то она преобразуется в знак =.
##########################
###    SCRIPT2.PHP
##########################
//Функция обработки "магических кавычек" (удаление слешей)
    function delslashes($val)
    {
      //Получаем необработанные данные из поля без крайних пробелов
      $result = trim($_POST[$val]);
      //Если в строке есть переводы строк, то заменяем их на теги <br>
      $result = str_replace("\r\n", "<br>", $result);
      //Если в строке встречаются знаки =, то заменяем их HTML-сущностью (&#61;)
      $result = str_replace("=", "&#61;", $result);
      //Если ф-я Magic Quotes активна, то удаляем слеши
      if(get_magic_quotes_gpc()) $result = stripslashes($result);
      return $result;
    }
//Заносим в переменные данные из полей
$txt = delslashes("txt");
$area = delslashes("area");
//Образуем результирующую строку
$result = "$txt=$area\r\n";
//Определяем в переменную имя файла
$fn = 'data.txt';
//Открываем файл записи в конец файла.
//Если не существует, то создается.
$fd = @fopen($fn, "at");
//Блокируем файл
flock($fd, LOCK_EX);
//Записываем данные в файл
fwrite($fd, $result);
//Закрываем файл
fclose($fd);
//Возвращаемся к таблице с данными и форме
header("Location:index.php");

##########################
### INDEX.PHP
##########################
//Функция вывода элементов массива в строки таблицы
function arraytotable($massive)
{
  //Создаем таблицу
  echo "<table border=1 cellspacing=0 cellpadding=5 width=90%>";
  //Проходим циклом по элементам массива
  foreach($massive as $row)
  {
    //Шаблон поиска частей строки
    $pattern = "#((^[^=]+)={1}(.+))#i";
    //Заносим в переменную результат поисков
    $res = preg_match($pattern, $row, $arr);
    //Получаем для вывода в браузер строки с декодированным знаком =
    $left = html_entity_decode($arr[2]);
    $right = html_entity_decode($arr[3]);
    //Создаем новую строку
    echo "<tr>";
    //Создаем левую ячейку таблицы и вставляем первый элемент массива
    echo "<td>".htmlspecialchars($left)."</td>";
        //Создаем правую ячейку таблицы и вставляем второй элемент массива
    echo "<td>".htmlspecialchars($right)."</td>";
    //Закрываем строку таблицы
    echo "</tr>";
  }
  // и закрываем таблицу
  echo "</table><br><br>";
}
//Определяем в переменную имя файла
$fn = 'data.txt';
//Проверяем его существование
if(!file_exists($fn))
{
echo "В гостевой книге пока нет записей. Вы можете быть первым!";
}
else
{
  //Читаем файл в массив
  $arr = file($fn);
  //Вызываем функцию
   arraytotable($arr);
}
//Форма ввода данных
?>
<form action="script2.php" method="post">
  Текстовое поле:<br>
  <input type="text" name="txt" size=50 value=""><br>
  Поле для комментария:<br>
  <textarea name="area" cols=39 rows=5></textarea><br><br>
  <input type="submit" name="btn" value="Отправить">
</form>

  Ответить  
 
 автор: Trianon   (18.03.2010 в 22:26)   письмо автору
 
   для: baston   (18.03.2010 в 17:27)
 

Бесполезно.

  Ответить  
 
 автор: baston   (18.03.2010 в 23:44)   письмо автору
 
   для: Trianon   (18.03.2010 в 22:26)
 

Дмитрий, почему?
Знак = не теряется в этом случае.

  Ответить  
 
 автор: Trianon   (19.03.2010 в 02:03)   письмо автору
 
   для: baston   (18.03.2010 в 23:44)
 

ага.
зато теряется такая вот строка из пяти символов:
&#61;


и такая - из четырех:
<br>

  Ответить  
 
 автор: baston   (19.03.2010 в 07:27)   письмо автору
 
   для: Trianon   (19.03.2010 в 02:03)
 

Верно. Я об этом и указал в своем сообщении выше:
>Да, если мы вводим в поля html-cущность знака =, то она преобразуется в знак =.
Про переводы строк я еще не придумал как обойти.

Дмитрий, хорошо. А вы можете показать конкретный способ решения этой проблемы? Просто неделю бьюсь и видимо не в том направлении. Ну, нет у меня опыта...
Буду благодарен.

  Ответить  
 
 автор: Trianon   (19.03.2010 в 21:58)   письмо автору
 
   для: baston   (19.03.2010 в 07:27)
 

<?php


$esc_pattern 
"
    (?i:             # начало эскейпа
       ==            #  эскейп
       (             #   начало кода
         [0-9A-F]    #    Шестнадцатеричная цифра
                {2}  #     дважды
       )             #   конец кода
    )                # конец эскейпа
"
;

$field_pattern "
                     # начало строки
    (                #  начало поля
      (?:            #   начало повтора
       (
$esc_pattern)#     эскейп_код
       |             #    либо
       ([^=]*)       #     строка любых символов кроме =
      )              #   конец повтора
     *               #   произвольное число раз
    )                #  конец поля
"
;

$fld1="Cпасибо, =Вася=!";

$fld2="C =новым= годом!
 Всегда =Ваша=,
  крыша."
;

echo 
"<pre>";
echo 
"-0-\r\n";
echo 
"$fld1 \r\n";
echo 
"$fld2 \r\n";

$fld1enc str_replace(array('='chr(0), chr(0xD), chr(0xA)),
                       array(
'==3D','==00''==0D','==0A'),
                         
$fld1);
$fld2enc str_replace(array('='chr(0), chr(0xD), chr(0xA)),
                       array(
'==3D','==00''==0D','==0A'),
                         
$fld2);
echo 
"-1-\r\n";
echo 
"$fld1enc \r\n";
echo 
"$fld2enc \r\n";

$text "$fld1enc=$fld2enc";
echo 
"-2-\r\n";
echo 
"$text \r\n";


$res preg_match("/^$field_pattern/x"$text$matches);
$len1 $res strlen($matches[0]) : 0;
$fld1enc $matches[0];
if(@
$text[$len1] != '=') return '-1 -- no field separator';
if(@
$text[$len1+1] == '=') return '-2 -- internal parse error';
$fld2enc substr($text$len1+1);
echo 
"-3-\r\n";
echo 
"$fld1enc \r\n";
echo 
"$fld2enc \r\n";
$res preg_match("/^$field_pattern/x"$fld2enc$matches);
$len2 $res strlen($matches[0]) : 0;
if(
$len2 != strlen($fld2enc)) return '-3 -- internal parse error';
$fld1 preg_replace("/$esc_pattern/xe"'chr(hexdec("\\1"))'$fld1enc);
$fld2 preg_replace("/$esc_pattern/xe"'chr(hexdec("\\1"))'$fld2enc);
echo 
"-4-\r\n";
echo 
"$fld1 \r\n";
echo 
"$fld2 \r\n";
echo 
"---\r\n";

?>

  Ответить  
 
 автор: baston   (19.03.2010 в 22:42)   письмо автору
 
   для: Trianon   (19.03.2010 в 21:58)
 

Да-а-а...
Дмитрий, до такого кода я ни в жизнь бы не додумался на том этапе развития в PHP, на котором я сейчас нахожусь.
Но, спасибо за урок!
Я вот попроще сделал (без учета многострочного ввода). Зато не надо думать о "паразитных" символах. Вытаскиваем нужные части строк и всех делов.
<?php
##########################
### INDEX.PHP
##########################
//Функция вывода элементов массива в строки таблицы
function arraytotable($massive)
{
  
//Создаем таблицу
  
echo "<table border=1 cellspacing=0 cellpadding=5 width=90%>";
  
//Проходим циклом по элементам массива
  
foreach($massive as $row)
  {
    
//Находим позицию последней открывающей скобки
    
$start mb_strrpos($row"(""UTF-8");
    
//Находим позицию последней закрывающей скобки
    
$end mb_strpos($row")"$start+1"UTF-8");
    
//Находим позицию разделяющего цифры двоеточия
    
$dotdot mb_strpos($row":"$start+1"UTF-8");    //позиция до двоеточия
    //Вытаскиваем цифры после скобки и до двоеточия
    
$lnum mb_substr($row$start+1$dotdot $start-1"UTF-8");
    
//Вытаскиваем цифры после двоеточия и до закрывающей скобки
    
$rnum mb_substr($row$dotdot+1$end $dotdot-1"UTF-8");
    
//Вытаскиваем текст левой части строки
    
$lstr mb_substr($row0$lnum"UTF-8");
    
//Вытаскиваем текст правой части строки
    
$rstr mb_substr($row$lnum+1$start $lnum-1"UTF-8");
    
//Создаем новую строку
    
echo "<tr>";
    
//Создаем левую ячейку таблицы и вставляем первый элемент массива
    
echo "<td>".htmlspecialchars($lstr)."</td>";
    
//Создаем правую ячейку таблицы и вставляем второй элемент массива
    
echo "<td>".htmlspecialchars($rstr)."</td>";
    
//Закрываем строку таблицы
    
echo "</tr>";
  }
  
// и закрываем таблицу
  
echo "</table><br><br>";
}
//Определяем в переменную имя файла
$fn 'data.txt';
//Проверяем его существование
if(!file_exists($fn))
{
echo 
"В гостевой книге пока нет записей. Вы можете быть первым!";
}
else
{
  
//Читаем файл в массив
  
$arr file($fn);
  
//Вызываем функцию
   
arraytotable($arr);
}
//Форма ввода данных
?>
<form action="script2.php" method="post">
  Текстовое поле:<br>
  <input type="text" name="txt" size=50 value=""><br>
  Поле для комментария:<br>
  <textarea name="area" cols=39 rows=5></textarea><br><br>
  <input type="submit" name="btn" value="Отправить">
</form>

<?php
##########################
###    SCRIPT2.PHP
##########################
//Функция обработки "магических кавычек" (удаление слешей)
function delslashes($val)
{
  
//Получаем необработанные данные из поля без крайних пробелов
  
$result trim($_POST[$val]);
  
//Если в строке есть переводы строк, то заменяем их на теги <br>
  //$result = str_replace("\r\n", "<br>", $result);
  //Если ф-я Magic Quotes активна, то удаляем слеши
  
if(get_magic_quotes_gpc()) $result stripslashes($result);
  return 
$result;
}
//Заносим в переменные данные из полей
$txt delslashes("txt");
//Вычисляем длину строки текстового поля
$ltxt mb_strlen($txt"UTF-8");
$area delslashes("area");
//Вычисляем длину строки комментария
$larea mb_strlen($area"UTF-8");
//Образуем результирующую строку и в конец
//строки записываем данные по длинам строк в
//формате (длина_строки:длина_комментария)
$result "$txt=$area($ltxt:$larea)\n";
//Определяем в переменную имя файла
$fn 'data.txt';
//Открываем файл записи в конец файла.
//Если не существует, то создается.
$fd = @fopen($fn"at");
//Блокируем файл
flock($fdLOCK_EX);
//Записываем данные в файл
fwrite($fd$result);
//Закрываем файл
fclose($fd);
//Возвращаемся к таблице с данными и форме
header("Location:index.php");
?>

  Ответить  
 
 автор: Trianon   (20.03.2010 в 00:35)   письмо автору
 
   для: baston   (19.03.2010 в 22:42)
 

вот поэтому я и написал "бесполезно".
Какая разница, какой будет код?
Я предложил подумать над алгоритмом.
И подсказок дал вполне достаточно.

Ваш вариант с разметкой тоже допустим. Достоинство - отсутствие последовательного разбора массового потока данных. Индексную часть, конечно, разобрать придется.
Я не понял, правда, зачем нужно было индекс запинывать в хвост строки, а на в начало.
Не потребовался бы поиск скобки.
Кстати проблему многострочных данных таким образом тоже можно решить - Вы просто не стали думать..

Главный же недостаток - отсутствие портабельности на уровне формата файла с Хеопсовой задачей.

  Ответить  
 
 автор: baston   (20.03.2010 в 08:31)   письмо автору
 
   для: Trianon   (20.03.2010 в 00:35)
 

"Я не волшебник. Я только учусь" (C).
При всем к вам уважении и с благодарностью, подсказки меня только запутывали больше. Но здесь, я думаю, проблема не в ваших подсказках, а в моих пока небольших познаниях и слабой логике. Все-таки я не программист...
Решил в конец записывать индекс потому что мыслю шаблонно, увы.
Про многостроки решил было пока не думать, следовало решить основную задачу - ввод любых данных от пользователя не разбирая, а сохраняя. Теперь буду думать и над этим.
Вы написали:
>Главный же недостаток - отсутствие портабельности на уровне формата файла с Хеопсовой >задачей.
Вот даже такое простое предложение я не могу понять. Как говориться, слова понимаю, но связать в единую логику для себя никак...
Мне бы попроще разьяснить, что вы имели в виду? Переносимость для других операционок?
Спасибо.

  Ответить  
 
 автор: Trianon   (20.03.2010 в 11:00)   письмо автору
 
   для: baston   (20.03.2010 в 08:31)
 

>Главный же недостаток - отсутствие портабельности на уровне формата файла с Хеопсовой >задачей.
>Мне бы попроще разьяснить, что вы имели в виду?

Я имею в виду то, что файл вида
Москва=Россия
Киев=Украина
Минск=Беларусь

, подготовленный программами согласно исходным условиям задачи N2,
не будет корректно отображен в виде таблицы Вашим скриптом, ожидающим индекс в конце каждой строки.

  Ответить  
 
 автор: Drago   (20.03.2010 в 02:10)   письмо автору
 
   для: Trianon   (19.03.2010 в 21:58)
 

Trianon, а разве нельзя проще?
Перед сохранением в файл заменяем символы & и = на их html эквиваленты, переводы строк экранируем. При выводе, заменяем html эквиваленты &#61; и &amp; на соответствующие символы, переводы строк разэкранируем и заменяем на <br>.

Для примера, сделал в одном файле, отчего получилось несколько громоздко, за то удобнее проверить.

<?php

function escape ($str) {
        return 
str_replace(
            array(
'&''='"\n""\r"),
            array(
'&amp;''&#61;'"\\n""\\r"),
            
$str
        
);
}
function 
unescape ($str) {
        return 
nl2br(htmlspecialchars(
            
str_replace(
                array(
'&#61;''&amp;'"\\n""\\r"),
                array(
'=''&'"\n""\r"),
                
$str
            
)
        ));
}

$filename 'data.txt';
$error '';

if (
$_POST) {
    if (
get_magic_quotes_gpc()) {
        
$_POST['fld1'] = stripslashes($_POST['fld1']);
        
$_POST['fld2'] = stripslashes($_POST['fld2']);
    }

    if (
$_POST['fld1'] === '' or $_POST['fld2'] === '')
        
$error 'Нужно заполнить все поля.';
    else {
        
$fp fopen($filename'a');
        
fwrite($fpescape($_POST['fld1']).'='.
                    
escape($_POST['fld2'])."\n"
        
);
        
fclose($fp);
        
header('Location: '.$_SERVER['PHP_SELF']);
        exit;
    }
}

if (
file_exists($filename) and filesize($filename)) {
    
$messages file($filenameFILE_IGNORE_NEW_LINES);
    
$rows '';
    
$count count($messages);
    for (
$i=0$i $count$i++) {
        
$rows .= '<tr><td>';
        
$rows .= implode(
            
'</td><td>',
            
array_map('unescape'explode('='$messages[$i]))
        );
        
$rows .= '</td></tr>';
    }
}
?>
<html>
<head>
    <title>Задача №2</title>
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
</head>
<body>
    <table border="1">
        <tr><td><b>fld1</b></td><td><b>fld2</b></td></tr>
        <?php
            
if (isset($rows))
                echo 
$rows;
            else
                echo 
'<tr><td colspan="2">Записей нет.</td></tr>';
        
?>
    </table><br>
    <?php echo $error '<b style="color: #800;">'.$error.'</b><br>' '' ?>
    <form action="" method="post">
        <b>fld1</b><br><input type="text" name="fld1"><br>
        <b>fld2</b><br><textarea name="fld2"></textarea><br><br>
        <input type="submit" value="Отправить">
</body>
</html>

  Ответить  
 
 автор: Trianon   (20.03.2010 в 11:04)   письмо автору
 
   для: Drago   (20.03.2010 в 02:10)
 

Можно, конечно.
Но совместимость с файлами исходных условий задачи будет утрачена.

  Ответить  
 
 автор: Drago   (20.03.2010 в 11:35)   письмо автору
 
   для: Trianon   (20.03.2010 в 11:04)
 

Не совсем понял почему вы так решили. В моем решении как и используется формат файла из исходных условий задачи.
text1=text2
text3=text4

При этом, text1, text2, text3, text4 могут содержать любые символы. В том числе знаки "=" и переводы строк.

  Ответить  
 
 автор: Trianon   (20.03.2010 в 12:58)   письмо автору
 
   для: Drago   (20.03.2010 в 11:35)
 

>Не совсем понял почему вы так решили. В моем решении как и используется формат файла из исходных условий задачи.
>text1=text2
>text3=text4
>При этом, text1, text2, text3, text4 могут содержать любые символы. В том числе знаки "=" и переводы строк.

Всю обедню портит вот этот массив: array('&amp;', '&#61;', "\\n", "\\r"),
достаточно написать
&amp;=так кодируется амперсанд
&#61;=так кодируется знак равенства
\r=так кодируется CR
\n=так кодируется LF

и несовместимость проявится.

  Ответить  
 
 автор: Drago   (20.03.2010 в 13:42)   письмо автору
 
   для: Trianon   (20.03.2010 в 12:58)
 

Спасибо, теперь понял, что вы имели ввиду.
Также, увидел что экранирование одних "\n" и "\r" - не выход и лучше экранировать всю строку функцией addslashes().

Однако, разве ваш вариант не хранит строки в обработанном виде?
То есть, на сколько я понял, в файле, у вас, получается должна лежать запись вида:
Cпасибо, ==3DВася==3D!=C ==3Dновым==3D годом!==0D==0A Всегда  =3DВаша==3D,==0D==0A  крыша.

Тогда, если файл будет следующего содержания:
==3D=так кодируется знак равненства
==0D==0A =а так символы перевода строки

Что выведет ваш скрипт?

  Ответить  
 
 автор: Trianon   (20.03.2010 в 13:47)   письмо автору
 
   для: Drago   (20.03.2010 в 13:42)
 

Исходный формат предполагал отсутствие значимых символов '=' и переводов строк в рабочем файле.

PS. Вы можете упрекнуть меня в том, что, строго говоря, отсутствие знаков равенства предполагалось лишь в левой части текста.
Ну так не всё ж мне решать задачки. Я оставляю пространство и для чужих решений. :)

Строгое решение задачи в общем случае невозможно.
Возможно лишь приближение к нему - через жертву некоторого множества исключений, которое новым скриптом будет отображаться не так, как старым.
Этот факт "невозможность строгого решения" - следствие непродуманности структуры данных на этапе проектирования.

PPS. Впрочем, нет.
Можно сделать практически строгое решение. С некоторой потерей совместимости, но уже в обратную сторону.
Оно, правда, будет не самым быстрым. И настолько запутанным, что в реальной жизни овчинка перестанет стоит выделки абсолютно, но тем не менее.

  Ответить  
 
 автор: Drago   (20.03.2010 в 15:52)   письмо автору
 
   для: Trianon   (20.03.2010 в 13:47)
 

> Вы можете упрекнуть меня в том, что, строго говоря, отсутствие знаков равенства предполагалось лишь в левой части текста.

Хочу упрекнуть вас несколько в другом. :)

Если Исходный формат предполагал отсутствие значимых символов '=' и переводов строк в рабочем файле., то почему сделали такое замечание: Теряются знаки равенства в исходных тексте и комментарии.?

И второе, утверждая что предложенные решения не совместимы с файлами исходных условий задачи, вы предложили точно такой же вариант решения, не совместимый с файлами исходных условий задачи.

В остальном согласен. :)

  Ответить  
 
 автор: Trianon   (20.03.2010 в 17:11)   письмо автору
 
   для: Drago   (20.03.2010 в 15:52)
 

почему же он несовместим?

Строки, порожденные скриптами, построенными по исходным условиям, и не содержащие = и переносов строк в данных, обрабатываются моим вариантом переносимым образом.

>И второе, утверждая что предложенные решения не совместимы с файлами исходных условий задачи, вы предложили точно такой же вариант решения, не совместимый с файлами исходных условий задачи.

Не надо. Я говорил о несовместимости про решения, которые затрагивали символы ни коим образом не вовлеченные в исходный формат хранения.

  Ответить  
 
 автор: baston   (24.03.2010 в 13:21)   письмо автору
 
   для: Trianon   (19.03.2010 в 21:58)
 

Дмитрий, а вы не могли пояснить один момент из регулярок, которые используете.
(?i: 

и
(?:

Что это?
Знак вопроса является модификатором для поиска необязательно текста.
А что он у вас в вашем варианте означает, не могу понять... Поясните пожалуйста.
По-крайней мере честно пытался найти ответ в регулярках, но увы...
Интересуют только указанные части вашей регулярки.
Спасибо.

  Ответить  
 
 автор: Trianon   (24.03.2010 в 21:15)   письмо автору
 
   для: baston   (24.03.2010 в 13:21)
 

Антон, Вы пытаетесь рассматривать отдельные символы вне контекста, в котором они применены.
Отсюда и неясности.

Знак вопроса является модивикатором необязательности только после квантификатора.
А в этом контексте это часть синтакстса незахватывающей маски - маски, которая не порождает элемент выходного массива.
В PCRE в этот синтаксис можно встраивать модификаторы шаблона для подмаски. В частности i поставлен затем, чтобы сделать отлов шестнадцатеричных вставок регистронезависимым.

  Ответить  
 
 автор: baston   (25.03.2010 в 08:14)   письмо автору
 
   для: Trianon   (24.03.2010 в 21:15)
 

Спасибо.
Я изучал брошюру "Регулярные выражения" (не Фридла) и там были описаны варианты некоторых незахватывающих масок. Что-то типа: ?< (поиск назад...).
А об этом варианте (?:) я не знал. Теперь буду знать. И нашел допинфу об этом.

  Ответить  
 
 автор: Trianon   (25.03.2010 в 10:05)   письмо автору
 
   для: baston   (25.03.2010 в 08:14)
 

Да уж, труд Фридла даже по сильной задумчивости брошюрой не назовешь.
Тем не менее читается он достаточно легко, особенно если не спешить.
А эффект дает весьма ощутимый.

Я не так давно страдал стойкой идиосинкразией к регулярным выражениям.
Вылечился только благодаря Фридлу. И Хеопсу, который мне его посоветовал.

  Ответить  
 
 автор: baston   (25.03.2010 в 13:04)   письмо автору
 
   для: Trianon   (25.03.2010 в 10:05)
 

Дмитрий, со зряплаты думаю купить. Дороговато, даже для меня, но что делать...
Могу читать только бумажные книги.
Брошюра была от Бена Форта из серии "10 минут на урок". Легкая и простая для начала изучения. Теперь вижу, что ее мне мало было.

  Ответить  
 
 автор: Trianon   (25.03.2010 в 14:28)   письмо автору
 
   для: baston   (25.03.2010 в 13:04)
 

Книга Дж.Фридла доступна для скачивания с портала.
Я в свое время скачал и распечатал.

  Ответить  
 
 автор: oliss   (25.03.2010 в 10:14)   письмо автору
 
   для: baston   (25.03.2010 в 08:14)
 

Введите в строку формы
&nbsp; 
как отреагирует обработчик ?

  Ответить  
 
 автор: Trianon   (25.03.2010 в 10:39)   письмо автору
 
   для: oliss   (25.03.2010 в 10:14)
 

А что там за баг?

По листингу (19.03.2010 в 22:42) подвоха не нашел.

Может, правда, невнимательно искал...

  Ответить  
 
 автор: baston   (25.03.2010 в 16:17)   письмо автору
 
   для: oliss   (25.03.2010 в 10:14)
 

Да, ошибка вывалится и некорректность в таблице.
Согласен, что код нехорош с точки зрения работоспособности в любых ситуациях. Сам недоволен.
Я учусь лишь только. Спасибо за выявленную ошибку. Изобретать велосипед не буду, а возьму на вооружение ваши наработки и при необходимости буду решать.

  Ответить  
 
 автор: oliss   (25.03.2010 в 17:02)   письмо автору
 
   для: baston   (25.03.2010 в 16:17)
 

Не дам решения ; )
Решите сами ,как получится,налейте себе ( ? ) грамм коньяка ; ) ) )

  Ответить  
 
 автор: baston   (25.03.2010 в 17:47)   письмо автору
 
   для: oliss   (25.03.2010 в 17:02)
 

Ваши наработки, опубликованные выше. :)
Только не удаляйте, пользуясь своим служебным положением (если такое в ваших силах).

  Ответить  
 
 автор: skykub   (21.04.2010 в 11:22)   письмо автору
 
   для: Trianon   (17.03.2010 в 15:05)
 

>Нет. Это не решение.
>Теперь внутрь текста невозможно записать разделитель |=|
>Принципиально ничего не изменилось.
Я бы предложил принудительно менять введенный пользователем = на ==
А в качестве разделителя по прежнему использовать |=|. Таким образом |=| будет разделителем, а введенный пользователем |=| превратится в |==| (а введенный пользоватиелем |==| превратится в |====| ;)
А перевод строки можно подменять, например, на #=#. Алгоритм тот же

  Ответить  
 
 автор: Trianon   (21.04.2010 в 11:56)   письмо автору
 
   для: skykub   (21.04.2010 в 11:22)
 

как отличить перевод строки от хвостового и начального # ?

  Ответить  
 
 автор: Trianon   (17.03.2010 в 00:59)   письмо автору
 
   для: baston   (16.03.2010 в 20:35)
 

И еще одно замечание.
Теряются знаки равенства в исходных тексте и комментарии.
Попробуйте сделать так, чтоб не терялись.
Это трудно, но возможно.

  Ответить  
 
 автор: baston   (19.03.2010 в 15:35)   письмо автору
 
   для: Trianon   (17.03.2010 в 00:59)
 

Дмитрий, у меня родилась еще одна идея :) Вот же неугомонный!
А что, если нам делить строку не по разделителю, а по позиции?
Это значит, мы определяем длину строки в каждом поле (не будем принимать во внимание многострочность). Эти данные (например в таком виде - 12:16) мы заносим в конец каждой строки через определенный разделитель (собственно, это не важно).
Далее мы считываем эти цифры и соответственно делим строку: первая часть равна первым цифрам, вторая часть - вторым.
Таким образом, нам совершенно не важно что используется в качестве разделителя и мы ничего таким образом не теряем.
Как на ваш взгляд?

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования