C++. How use SQLite in Windows Forms

В свое время знакомство с движком SQLite ограничилось разработками консольных приложений. Но вот настало время и более интересному использованию: интеграция в проекты сопряженных с созданием UI с помощью Windows Forms. Как и ранее я буду работать со средой разработки Microsoft Visual C++ 2008 Express Edition.
В отличии от консольных приложений все попытки связать SQLite с такого рода проектами были безуспешными. Может конечно у Вас получится, буду очень благодарен за письмо в мой адрес с Вашим рецептом. Приготовить по рецепту с официального сайта (The SQLite Amalgamation) также не удалось.

Из логов компилятора:
  • Command line error D8045 : cannot compile C file '.\sqlite3.c' with the /clr option
  • error LNK2019: unresolved external symbol _sqlite3_exec referenced in function _main
  • error LNK2019: unresolved external symbol _sqlite3_open referenced in function _main
Вопрос - почему? Причем этот вопрос судя по результатам поиска в "инете" не единичный. Как выяснилось чуть погодя проблема была связана с тем, что по сути своей Windows Forms является частью Microsoft .NET Framework. Внутри которой Windows Forms реализуется в рамках пространства имён System.Windows.Forms. В связи с этими нюансами и просходили всякие неприятности на моей кухне. И под конец на глаза попалась книжечка Using SQLite. Jay A. Kreibich, где сказано:


Building


There are a number of different ways to build SQLite, depending on what you’re trying


to build and where you would like it installed. If you are trying to integrate the SQLite

core into a host application, the easiest way to do that is to simply copy


sqlite3.c and


sqlite3.h
 

into your application’s source directory. If you’re using an IDE, the sqlite3.c


file can simply be added to your application’s project file and configured with the proper

search paths and build directives. If you want to build a custom version of the SQLite

library or


sqlite3 utility, it is also easy to do that by hand.


All of the SQLite source is written in C. It cannot be compiled by a C++ compiler. If

you’re getting errors related to structure definitions, chances are you’re using a C++

compiler.


Вопрос был снят. Получается, что нужно адаптировать SQLite библиотеку под .NET Framework. Для этого на официальном сайте есть ссылка на так называемый ADO.NET adapter for SQLite - System.Data.SQLite. 

Среди этих ресурсов (например - здесь) можно встретить вот такой ролик, который демонстирует сие адаптер - так сказать - in action. 

 

P.S.: For a CLR/.NET/WinForms projects you should use System.Data.SQLite.
Всем удачи :)

 

C/C++. Обращение к глобальным и локальным переменным

Не буду многословен. Для прямого обращения к глобальной переменной можно воспользоваться оператором расширения области видимости переменной variable:

::variable;

Соотвественно, для локальной переменной - по адресу.

some_function(&variable);

Ниже приведен примерчик для нагядности слов :)

#include <iostream>
using namespace std;
// Глобальная инициализация
// Глобальная переменная
int n = 100;
void glob() {
 ::n++;
}
void loc(int *n) {
 (*n)++;
}
int main() {
 // Локальная инициализация
 char temp;
 // Локальная переменная
 int n = 16;

 // ...до изменения переменных
 cout << "Global var before: n = " << ::n << "\n";
 cout << "Local var before: n = " << n << "\n";

 // Обращаемся к глобальной переменной и меняем ее
 glob();
 // Обращаемся к локальной переменной и также меняем ее
 loc(&n);
 // ...после изменения переменных
 cout << "Global var after: n = " << ::n << "\n";
 cout << "Local var after: n = " << n << "\n";
 // задержка...
 cin >> temp;
}

В итоге имеем:
 
Ура, все работает.

C++/CLI. Write to buffer (change cout on char buffer) and get string data from char buffer

Работая над проектом возникла необходимость в перехвате (громко сказано) стандартного вывода ( printf() ) для анализа того, с чем же приходилось работать. Далеко не копая, воспользовался "C"-шной функцией - sprintf(). Здесь небольшой faq. Данная функция на выходе все кладет в буфер. Приведу примерчик:

#include <stdio.h>

int main( void )
{
   char  buffer[200];
   int   j;
   


   /* Format and print various data: */
   j  = sprintf( buffer,     "   First string\n");
   j += sprintf( buffer + j, "   Second string\n");
   

   printf( "Output:\n%s\ncharacter count = %d\n", buffer, j );
}

 

 

 

 
В итоге имеем:

Output:

First string

Second string

character count = 25

 

 

 

 
 То, что нужно. Далее снова появилась мини-задачка: буфер - он и в Африке буфер, мне нужны были содержащиеся в нем данные, в частности - все "пойманные" строки. Их нужно было извлечь. Так как проект разрабатывался с помощью Microsoft Visual C++ 9.0 Express Edition (этого было достаточно :) ), то для сие нужды воспользовался методом gcnew String() (в следствие C++/CLI).
Он нужен для convert from 'char *' to 'System::String ^' . И снова пример:

// some code

char buffer[16];
String ^str;

sprintf(buffer, "Testing...\0");
   
str = gcnew String(buffer);
this->textBox1->AppendText(str);

// some code

И о чудо, я вновь "вижу" :)
Кстати, скоро новый год, еще  21 день. Заранее всех с наступающим :)

JavaScript. Несложное создание гистограмм

Учитывая, что сейчас многие пользуются блого-сервисами (blogger, tumblr, livejournal, etc.), могут возникнуть потребности в создании гистограмм. Мы же любим, когда данные можно "потрогать". Использование PHP в этом случае затруднено. Поэтому самый простой способ - создание гистограмм на JavaScripte с помощью CSS-стилей. Сразу отмечу, что сие способ описан в руководстве Флэнагана по JavaScript (со своими изменениями).
Основную работу будет выполнять js-файл - BarChart.js (см. листинг ниже). На входе он ожидает данные в виде массива, значения которого он аккуратно заклыдывает в гистограмму, которую выдает на выходе. Все очень просто. Ниже представлен один из примеров гистаграммы (Test chart).
Получаемые гистограммы легко инсталлируются в веб-странички. При этом можно входные данные сделать динамичными, так сказать - поставить на поток, что должно сделать динамичным и саму гистограмму. Ниже представлены листинги индексной html-странички и BarChart.js.
 
index.html
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<!-- Без объявления DOCTYPE в IE рисунок будет выглядеть неправильно -->
<html>
<head>
<script src="BarChart.js"></script> <!-- Подключить библиотеку -->
<script>
function drawChart() {
var data = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,50,50,50,5,5,5,5,5,5,5,5,50,6,6,7,7,7,60,8];
var chart = makeBarChart(data, 300, 300);
var container = document.getElementById("chartContainer");
container.appendChild(chart);
}
</script>
</head>
<body onload="drawChart( )">
<h2>Test chart</h2><!-- Заголовок гистограммы -->
<div id="chartContainer"><!-- Здесь рисуется гистограмма --></div>
<!-- Подпись под гистограммой -->
<i>Test chart</i>
</body>
</html>
 
BarChart.js
 
 /**
* BarChart.js:
* В этом файле содержится определение функции makeBarChart(), которая
* создает гистограмму для вывода содержимого массива data[].
* Общий размер гистограммы определяется необязательными аргументами
* width и height, которые учитывают пространство, необходимое для рамок
* гистограммы и внутренних отступов. Необязательный аргумент barcolor
* определяет цвет столбиков. Функция возвращает созданный ею элемент
* <div>, таким образом, вызывающий сценарий может манипулировать
* этим элементом, например, изменять величину отступов. Вызывающий
* сценарий должен вставить в документ полученный от функции элемент,
* чтобы сделать его видимым.
**/
function makeBarChart(data, width, height, barcolor) {
 // Предусмотреть значения по умолчанию для необязательных аргументов
 if (!width) width = 500;
 if (!height) height = 350;
 if (!barcolor) barcolor = "blue";
 // Аргументы width и height определяют общий размер гистограммы.
 // Чтобы получить размер создаваемого элемента, необходимо вычесть
 // из этих значений толщину рамок и величину отступов.
 width -= 24; // Вычесть 10px отступа и 2px толщины рамки слева и справа
 height -= 14; // Вычесть 10px отступа сверху и 2px толщины рамки сверху и снизу
 // Создать элемент для размещения гистограммы. Обратите внимание:
 // гистограмма позиционируется в относительных координатах, т. е.
 // в ней могут располагаться дочерние элементы с абсолютным
 // позиционированием, и отображаться при этом в нормальном потоке
 // вывода элементов документа.
 var chart = document.createElement("div");
 chart.style.position = "relative"; // Относительное позиционирование
 chart.style.width = width + "px"; // Ширина гистограммы
 chart.style.height = height + "px"; // Высота гистограммы
 chart.style.border = "solid black 1px"; // Определить рамку
 chart.style.paddingLeft = "10px"; // Добавить отступ слева
 chart.style.paddingRight = "10px"; // Справа
 chart.style.paddingTop = "10px"; // Сверху
 chart.style.paddingBottom = "0px"; // Но не снизу
 chart.style.backgroundColor = "white"; // Фон гистограммы - белый
 // Рассчитать ширину каждого столбика

 //var barwidth = Math.floor(width/data.length);
 var barwidth = 1;

 // Отыскать наибольшее число в массиве data[]. Обратите внимание
 // на грамотное использование функции Function.apply().
 var maxdata = Math.max.apply(this, data);
 // Масштабирующий множитель: scale*data[i] дает высоту столбика
 var scale = height/maxdata;
 // Обойти в цикле массив с данными и создать столбики для всех элементов
 for(var i = 0; i < data.length; i++) {
  var bar = document.createElement("div"); // Создать столбик
  var barheight = data[i] * scale; // Рассчитать высоту
  bar.style.position = "absolute"; // Уст. размер и положение
  bar.style.left = (barwidth*i+1+10)+"px"; // Добавить рамку столбика
  // и отступ
  bar.style.top = height-barheight+10+"px";// Добавить отступ
  // гистограммы
  bar.style.width = (barwidth-2) + "px"; // -2 - рамка столбика
  bar.style.height = (barheight-1) + "px"; // -1 - рамка сверху
  if (data[i] >= 50) bar.style.border = "solid red 1px"; // Стиль рамки столбика при значениях более 50
  if (data[i] < 50) bar.style.border = "solid blue 1px"; // Стиль рамки столбика при значениях менее 50
  bar.style.backgroundColor = barcolor; // Цвет столбика
  bar.style.fontSize = "0px"; // Учесть особенность IE
  chart.appendChild(bar); // Добавить столбик
  // в гистограмму
 }
 // В заключение вернуть элемент с гистограммой
 return chart;
}


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

 

C++. Simple displaying a Message Box

Простой способ создания диалоговоко окошка.

Для более подробного ознакомления - MessageBox function (Windows), Message Box Example (C++) (Windows) и Using Dialog Boxes (Window).

Немного кода (скачать):

#include <windows.h>

int DisplayResourceNAMessageBox() {
    int msgboxID = MessageBox(
        NULL,
        (LPCWSTR)L"Are you sitting down for an hour. Quickly raise your ass and go a walk",
        (LPCWSTR)L"Health timer",
        MB_OK
    );
    return msgboxID;
}

int main() {
 DisplayResourceNAMessageBox();
 return 0;
}

Ну и как всегда - удачи!

RSLogix5000. Создание массива. Объяснение на пальцах.

Как создать массив в RSLogix 5000? Очень просто. Есть два пути. По-крайней мере известных мне: - 1) Создать соответствующий тег в общем списке всех тегов контроллера (Control Tags); - 2) завести непосредственно в программе и далее правым кликом выбрать - `создать`. Ниже на пальцах на скриншотах показаны ориентиры в этом нелегком деле (выбран первый способ). Use it!
Step 1

Step 2

Step 3

Step 4

Step 5

Промышленное программирование. Введение. PLC/RSLogix5000/Archestra

Промышленное программирование.


Что же это такое? С чем приходиться больше сталкиваться: больше с промышленностью или с программированием? Лично у меня на это свой ответ: все зависит от технологии конкретного производства и, конечно, от степени внедренности на предприятии it-технологий. Также для меня стало очевидно, что круг вопросов программирования становится иным, весь фокус ложится именно на разработку промышленной логики (алгоритм) и визуализацию данной логики (по-сути - разработка интерфейса, позволяющего пользователю взаимодествовать с данной логикой в рамках технологических процессов). С этой точки зрения, промышленное программирование эквивалентно классическому: также - разработка алгоритма и также - разработка интерфейсной части. Но инструменты (язык) при этом свои, а ведь именно инструмент накладывает свои отпечатки на образ мышления. Думать по "С++" - ному - не то что думать по "PHP" - шному. Уверен, что Вы со мной согласитесь. Это же относится и к промышленному программированию.

Разработка помышленной логики (алгоритм).

Для кодинга в этом направлении используются свои языки. Все зависит от того, какой контроллер используется на предприятии. В моем случае - RSLogix, скорее это даже не язык, а среда разработки - RSLogix 5000 (разработка компании Rockwell Automation) для контроллеров производителя Allen Bredly (Allen Bredly Programmable Controller).




В  RSLogix реализованы три подхода в программировании:
1 - Ladder Diagram (по-сути - RAD (от англ. rapid application development — быстрая разработка приложений));
2 - Function Block (графичский подход, ориентировано больше на инженеров по микроэлектронике);
3 - Structered Text (можно сказать - Паскаль в действии);
В большей степени на практике использую именно первый подход - Ladder Diagram. Ниже представлен небольшой пример программы: каждые 0,1 секунду контроллер считывает внешний сигнал - Signal - и записывает полученные значения в одномерный массив test[i]. И так - 10 раз. Программа конечно несложная, скорее - наглядная.
Сам по себе, синтаксис паскалеподобный.
Типы данных представлены не только такими как - bool, int, dint (double int), string, real (аналог float), timer, но и специфичными - alarm, hmi_button, etc.
Максимальная допустимая к созданию размерность массива - `3`мерная (Array Dimensions). Если в Паскале мы имеем дело с процедурой, то здесь представлены `Add-on`ы (Control module), в которых есть как внешние (Parameters), так и внутренние (Local Tags) члены, есть возможность назначить модификаторы доступа как в классах ООП (required, visibility).
Раасматривать другие возможности здесь не буду, просто скажу, что все, что есть в обычном программировании - есть и здесь, плюс свои "штучки".

Вообще, когда начинаешь программировать, то приходиться работать с 1) со множеством сигналов от различных датчиков, устройств, моторов, клапанов, ну и прочего оборудования и 2) центром всего - контроллером. Когда мы сидим за ноутом или компом и программируем, то часто не берем в счет то, что мы также обращаемся к микрокотроллеру - центральному процессору. Для высокоуровневых языков с ООП подходом - нормально, но если взять ассемблер - без этого никак. Ниже представлен промышленный контроллер. Протокол общения - сетевой стандарт - tcp/ip.



 










Для контоллеров Siemens используется Simatic Step7. Подходы теже самые, но со своими нюансами.

Визуализация промышленной логики (графический интерфейс пользователя).

 "Общение" программы с конечным пользователем происходит на уровне интерефейса, в большей степени - графическом интерфейсе. В промышленном программировании - конечным пользователем является так называемый - оператор, причем так звучит должность человека на фабрике. Все серьезно :) Отсюда понятно, что интерефейс должен быть интуитивно понятным, а значит - графическим (70 % информации "бежит" по глазам). Поэтому приходиться решать и чисто дизайнерские задачи. Для наглядности приведен скриншотик рабочей зоны вот такого вот интефейса.

Вообще, система визуализации в промышленности именуется SCADA (аббр. от англ. supervisory control and data acquisition, диспетчерское управление и сбор данных). На самом деле, визуализация - это не просто создание интерфеса, это система сбора, управления и вывода данных. У нас на фабрике используется системная платформа - Archestra SCADA компании Invensys Systems. Также есть альтернативные системы, например - Elipse.

Стоит отметить и еще одну вещь. Теги (англ. tag — ярлык, этикетка, бирка; метить). После знакомства с промышленным программированием, понятие тега встречается практически на всех этапах. Для меня тег - не просто какая-то высокоуровневая метка, это носитель информационных единиц (true/false), также и носитель физических данных между контроллером и человеком. Своего рода теговый мостик (Tags bridge). Ниже представлены модели взаимодействия контроллера со SCADA с одной стороны, и с другой - датчиками, моторами, клапанами и другими устройствами.


Вот такое небольшое введение в промышленное программирование. Всем удачи :)









Javascript. Обмен данными между html - страничками. Альтернатива PHP скрипту

Конечно, громко сказано - альтернатива php скрипту. Имеется в виду отправка, обработка и получение ответа данных всевозможными методами (GET, POST). Как говорится, это классика. Но есть и вот такой вот альтернативный способ. Это взаимодействие html - файликов с помощью URL - адресов и JavaScript. Итак, подробности.

Передача данных в html-файл через URL-адрес.

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

html://webpage.html?parametr

Если этих параметров несколько, то между ними ставиться амперсанд (&).

html://webpage.html?parametr1&parametr2&parametr3

Помимо этого можно передавать при помощи форм. Для этого нужно воспользоваться методом GET.
Выглядеть URL-адрес в строке броузера будет следующим образом:

webpage.html?name1=value1&name2=value2&name3=value3

Получение переданных данных выполняется при помощи JavaScript.

Сначало мы присваиваем переменной все то, что находится после знака вопроса:

var p_url=location.search.substring(1);

Если передавался один параметр, то переменную p_url можно обрабатывать.
Если параметров было много, то их нужно разделить:

var parametr=p_url.split("&");

В итоге мы получаем массив parametr, который содержит полученные данные.
Если Вы переслали данные при помощи форм, то надо избавиться от знака равенства и присвоить каждой переменной свое значение:

var values= new Array();
for(i in parametr) {
    var j=parametr[i].split("=");
    values[j[0]]=unescape(j[1]);
}

Если строчка была вида:

webpage.html?name=Serg&city=Рязань&age=21

то получим массив:

values[name]="Serg";
values[city]="Рязань";
values[age]="21";

или можно так:

values[0]="Serg";
values[1]="Рязань";
values[2]="21";

Последнее время популярность набирает такой сервис как говорят - микроблогинга (по мне это больше, чем просто микроблогинг) - www.tumblr.com. Разработчики сервиса предоставили простой способ создания шаблона или по-другому - тем оформления с помощью обычной html
верстки с поддержкой javascript. И это отрадно. Для демонстрации отправки данных с одной html странички на другую я воспользовался именно этим сервисом.
Для этого я создал два блога, по-сути - две странички. Один из них - http://datasource.tumblr.com/ - будет служить формой для отправки данных, которые Вы туда поместите, ну и второй - http://tempbuffer.tumblr.com - принимающая Ваши данные страничка. Эта страничка парадирует php-скрипту, так сказать - пытается играть ее роль. Вот отсюда и было упомянуто об альтернативе. It`s working. Отрадно, все работает.
Ниже приведены сорсы, если нужно скачать, то кликай здесь - datasource  и tempbuffer. Всем гуд лака :)

C++. Пентамино. Решатель головоломки

Пентамино. Интересная конечно головоломка. На днях столкнулся с подобной задачкой. Есть 9 фигурок, каждая из которых представлена во входном файлике, причем своеобразной формы. Ниже парочка изображений этих фигурок






 Также после нахождения решений в виде таких же рисунков, нужно каждую из фигурок как-то отделить визуально, обычно в классическом пентамино для этого квадратные фигуры разукрашивают в разные цвета. Но в нашем случае фигурки необычные :) На выходе должен быть выходной файл с приведенными решениями пентамино! Как быть? С чего начать? Какую выбрать тактику? На первый взгляд непонятно с какого угла подойти к вопросу. Но для себя определил пару критериев, которых попробую придерживаться.

1. Необходимо фигуры перевести в цвет. Номер фигуры определяет цвет в виде числа(числовой цвет, числовая идентификация)


2. Каждая фигура определяется матрично (2ух мерно) размера m*n. Матричный каркас
 
3. У фигуры есть форма, а значит должна быть возможность симметричных поворотов определенных для  данной фигуры. Объектно-ориентированный подход
 
4. Метод сортировки - обход ладьей по часовой стрелке около первой фигуры (ближайшие ячейки, точки сопряжения) с переопределением матричного каркаса (подгонка)
5. Решением для двух фигур считается такая сортировка, при которой площадь сопряжения поверхностей двух фигур максимальна

Вперед и с песней :)

PHP5. Быстрая обработка csv файлов

Задача.
Есть основной файл и файлы шаблонов, причем все имеют расширение csv. Как можно быстро обработать файл на основе шаблонов?

В php5 есть специализированные функции str_getcsv(), fgetcsv() и fputcsv(), которые адаптированы для работы с такого рода файлами. Но можно обойтись и без этих функций. Во время такого рода манипуляций часто сталкивался с ошибками, которые необходимо учитывать - извлекаемые значения из массивов порой содержали неожиданные знаки табуляции, или строка состояла из символов в перемешку с NULL-символами... Поэтому обращение к шаблонам, разобранных на соответствующие массивы, сопровождались казусами, например - использование неопределенных массивов. Отсюда вывод - нужно использовать trim() как фильтр от таких "неожиданностей" и isset() - как подобие отлова исключительной ситуации с попыткой извлечения значения из массива по неопределенному индексу. В остальном все сработало неплохо :)

Пример (download).

<?php ## manipulation with csv-files (base of device tags)
/***********open source and target csv-files*****************************************
// 13010000.csv
$f = fopen("c:\\php\\scripts\\in\\devices.csv", "rb");
// pattern.csv
$pattern = fopen("c:\\php\\scripts\\templates\\pattern.csv", "rb");
// BTDevices_Adresses.csv
$btdevices = fopen("c:\\php\\scripts\\templates\\BTDevices_Adresses.csv", "rb");
// output.csv
$output = fopen("c:\\php\\scripts\\out\\output.csv", "wb");
//***********transfer data from file to string and clean all NULL************************
function transfer($file) {
 // read file to $hash from $buffer. Take max length of Double Integer
 while(($buffer = fgets($file, 64536)) !== FALSE) {
  $hash[] = $buffer;
 }
 // sort $hash and clean from '\0'
 for($k = 0; $k < count($hash); $k++) {
  // cleaned massive
  $strbox[$k] = " ";
  for($i = 0, $j = 0; $j < strlen($hash[$k]); $j++) {
   if($hash[$k][$j] == "\0") {
    continue;
   }
   else {
    $strbox[$k][$i] = $hash[$k][$j];
    $i++;
   }
  } 
 }

 // Clean buffer
 $buffer = NULL;

 return $strbox;
}
//**********transfer all files****************************************************
// device.csv
$box_f = transfer($f);
// pattern.csv
$box_patt = transfer($pattern);
// BTDevices_Adresses.csv
$box_btd = transfer($btdevices);
// create accessories arraies
//********$template_array  ********Array[:TEMPLATES][$i] = Signal Alias   ***********
// parse string into an array
for($i = 0; $i < count($box_patt); $i++) {
 $temp[] = explode(",", $box_patt[$i]);
}
// create Array[:TEMPLATES][$i] = Signal Alias
$template_array = Array();
for($col = 0; $col < count($temp[0]); $col++) {
 $template_name = NULL;
 $template_name = $temp[0][$col];
 for($str = 1; $str < count($temp); $str++) {
  $tem = NULL;
  $tem = $temp[$str][$col];
  $template_array[$template_name][] = $tem;
 }
}
//************************************************  $btd  ***********************   Array[:Tagname] = ShortDesc   *****************
// create Array[:Tagname] = ShortDesc
// ...немного схалтурил, так как нужно искать по индексам или иначе.
// Сие допустимо, так как структура файла - исходника нам известна
// parse string into an array. $i = 0 - header string have to miss
for($i = 1; $i < count($box_btd); $i++) {
 list(, $shortdesc,,,,,,, $tagname) = explode(",", $box_btd[$i]);
 $btd[$tagname] = $shortdesc;
 $shortdesc = NULL;
 $tagname = NULL;
}
//**********$engunits  ****************Array[:Tagname] = EngUnits   *****************
// create Array[:Tagname] = EngUnits
// ...немного схалтурил, так как нужно искать по индексам или иначе.
// Сие допустимо, так как структура файла - исходника нам известна
// parse string into an array. $i = 0 - header string have to miss
for($i = 1; $i < count($box_btd); $i++) {
 list(,,,, $engunit,,,, $tagname) = explode(",", $box_btd[$i]);
 $engunits[$tagname] = $engunit;
 $engunit = NULL;
 $tagname = NULL;
}
// create main array ($arr is base on input file)
//**********************$arr ****************************************************
// parse string into an array
for($i = 0; $i < count($box_f); $i++) {
 $arr[] = explode(",", $box_f[$i]);
}
print_r($arr);
//***********************processing $arr and rewrite needly values*********************
// for change values of $arr in loop we get array by ref
$count_row = 0;
foreach($arr as &$row) {
 foreach($row as $elem => $value) {

  // ':TEMPLATE'
  if((strpos($value, ':TEMPLATE')) !== false) {
  
   // reset array
   $signal_aliases = Array();
   // find template name of device
   list(,$templ) = explode("=", $value);
   $trimmed_templ = trim($templ);
   // defined signal aliases of find template
   // $template_array is array that content link :TEMPLATE -> Array(Template signal aliases)
   if(isset($template_array[$trimmed_templ])) {
    $signal_aliases = $template_array[$trimmed_templ];
   }  
  }
 
  // ':Tagname'
  if((strpos($value, ':Tagname')) !== false) {
  
   // initialization
   $index = 1;
   $stop = true;
   // reset array $tags
   $tags = Array();
   //
   while($stop) {
    $tag = trim($arr[$count_row + $index][$elem]);
    if($tag !== "") {
     $tags[] = $tag;
     $index++;
    }
    if($tag == "") {
     $stop = false;
    }
   }
  }
 
  // 'ShortDesc'
  if((strpos($value, 'ShortDesc')) !== false) {
   // initialization
   $position = $count_row + 1;
   $indexx = 0;
   while($indexx < count($tags)) {
    $tag_item = trim($tags[$indexx]);
    if(isset($btd[$tag_item])) {
     $short_desc = trim($btd[$tag_item]);
     $arr[$position + $indexx][$elem] = $short_desc;
    }
    $indexx++;
   }  
  }
 
  // 'Signal_alias.Desc'
  if((strpos($value, '.Desc')) !== false) {
 
   // find index field 'ShortDesc'
   list($item,) = explode(".", $value);
   $item = trim($item);
   //
   if(in_array($item, $signal_aliases)) {
  
    $pos = $count_row + 1;
    $indexxx = 0;
   
    while($indexxx < count($tags)) {
     $new_tag_item = trim($tags[$indexxx]);
     if(isset($btd[$new_tag_item])) {     
      $new_item = ". ".str_replace("_", " ", $item).".";
      $item_for_push = $btd[$new_tag_item].$new_item;
      $arr[$pos + $indexxx][$elem] = $item_for_push;
     }
     $indexxx++;
    }
   }  
  
  }
 }
 $count_row++;
}
//**************transfer from massive to string and write to output csv-file*****************
// for catch mini bug 'ая;'. It`s may be control symbols
$str = ltrim(implode(",", $arr[0]), "ая;");
fputs($output, $str);
// build output file
for($i = 1; $i < sizeof($arr); $i++) {
 $str = implode(",", $arr[$i]);
 fputs($output, $str);
}
//***********************close handles of source and target csv-files*********************
 
fclose($f);
fclose($pattern);
fclose($btdevices);
fclose($output);
?>

.htaccess. Правило перенаправления ссылок

Задача. Ссылки в адресной строке не должны быть вида http://mysite.ru/index.php?param=target, а должны выглядеть так http://mysite.ru/target.

Для реализации можно воспользоваться следующим способом. Необходимо создать .htaccess, где нужно прописать следующее правило, правило перенаправления. Соответственно, для ограничения поля влияния .htaccess, его нужно разместить в той директории, где нужно распространить сие правило (поддиректории также будут подподать в это поле влияния).

Я сделал так:

RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ http://mysite.ru/index.php?param=$1

php5. Debuging...

Иногда, для отлова своей же ошибки (!), приходится тратить много времени, казалось бы все хорошо, но почему-то все идет не так как мы того хотели бы. Что же мешает быстродействию отлова (debug)? Лень. Например, для того, чтобы понять, что же происходит, в определенных кусках кода проставляем команду вывода содержимого какой-нибудь переменной, бывает, нужно проставить таких меток более десятка, вот здесь и нужно проявить усидчивость, нужно их по-человечески прописать, чтобы при дальнейшем анализе было понятно, что идет не так!

MySQL Command Line Client. Not launch on WinOS

Если не запускается MySQL Command Line Client, нужно немного подкрутить в my.ini в блоке [mysql]: добавить строчечку вида character-sets-dir="C:/mysql5/share/charsets/". По-сути, здесь прописан путь до кодировок (используются правые "слэши")

PHP5. Обращение к переменным родительского класса. Два способа

Как можно получить доступ дочернего класса к переменным родительского класса?

Способ первый: необходимо несколько условий. 1 - переменные в родительском классе должны быть объявлены как protected, 2 - при объявлении дочернего конструктора, необходимо также объявить родительский конструктор, 3 - соответственно, обращаемся к переменной родительского класса как ко внутренней переменной $this->variable;

Способ второй: 1 - переменные в родительском классе могут быть закрытыми (private), 2 - необходимо создать методы, позволяющие получить доступ к переменным из дочернего класса, 3 - при объявлении дочернего конструктора, необходимо также объявить родительский конструктор, 4 - соответственно, обращаемся к переменной родительского класса через соответствующие методы parrent::getVariable();

Ниже приведен пример использования двух спобов обращения к переменным родительского класса.

<?php ##Обращение к переменным родительского класса. Два способа
// Родительский класс
class Item {
 // Для первого способа необходим уровень конфиденциальности - protected
 protected $name;
 private $code;
 // Консруктор родительского класса
 function __construct( $name = "Item", $code = 0 ) {
  $this->name = $name;
  $this->code = $code;
 }
 // Для второго способа создаем метод
 function getName() {
  return $this->name;
 }
 // Также создаем метод для второго метода
 function getCode() {
  return $this->code;
 }
}
// Дочерний класс
class PriceItem extends Item {
 private $temp;
 // Конструктор родительского класса
 function __construct( $name, $code, $temp = "temp" ) {
  // Обязательное объявление родительского конструктора
  parent::__construct( $name, $code );
  // Обращаемся к переменным родительского класса вторым способом - parent:getName() и getCode()
  $this->temp = "temp = ".$temp." name = ".parent::getName()." code = ".parent::getCode();
 }
 // Для вывода результата обращения к переменным родительского класса первым способом
 function getParentName() {
  return $this->name;
 }
 // Для вывода результата обращения к переменным родительского класса вторым способом
 function getIt() {
  return $this->temp;
 }
}
// Инстанцируем объект
$Item = new PriceItem(Name, 1616);
// Выводим результаты
print $Item->getIt();
print "<br />";
print $Item->getParentName();
?>

C/C++/PHP5. About Windows services

Предположим, нам необходимо воспользоваться неким скриптом, который должен циклически ожидать каких-либо внешних изменений, реагируя определенным действием в ответ. Вроде бы не сложно. Инициируем сие скрипт в системе посредством автозагрузки. Но как-то это не серьезно.
Другое дело - реализовать скрипт через службы. Далее рассматриваются службы систем win32. Скриптовая часть - php-файл, batch-файл, да что угодно. Попробуем создать службу стандартными средствами самой системы:

sc create tester start= auto binPath= c:\tester\tester.php

В базу служб будет занесена запись о новой службе tester. Попытаемся запустить ее. Ну как? Нас ждет сообщение об ошибке запуска службы. Не смотря на это в "инете" такого рода решения встречаются очень часто. Правда там же предлагают дополнительные шаманства в реестре. Вам это по-душе? 
Если немного порыться в источниках Microsoft, можно узнать, что binPath должен "смотреть" на exe-файл. Немного "покодив" можно создать прототип нашего скрипта. Но после очередного теста стало ясно, что и это не прокатывает. В чем тогда дело? А в том, что служба - непросто исполнимый файл, это нечто большее. Вот пара ссылок на то, чтобы понять суть слова - большее:

Скелет службы (service) на Visual C++
http://dobrunov.ru/2009/08/service-visual-c.html

Beginner's introductory guide to writing, installing, starting, stopping NT services
http://www.codeproject.com/Articles/1697/Beginner-s-introductory-guide-to-writing-installin

Создание своего Windows Service
http://habrahabr.ru/post/71533/

Using Services
http://msdn.microsoft.com/en-us/library/ms686953%28v=vs.85%29 

Таким образом необходимо разработать службу. Но все же как нам не терять связи с нашим изначальным скриптом. Мое решение таково: 1) при создании службы в системе, создаем дополнительную переменную окружения; 2) при запуске службы в данную переменную заносим соответствующее значение и далее запускаем сам скрипт, который циклически просматривает значение переменной окружения; 3) соответственно, остановка службы должна приводить к изменению значения данной переменной, что будет указывать скрипту на необходимость завершения своей работы.
В данном случае переменные окружения могут выступать как посредники между exe-службой и скриптовой частью. Это подобие глобальных переменных в PHP.


C/C++. Quine. Куайны или квайны

Что такое куайн или квайн программирование?
Куайн, квайн (англ. quine) — компьютерная программа (частный случай метапрограммирования), которая выдаёт на выходе точную копию своего исходного текста.
На днях столкнулся с подобной задачей: реализовать на С++ куайн или квайн, но с одним но - вывести текст не на стандартное устройство вывода (например, консоль), а во внешний текстовый файлик (например, output.txt).
Пришлось немного поломать голову. С одной стороны - просто, а с другой начинаешь себя спрашивать - с какого угла подойти? Немного помогла статья с "хабры" - "Как писать квайны":
Введение 
Многие программисты считают написание квайнов (программ, выводящих свой исходный код) непосильной задачей. И действительно — все эти цепные квайны и квайны различного порядка, при взгляде на которые можно потеряться в казалось бы бессмысленном наборе символов…
Однако на самом деле написать квайн на каком-либо языке не так сложно, как кажется. Сейчас я расскажу, как сделать это на различных языках программирования. Более того, мы не будем использовать «хаки» интерпретеруемых языков вроде операции вывода исходного кода и функций типа eval, а также напишем квайны на интерпретируемых и компилируемых языках.
Теория
Попробуем написать квайн. Для этого возьмём инструкцию языка для вывода и передадим ей как параметр код программы. Однако в коде мы снова используем этот же код и так далее — возникает бесконечная рекурсия. Но что можно сделать для того, чтобы не передавать строковую константу? Решение — поместить строку (копию части кода) в переменную. Для удобства назовём такую строку s-строкой, а переменную с этой строкой — s-переменной. Чтобы и в s-переменной не было рекурсии, мы просто исключим из неё фрагмент со значением этой самой переменной. То есть, выглядеть это будет примерно так:

C:

char s[]="char s[]=;";

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

Далее, при выводе, мы подставим значение s-строки в её же определение в коде (в примере выше — перед тремя последними символами). Здесь же возникает ещё несколько проблем. Первая проблема — при подставлении в s-строке нельзя использовать символы, которые поведут себя в коде не так, как надо. Например, мы не можем так просто вставить кавычку — ведь вместо того, чтобы стать частью s-строки, она завершит её определение и выводимый код не будет совпадать с исходным, являясь некорректным вообще.


Экранирование применить здесь достаточно сложно — символ экранирования надо тоже экранировать и т.д.. Гораздо проще, например, использовать другой вариант кавычек — так, во многих интерпретируемых языках разрешено использование как одинарных, так и двойных кавычек для задания строки, а отличие состоит в том, что можно без проблем использовать одну кавычку в константе, если она ограничивается другими. То есть, код
'"' создаст односимвольную строку с двойной кавычкой, а код "'" — с одиночной. Если использовать этот вариант, удобно задать в начале переменную с какой-либо кавычкой, а затем использовать её при выводе.

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


Следующая проблема — вставка другой строки (или символа с каким-либо кодом) в вывод s-строки. Решение здесь очевидно — брать подстроку s-строки специальной функцией, выводить её, далее выводить то, что надо вставить, затем выводить другую подстроку s-строки. Может показаться, что в Си взятие подстроки для вывода потребует немало кода. Тут нам на помощь придёт мощь функции printf. Так, например, вот варианты кода для различных языков, печатающего часть строки s со второго символа (считая с единицы) по четвёртый включительно:


Python:

print(s[1:4])

Ruby:

print s[1..3]

Perl:

print substr(s,1,2)

C:

printf("%.2s",s+1);

Обычно методы взятия подстроки могут также брать её остаток до конца. Например, напечатаем строку s со второго символа до конца строки (то есть, всю строку кроме первого символа):

Python:

print(s[1:])

Ruby:

print s[1..-1]

Perl:

print substr(s,1)

C:

printf("%s",s+1);

Если такой возможности нет, придётся на место параметра с длиной подстроки поставить заглушку типа «XX», а затем в конце посчитать символы до конца и подставить их вместо «XX» в коде и в s-строке, не изменяя длины различных частей кода. Например, если в длине окажется одна цифра, целесообразно подставить вместо первого икса пробел, ведь если его удалить, длины частей s-строки изменятся и их придётся пересчитывать.

Интерпретируемые языки
Итак, начнём писать квайны, собрав все суждения выше. На Python я написал такой квайн (работает и на 3.x):
q="'";s='q="";s=;print(s[:3]+q+s[3:7]+q+s+q+s[7:])';print(s[:3]+q+s[3:7]+q+s+q+s[7:])

Здесь переменная q используется как переменная, где хранится одинарная кавычка, далее идёт определение s-переменной со всем кодом, кроме самой s-строки. После этого идёт вывод s-переменной со следующими вставками:
1). Одинарная кавычка как значение переменной q;
2). Одинарная кавычка как начало определения s-строки;
3). Сама s-строка (да-да, s-строка вставляется внутри s-строки);
4). Одинарная кавычка как конец определения s-строки.
Примечание. При написании квайнов по данному методу не забывайте копировать все изменения в коде в копию кода в s-строке.

С минимальными изменениями можно получить квайн только для
Python 2.x:
q="'";s='q="";s=;print s[:3]+q+s[3:7]+q+s+q+s[7:]';print s[:3]+q+s[3:7]+q+s+q+s[7:]

Абсолютно аналогичны и квайны на других языках, где мы изменяем лишь некоторые синтаксические особенности:

Ruby:

q="'";s='q="";s=;print s[0..2]+q+s[3..6]+q+s+q+s[7..-1]';print s[0..2]+q+s[3..6]+q+s+q+s[7..-1]

Perl:

$q="'";$s='$q="";$s=;print substr($s,0,4).$q.substr($s,4,5).$q.$s.$q.substr($s,9)'; 
print substr($s,0,4).$q.substr($s,4,5).$q.$s.$q.substr($s,9)

PHP:

<?$q="'";$s='<?$q="";$s=;print substr($s,0,6).$q.substr($s,6,5).$q.$s.$q.substr($s,11);' 
;print substr($s,0,6).$q.substr($s,6,5).$q.$s.$q.substr($s,11);

Компилируемые языки.
Написание квайна на C оказалось чуть более трудной задачей. Здесь я активно использовал коды символов: двойной кавычки — 34, и перевода строки — 13 (он понадобился, чтобы отделить директиву компилятора для включения stdio.h), а также интересный способ взятия подстроки с помощью printf, уже описанный выше.

А вот и сам квайн:


#include <stdio.h>
int main(){const char *s="#include <stdio.h>int main(){const char *s=;
printf(%.18s%c%.25s%c%s%c%.8s%c%.33s%c%s,s,10,s+18,34,s,34,s+43,34,s+51,34,s+84);
return 0;}";printf("%.18s%c%.25s%c%s%c%.8s%c%.33s%c%s",s,10,s+18,34,s,34,s+43,34,s+51,34,s+84); 
return 0;}

Заключение.
Вот и всё. Я написал квайны на большинстве языков, интерпретаторы и компиляторы которых обнаружил на своём компьютере. Думаю, теперь вы и сами напишете подобную программу на своём любимом языке программирования, если я не упомянул его здесь. В качестве упражнения вы также можете написать квайн на таких языках, как Java, C#, Haskell или Pascal. Не бойтесь трудностей — достаточно попробовать, и всё получится! 

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


Ниже приведен листинг решения поставленной задачи.  Скачать можно по ссылке - Download.


#include <stdio.h>
void main(){FILE *f=fopen("output.txt","w");const char *s="#include <stdio.h>void main(){FILE *f=fopen(output.txt,w);const char *s=;fprintf(f,%.18s%c%.26s%c%.10s%c%.1s%c%.1s%c%.16s%c%s%c%.11s%c%.60s%c%s,s,10,s+18,34,s+44,34,s+54,34,s+55,34,s+56,34,s,34,s+72,34,s+83,34,s+143);fclose(f);}";fprintf(f,"%.18s%c%.26s%c%.10s%c%.1s%c%.1s%c%.16s%c%s%c%.11s%c%.60s%c%s",s,10,s+18,34,s+44,34,s+54,34,s+55,34,s+56,34,s,34,s+72,34,s+83,34,s+143);fclose(f);}

 

PHP5. Temporary files

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


<?php ##Temporary files
// Создаем в текущей директории временный файл
$tmp = tempnam(".", "udp");
// Содержимое для временного файла
$content = "Testing...\n";
// "Кладем" данное содержимое во временный файл
file_put_contents($tmp, $content);
// IExplorer для просмотра временного файла
$ie = '"C:\Program Files\Internet Explorer\iexplore.exe" ';
// Путь к временному файлу
$exec = $ie.$tmp;
// Просмотр временного файл User-agent-ом
system($exec);
// Удаляем временный файл
unlink($tmp);
?>

PHP5. Модуль CLI SAPI. Встроенный web-сервер



Официальный сайт PHP - http://www.php.net - гласит:

Начиная с версии PHP 5.4.0 модуль CLI SAPI содержит встроенный web-сервер.

Этот web-сервер предназначен для использования при разработке и не должен использоваться на обычном сервере. 

URI запросы обслуживаются из текущей директории, в которой был запущен PHP, если не используется опция -t для явного указания корневого документа. 

Если URI запроса не указывает на определенный файл, то будет возвращен либо index.php, либо index.html в данной директории. Если не существует ни одного из них, то возвращается 404 код ответа.

Если PHP-файл указывается в командной строке, когда запускается веб-сервер, то он рассматривается как скрипт "маршрутизации" web-сервера. Скрипт выполняется в самом начале после каждого HTTP-запроса. Если этот скрипт возвращает FALSE, то запрашиваемый ресурс возвращается как есть. В противном случае браузеру будет возвращен вывод этого скрипта. 

Если в работе есть необходимость часто работать с php-скриптами, для удобства взаимодействия с ними, например через GUI, можно воспользоваться данным веб-сервером. Намекаю на standalone (и только) приложения, сам запуск такого "сервачка" можно внедрить в сервисы (службы).




PHP5. Ссылки на массив - интерфейс доступа - деревья

Предположим, что мы строим такую структуру данных как дерево на массивах. Как сделать так, чтобы обращение к дереву было уникальным, то есть как создать интерфейс доступа к узлам и элементам дерева?

Один из способов - использование ссылки на массив с последующими ее условными переопределениями. Так мы реализуем интерфейс доступа к дереву. "Покодим" немного.



PHP5. Распаковка строкового представления n-мерного массива в исходный массив. String to array

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

<?php ## Распаковка строкового представления в n-мерный массив
// Счетчик вложенности массивов
$in = 0;
// Используем для отлова элементов (ключ => значение)
$catched = 0;
// Строковое представление массива (упакованный вид)
$str = "[|first|element|second|element|[|first_1|element_1|second_1|element_1|third_1|element_1|therd_1|element_1|]|third|element|[|first_2|element_2|second_2|element_2|]|2|end|]";
// Перекидываем элементы из строки $str в список - массив $view 
$view = explode("|", $str);
// Создаем пустой рабочий массив для распаковывания строкового представления //массива
$restore = array();
// Создаем рабочую ссылку на рабочий массив $restore.
$temp = &$restore;
// Проccматриваем массив $view
foreach($view as $val) {
    // Открываем массив
    if($val == "[") {
        // Увеличиваем счетчик вложенности массивов
        $in++;
        // Перезаписываем рабочую ссылку на последующий элемент массива $restore
        // Такого рода перезаписи используем для создания единого интерфейса доступа к //рабочему массиву
        $temp = &$temp[];
    }
    // Закрываем массив
    elseif($val == "]") {
        // Используем счетчик вложенности массивов $in для переопределения ссылки $temp //на рабочий массив $restore
        $step = $in - 1;
        // Перезаписываем ссылку. По-сути, возврат на начало
        $temp = &$restore;
        // Устанавливаем ссылку на соотвествующий элемент массива $restore
        // Такого рода перезаписи используем для создания единого интерфейса доступа к //рабочему массиву
        while($step) {           
            $temp = &$temp[0];
            $step--;
        }
        // Понижаем счетчик вложенности
        $in--;
    }
    // Запись извлекаемых ключей и соответствующих значений в рабочий массив $restore //с помощью ссылки $temp.
    // По-сути, $temp - интерфейс доступа
    else {
        // счетчик отлова очередного элемента массива $view
        $catched++;
        // Временный буфер для отлова ключей и соответствующих значений
        $buffer[] = $val;
        // Так как элементы в проссматриваемом массиве $view содержат ключ и значение в //паре, используем такой мини-фильтр
        if($catched == "2") {
            // Распределяем отловленный ключ и соответствющее значение в буферные //переменные $key и $value
            list($key ,$value) = $buffer;
            // Записываем ключ и соответствующее значенее в рабочий массив $restore
            $temp[$key] = $value;
            // Сброс счетчика отлова очередного элемента массива $view
            $catched = 0;
            // Очищаем временный буфер $buffer
            unset($buffer);
        }

    }
}
// Так как изначально для распаковки был создан массив $restore, а первый и последний //элементы Sstr порождали новый массив $restore[0] = array(), куда фактически
// все и распаковывалось, то для идеальности результата необходимо их перезаписать
$restore = $restore[0];
// Смотрим на результат
print_r($restore);           
?>


Да, решение данного вида не идеально, не эстетично, поэтому-то необходимо для этих - и не только - целей использовать стандартные методы сериализации PHP5:

// Упаковывка не только массивов, но и чего-угодно
string serialize(mixed $obj);

// Распаковка в исходном виде сериализованного объекта
mixed unserialize(string $st);

Если в представленной реализации упаковки массива в строку были ограничения (критичность значения содержащего символ "|"), то прибегая к этим функциям можно этого не бояться. Что уж говорить, если данные методы сериализации активно используются при работе с базой данных, упаковывая и распаковывая различного рода объекты. 

 

PHP5. Строковое представление n-мерных массивов. Array to string

Как n-мерный массив представить в виде строки?
Здесь представлена одна из реализаций. В связи с многомерностью была использована рекурсия. А разделителем элементов массива в рабочей строке была принята вертикальная черта - "|". Отсюда не универсальность данного подхода, так как при наличии такого же символа в разбираемом массиве в ключе, в значении или в обоих составляющих, возникает путаница. Поэтому нужно что-то посерьезнее придумать. Это блюдо из быстрой кухни :)
Скачать данный листинг можно здесь - downoad.

<?php ## Перевод n-мерного массива в строковое представление
// Строка для формирования строкового представления массива
$str = "";
// Строковый разделитель-казатель начала массива
$begin = "[";
// Строковый разделитель-указатель окончания массива
$end = "]";
/* Разделитель элементов массива (ключей, значений, вложенных элементов-массивов) в формировании $str */
$separator = "|";

// Тестовый 2-у мерный массив

$massive = array(
                    "first" => "element",
                    "second" => "element",
                    array(
                            "first_1" => "element_1",
                            "second_1" => "element_1",
                            "third_1" => "element_1",
                            "therd_1" => "element_1",
                        ),
                    "third" => "element",
                    array(
                            "first_2" => "element_2",
                            "second_2" => "element_2",
                        ),
                    "2" => "end",                          
                );
      

/* Функция для рекурсивного поиска среди элементов массива вложенных массивов. Передаем рабочую строку $str и элемент с вложенным массивом $temp */          
function searchIn($str, $temp) {  
    $str = "";
    $begin = "[";
    $end = "]";
    $separator = "|";
    // Формируем строковое представление массива
    $str .= $separator;
    $str .= $begin;
    foreach($temp as $key => $value) {
        // Поиск вложенных массивов среди элементов переданного массива
        if(is_array($massive[$key])) {
            /* При наличии вложенных массивов продолжаем поиск вглубь элемента массива.
             Полное погружение обеспечивается за счет рекурсивного вызова исходной функции   searchIn($str, $temp) */
            $str .= searchIn($str, $massive[$key]);
        }
        else {
            $str .= $separator;
            $str .= $key;
            $str .= $separator;
            $str .= $value;
        }
    }
    $str .= $separator;
    $str .= $end;
    // Возвращаем сформированное строковое представление массива
    return $str;  
}

// Формируем строковое представление массива $massive
$str .= $begin;
foreach($massive as $key => $value) {
    // Поиск вложенных массивов среди элементов массива $massive
    if(is_array($massive[$key])) {
        /* При наличии вложенных массивов продолжаем поиск вглубь элемента массива.
        Полное погружение обеспечивается за счет рекурсивного вызова исходной функции searchIn($str, $temp) */
        $str .= searchIn($str, $massive[$key]);
    }
    else {
        $str .= $separator;
        $str .= $key;
        $str .= $separator;
        $str .= $value;
    }
}
$str .= $separator;
$str .= $end;

// Выводим полученное строковое представление $str исходного 2-у мерного массива $massive
echo $str;
?>   


В итоге на столе окажется строчечка следующего вида:

[|first|element|second|element|[|first_1|element_1|second_1|element_1|third_1|element_1|fourth_1|element_1|]|third|element|[|first_2|element_2|second_2|element_2|]|2|end|]