C++. Application for processing input files and generate output html-files

В начале года на глаза попалась одна задачка. Суть состояла в следующем: разработать приложение, на вход которого подаются входные файлы, с размером не более 2Мб, один из которых - текстовый файл, состоящий из некоторого текста, второй - справочник, состоящий из различных слов (слово занимает ровно одну строку). Справочник полностью должен быть загружен в память машины, в отличие от первого входного файла, его нельзя сразу загружать. Приложение должно обрабатывать первый входной файл с учетом справочника и генерировать выходные html-файлы, валидные по отношению к различным браузерам (IE, Firefox, Chrome и др.) и иметь способность загрузки браузером за время не более 5-10 секунд. Содержимое этих выходных файликов должно в точности соответствовать содержимому первого входного файла с одним исключением: нужно пометить жирным и наклонным шрифтом все слова из справочника. Количество выходных html-файлов должно определяться пользователем при определении желаемого максимального количества строк в этих выходных файликах. Помимо всего прочего необходимо реализовать перехват и обработку исключительных ситуаций.

Решение построил на основе объектно-ориентированного подхода. Для этого было создано два класса: class Search (основной класс) и class Exceptions (очень упрощенный класс, без обработки, только отлавливает и выводит сообщение об исключении). Эти классы приведены ниже



Search.h

#ifndef SEARCH_H
#define SEARCH_H


#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <sstream>
#include <map>


using namespace std;

class Search {

 // Допустимое количество строк в выходных файлах
 int N;

 // Текущая позиция обрабатываемой строки входного файла
 int current_pos;

 // Нумератор ( необходим для именования выходных файлов )
 int numerator;

 // Префикс ( статическая часть имени выходных файлов )
 string prefix;

 // Расширение выходных файлов ( default - .html )
 string file_extension;

 // Буферная строка ( используем для сохранения и записи обработанных строк )
 string current_str_buffer;

 // Ассоциативный map-контейнер ( слово - тегированное слово ). Для загрузки справочника
 map<string, string> catalogBuffer;

public:
 Search() : N(0), current_pos(0), numerator(0) {
  // Первоначальная инициализация
  Search::set_file_extension();
  Search::set_name_prefix();
  Search::set_num_lines();
 };

 // Определение имен входных файлов
 string get_ifstream_file_name();

 // Определение имен выходных файлов
 string get_ofstream_file_name();

 // Определение префикса (статическая часть) имен выходных файлов
 void set_name_prefix();

 
// Определение расширения выходных файлов
 void set_file_extension();

 // Определение допустимого максимального количества строк в выходных файлах
 void set_num_lines();

 // Загрузка справочника в память
 void get_catalog(ifstream &file);

 // Открытие файла (ifstream поток)
 void open(ifstream &file);

 // Открытие файла (ofstream поток)
 void open(ofstream &file);

 // Закрытие файла (ifstream поток)
 void close(ifstream &file);

 // Закрытие файла (ofstream поток)
 void close(ofstream &file);

 // Разбор строки по словам и поиск по справочнику. Результат заносится в буферную строку
 void find(string &temp);

 // Запись текущей буферной строки в выходной файл
 void write(ofstream &output);

 // Обработка входного файла по справочнику и генерация выходных файлов
 void get_output(ifstream &input, ofstream &output);

};

#endif SEARCH_H



 





Exceptions.h

#ifndef Exceptions_H
#define Exceptions_H


#include <iostream>

using namespace std;

class Exceptions {

 char str_what[80];


public:

 Exceptions() {*str_what = 0;}

 Exceptions(char *str) {strcpy(str_what, str);}

 void what() {
 
  cout << "Exception: " << str_what << endl;
 
 }


};

#endif Exceptions_H

class Search ориентирован на прямую работу с входными файлами, поэтому большинству методов передаются соответствующие ссылки на наши файлики (если точнее - на ifstream и ofstream потоки). 

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

Реализация класса Search и реализация программы SearchMain представлено ниже

Search.cpp

#include "Search.h"
#include "Exceptions.h"


// Определение имен входных файлов
string Search::get_ifstream_file_name() {
 string file_name;
 cout << "Enter file name:" << endl;
 cin >> file_name;
 return file_name;
}


// Определение имен выходных файлов
string Search::get_ofstream_file_name() {
 ++Search::numerator;
 // Конвертация нумератора - numerator - в строку типа string ( integer -> string )
 stringstream stream_converter;
 if (!(stream_converter << Search::numerator)) {
  throw Exceptions("internal fail of convertation");
 }
 string temp_converter = stream_converter.str();

// Формируем полное имя выходного файла
 string temp = Search::prefix + temp_converter + Search::file_extension;
 return temp;
}


// Определение префикса (статическая часть) имен выходных файлов
void Search::set_name_prefix() {
 string temp;
 cout << "Enter name prefix for naming output files:" << endl;
 cin >> temp;

// Небольшая проверка на валидность введенного префикса имени файла
 for (int i = 0; i < temp.length(); i++) {
  if (!isalnum(temp[i])) {
   throw Exceptions("name prefix content is not valid symbols");
  }
 }
 Search::prefix = temp;
}


// Определение расширения выходных файлов
void Search::set_file_extension() {
 // По умолчанию...
 Search::file_extension = ".html";
}


// Определение допустимого максимального количества строк в выходных файлах
void Search::set_num_lines() {
 string temp;
 // Флаг валидности значения ( введено ли целое число )
 bool stop;
 for (;;) {
  cout << "Enter max string number lines in output file(s):" << endl;
  stop = true;
  cin >> temp;
  // Небольшой анализатор валидности введенного пользователем значения
  for (int i = 0; i < temp.length(); i++) {
   // Если число
   if (isdigit(temp[i])) {
    // Недопустимо
    if (temp[0] == '0') {
     stop = false;
     break;
    }
   }
   // Если не число
   else {
    stop = false;
    break;
   }
  }
  // Если введено валидное значение (целое число), выходим из цикла
  if (stop) {
   break;
  }
  cout << "Illegal value (not an integer or illegal character). Please, repeat!" << endl;
 }
 // Конвертируем валидное значение в целое ( string -> integer )
 // и сохраняем значение
 int n;
 stringstream stream_converter;
 stream_converter << temp;
 if (!(stream_converter >> n)) {
  throw Exceptions("internal fail of convertation");
 }
 else {
  Search::N = n;
 }
}


// Загрузка справочника в память
void Search::get_catalog(ifstream &file) {
 if(!file.fail()) {
  // Наполняем map - контейнер catalogBuffer словами из справочника catalog.txt
  for(string search_word, wrapper; !file.eof();) {
   // Считываем слово из справочника
   file >> search_word;
   // Небольшая защита от несоответствия структуры входного справочника
   // на наличие пустых строк между словами
   if (!search_word.empty()) {
    // Оборачиваем в требуемые html - теги
    wrapper = "<b><i>" + search_word + "</i></b>";
    // Сохраняем результат в map - контейнер catalogBuffer
    Search::catalogBuffer[search_word] = wrapper;
   }
   // Сброс содержимого строк
   search_word.clear();
   wrapper.clear();
  }
 }
 else {
  throw Exceptions("file is failed");
 }
}


// Открытие файла ( ifstream поток )
void Search::open(ifstream &file) {
 // Получаем имя файла входного файла
 string file_name = Search::get_ifstream_file_name();
 // Открытие файла
 file.open(file_name.c_str(), ios::in);
 if (!file.fail()) {
  // Определение размера входного файла, b
  file.seekg (0, ios::end);
  double length = file.tellg();
  file.seekg (0, ios::beg);
  if ((length/1024/1024) > 2) {
   cout << "size of file ( " << length << "Mb ) bigger than available ( 2Mb )" << endl;
   throw Exceptions("file is failed");
  } else {
   cout << "size of file in available zone" << endl;
  }
 }
 else {
  cout << "file is not open, check your file!" << endl;
  throw Exceptions("file is failed");
 }
}


// Открытие файла ( ofstream поток )
void Search::open(ofstream &file) {
 // Получаем имя файла выходного файла
 string file_name = Search::get_ofstream_file_name();
 // Открытие файла
 file.open(file_name.c_str(), ios::out);
 if (file.fail()) {
  throw Exceptions("file is failed");
 }
}


// Закрытие файла (ifstream поток)
void Search::close(ifstream &file) {
 // Закрытие входного файла
 file.close();
}


// Закрытие файла (ofstream поток)
void Search::close(ofstream &file) {
 // Закрытие выходного файла
 file.close();
}


// Разбор строки по словам и поиск по справочнику. Результат заносится в буферную строку 
void Search::find(string &temp) {
 ++Search::current_pos;
 // При возникновении неожиданных исключительных ситуаций перехватываем их и снова перенапрвляем
 try {
  // Итератор для map-контейнера catalogBuffer
  map<string, string>::iterator iteratorCatalogBuffer;
  string search_word, wrapper;
  // Проссматриваем слова строки temp в справочнике catalogBuffer
  for (iteratorCatalogBuffer=Search::catalogBuffer.begin(); iteratorCatalogBuffer!=Search::catalogBuffer.end(); ++iteratorCatalogBuffer) {
   search_word = iteratorCatalogBuffer->first;
   wrapper = iteratorCatalogBuffer->second;
   // Поиск соответствий слов от начала и до конца по справочнику.
   // При нахождении соответствия производим замену на тегированное слово из справочника ( обертка html - тегами )
   for (int found = temp.find(search_word); found!=string::npos; found=temp.find(search_word,found+wrapper.length())) {
    temp.replace(found, search_word.length(), wrapper);
   }
  }
 } catch (...) {
  throw Exceptions("Error in find method!");
 }
 // Добавляем тег переноса html строк
 temp+= "<br>";
 // Итоговая строка готова для записи. Сохраняем в буферную строку
 Search::current_str_buffer = temp;
}


// Запись текущей буферной строки в выходной файл
void Search::write(ofstream &output) {
 // output.fail()
 if (!output.fail()) {
  // Запись содержимого буферной строки в выходной файл
  output.write(Search::current_str_buffer.c_str(), Search::current_str_buffer.length());
 }
 else {
  throw Exceptions("write to file is failed");
 }
}


// Обработка входного файла по справочнику и генерация выходных html - файлов
void Search::get_output(ifstream &input, ofstream &output) {
 for (string temp; !input.eof(); temp.clear()) {
  // При текущей позиции обрабатываемой строки входного файла в начале 
  if (Search::current_pos == 0) {
   // Открытие выходного файла
   Search::open(output);
  }
  // При достижении текущей позиции обрабатываемой строки входного файла
  // заданной границы допустимого количества строк в выходных файлах
  if (Search::current_pos == Search::N) {
   // Сброс текущей позиции обрабатываемой строки входного файла в начало
   Search::current_pos = 0;
   // Закрытие выходного файла
   Search::close(output);
   continue;
  }
  // Извлечение текущей строки из входного файла для последующего поиска соответствий по справочнику
  getline(input, temp);
  // Поиск соответствий слов текущей строки по справочнику.
  // Результат заносится в буферную строку
  Search::find(temp);
  // Запись буферной строки в выходной файл
  Search::write(output);
 }
}


SearchMain.cpp
 
#include "Search.h"
#include "Exceptions.h"


int main() {

 // Входной файл (*.txt) input.txt
 ifstream input;
 // Справочник (*.txt) catalog.txt
 ifstream catalog;
 // Выходной файл (*.html) prefix1.txt
 ofstream output;

 // Создаем объект
 Search *search = new Search();

 try {
 
  // Открываем входные файлы
  cout << "Input file. ";
  search->open(input);
  cout << "Catalog file. ";
  search->open(catalog);
 
  // Загружаем словарь справочника в память
  cout << "Download catalog to memory..." << endl;
  search->get_catalog(catalog);
 
  // Начинаем обрабатывать входной файл с учетом справочника
  // и генерировать выходные html - файлы
  cout << "Processing..." << endl;
  search->get_output(input, output);


 } catch(Exceptions e) {
   e.what();
 }


 // Закрываем входные файлы
  search->close(input);
  search->close(catalog);
  delete search; 

 return 0;
}

Ниже приведен алгоритм сие программы

1. Создаем объект класса Search и ссылку на него. В это время будут вызваны методы, которые затребуют ввода префикса выходных файлов (это статическая часть имени) и желаемое максимальное количество строк в выходных html-файлах

2. Далее создаем ifstream и ofstream потоки (точнее - объекты), которые передаем классу Search для открытия этих потоков (открытие входных файлов)

3. Если справочник открылся, то загружаем его полностью в память машины. Загружается в память ассоциативный map-контейнер, которое получаем из разбора слов, в итоге получаем пару <слово - тегированное слово>. Тегированное слово - это слово обернутое в html-теги для жирности и наклонности шрифта, например - <b><i>word</i></b>

4.1 Далее начинаем построчно считывать содержимое первого входного файла, которое в свою очередь разбирается на слова, которые сравниваются со словами справочника. Если найдено соответствие, то заменяем слово в считанной строке на тегированное слово из справочника (по сути - из map-контейнера)

4.2 После полного разбора, строка записывается в буфер класса (буферная строка)

4.3 Открываем выходной файл.

4.4 Записываем содержимое буфера (буферная строка)

4.5 Закрываем выходной файл

Продолжаем считывать следующую строку входного файла. Далее все повторяется до тех пор, пока не будет достигнут конец входного файла. Стоит отметить, что на этих шагах при каждом считывании строки входного файла производится инкрементирование внутренней переменной класса (Search::current_pos) и сравнение с числом допустимых максимальных строк в выходных файлах (Search::N), которое было введено во время создания объекта нашего класса. В сравнении определяется, или открыть новый выходной файл, или же закрываем выходной файл, или продолжаем работать.

5. Закрываем входные файлы (потоки) и уничтожаем объект класса Search

6. Программа завершена

Также отмечу, что поиск соответствий слов по справочнику очень прост: каждое слово приводит к полному просмотру справочника, от начала и до конца, здесь можно поработать над оптимизацией, например, проводить поиск по первым символам в слове подобно поиску в базе данных по индексу. Есть над чем подумать :)

Если запстить прогу, то вот что получим.


Исходники можно скачать по ссылке - download.

Псевдокод. Удобство разработки и написания алгоритма

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

 ЦИКЛ ДЛЯ J=1 ДО N-1 ШАГ 1                  
   ЦИКЛ ДЛЯ I=1 ДО N-J ШАГ 1                    
     ЕСЛИ A[I]>A[I+1] ТО ОБМЕН A[I],A[I+1]       
   СЛЕДУЮЩЕЕ I                                
 СЛЕДУЮЩЕЕ J
 
 Ну а далее производим реализацию на языке программирования: 
 
 FOR J=1 TO N-1 STEP 1 
   FOR I=1 TO N-J STEP 1 
     IF A[I]>A[I+1] THEN SWAP A[I],A[I+1]
   NEXT I
 NEXT J
 
Если нет функции SWAP A[I],A[I+1], тогда можно заменить ее следующим образом:
 
 TEMP=A[I]
 A[I]=A[I+1]
 A[I+1]=TEMP                               

 По мне - временами очень помогает в прояснении своих мыслей. Всем хорошего дня.

RSLogix Emulate 5000. Process Emulation.

Для освоения plc программирования недостаточно обращаться к мануалам, все же желательно иметь под рукой среду разработки. Для промышленного программирования сама по себе среда разработки специфична, все зависит от контроллера. Но и этого мало. Также нужно иметь под рукой сам контроллер с входными и выходными сигналами. Откуда взять и того и другого? Для этого есть эмулятор. Я работаю с контроллерами AllenBradley, поэтому рассматриваю эмуляцию под контроллеры именно этой линии. Итак, средой разработки служит Рслогих 5000 (версион 17.0), а для эмуляции используется RSLogix Emulate 5000. Ниже приведены детальные скриншоты, которые помогут пошагово установить и настроить эмулятор. Желаю успехов.
 
For the development of PLC programming is not enough to access the manual, it is still desirable to have at hand a development environment. Industrial programming alone development environment specific, depending on the controller. But this is not enough. You also need to have on hand controller with input and output signals. And where to get that, and the other? For that there are emulators. I work with controllers Allenbradley, so consider emulation controller is under this line. Thus, the development environment is Rslogih 5000 (VCS 17.0), and is used to emulate the RSLogix Emulate 5000. Below are detailed screenshots to help you install and configure steps emulator. I wish you success.

Before start to install need stop RSLinx service


Start installing...

 
 
Step1. After install. Launch emulator
Step 2. Add controller in chassis
Step 2.1. Configure controller 
Step 2.2. Configure controller
Step 2.3. Controller is added
Step 3. Add I/O module (for emulate input and output signals) in chassis
Step 3.1. Configure I/O module
Step 3.2. Configure I/O module
Step 3.3. I/O module is added
Step 4. Open RSLinx
Step 4.1. Configure driver
Step 4.2. Configure driver. Choose virtual backplane
Step 4.3. Configure driver. Choose virtual backplane
Step 4.4. Configure driver. Choose virtual backplane
Step 4.4. Driver is ready
Step 5. Launch RSLogix 5000
Step 6. Create new project and define new controller
Step 6.1. yippee, almost ready
Step 7. Add I/O module to project
Step 7.1. Add I/O module to project. Configure
Step 7.2. Add I/O module to project. Configure
Step 8. For connecting to controller go to `Who Active` 
Step 8. Connecting to controller (Online)
Step 8. Connecting to controller. At first time controller download programm
Step 8.1. Emulation is ready and in Action.
Step 9. Check emulation in RSLogix 5000. Before toggle input bit in I/O module
Step 9.1. Check emulation in RSLogix 5000. After toggle input bit in I/O module. It`s working :)
 
Если у вас будут вопросы, напишите мне, буду рад помочь Вам!

Jquery. Работа с json-данными. Python - версия

В предыдущем посте - Jquery. Работа с json-данными (клиент-серверное взаимодействие) - было показано клиент-серверное взаимодействие в одном направлении: от сервера к клиенту. На стороне сервера отрабатывал скрипт - json.php, но предположим, что у нас есть Apache, например, который "завязан" на python с cgi интерфейсом. Таким образом, нам нужно переписать скрипт: json.php -> json.py. Итак.

json.py:

#!/usr/bin/env python
import MySQLdb
import json

# Параметры (тестовые), необходимые для коннекта к базе данных db_name
server = "localhost"
username = "root"
password = "password"
# Тестовое имя базы данных
dbname = "db_name"
# sql-запрос. Возвращает данные двух работников из одного отдела
sql = "SELECT DISTINCT a.id, a.date, a.staff, a.otdel \
        FROM db_name.tbl_name a, db_name.tbl_name b \
        WHERE a.otdel = b.otdel AND a.id <> b.id \
        ORDER BY a.otdel ASC \
        LIMIT 2"

# Подключение к серверу и базе данных...
db = MySQLdb.connect(server, username, password, dbname)

# Подготовка курсора...
cursor = db.cursor()

# Выполняем sql-запрос к базе данных...
cursor.execute(sql)

# Извлекаем результат запроса в переменную для дальнейшего разбора
result = cursor.fetchall()

# Отключаемся от сервера...
db.close()

# Создаем пустой список из двух пустых словарей
data = [{}, {}]

for i in range(0, 2):
    data[i]['id'] = result[i][0]
    data[i]['date'] = result[i][1]
    data[i]['staff'] = result[i][2]
    data[i]['otdel'] = result[i][3]
   
print("Content-type: application/json\n")

print(json.dumps(data))


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

[{'date': 12032013, 'otdel': 'it', 'id': 16, 'staff': 'developer'}, {'date': 12032013, 'otdel': 'it', 'id': 61, 'staff': 'tester'}] 

Который отправляется в ответ клиенту после обработки методом json.dumps(), в итоге получим:

'[{"date": 12032013, "otdel": "it", "id": 16, "staff": "developer"}, {"date": 12032013, "otdel": "it", "id": 61, "staff": "tester"}]'

Исходник - download.

Jquery. Работа с json-данными (клиент-серверное взаимодействие)

Задачка. Нужно реализовать взаимодействие клиента (user-agent) с сервером (web server) с помощью json-данных, для упрощения - в одном направлении: от сервера к клиенту. При необходимости можно попробовать реализовать и двунаправленность.
Для ясности нужно продумать и представить всю цепочку хода запросов и ответов.



Цепочка запроса и ответа


Решение задачи схематично представлено на рисунке. Ддя клиентской строны имеем - index.html или index.php, для серверной - скрипт json.php. Рассмотрим подробнее:

index.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
                    "
http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; Charset=UTF-8">
  <script src="jquery-1.9.1.js"></script>
  <script>
  $(document).ready(function(){ 
   $('#btn').click(function(){
    // При нажатии кнопочки запрашиваются данные
    // с сервера (скрипт - json.php), при успешном ответе
    // вызывается callback функция function(data)
    // с входными данными data
    $.getJSON('json.php', function(data) {
     // Разбивка входных данных на пару 'ключ=>значение'
     // (соответствующая структура json-данных)
     $.each(data, function(key, value) {
      // При отладке удобно пользоваться методом alert(),
      // можно отслеживать содержимое входных данных
      // alert("value.id = " + value.id +
      //  " value.date = " + value.date +
      //  " value.staff = " + value.staff +
      //  " value.otdel = " + value.otdel);
      // Разбираем полученные данные и формируем
      // для html-представления строку (для отображения табличных данных)
      var table_row = "<tr>" +
            "<td>" + value.id + "</td>" +
            "<td>" + value.date + "</td>" +
            "<td>" + value.staff + "</td>" +
            "<td>" + value.otdel + "</td>" +
          "</tr>";
      // Добавляем сформированную строку table_row в таблицу
      // с идентификатором table_content
      $(table_row).appendTo("#table_content tbody");
     }); 
    });
   });
  });
  </script>
  <style>
   #table_content
   {
   background-color:#00CCFF;
   color:#000000;
   }
  </style>
 </head>
 <body>
  <p>Test page for testing get JSON data from server:</p> 
  <form> 
   <input id="btn" type="button" value="Click me to get json-data">   
  </form>
  <!-- В данной таблице будут отображены полученные данные -->
  <table id="table_content" border="1">
   <thead>
    <th>id</th>
    <th>date</th>
    <th>staff</th>
    <th>otdel</th>
   </thead>
   <tbody>
   </tbody>
  </table>
 </body>
</html>



До нажатия кнопочки таблица (немного не соответствует) пуста

После нажатия заполняется содержимое таблицы


Как видно, на стороне клиента используется js-библиотека jquery. Логика такая. При нажатии кнопочки будет вызван специальный метод $.getJSON('json.php', function(data) {}), который запрашивает данные с сервера (обращение к скриптовой части - json.php), если все хорошо, мы получаем входные данные data, которые далее поступают на вход callback-функции, где непосредственно идет разбор данных и подготовка к последующему html-отображению. В нашем случае - табличное представление. В принципе, здесь ничего сложного.
Теперь рассмотрим скриптовую часть:

json.php

<?#Взаимодействие с клиентом в json-формате
// Параметры (тестовые), необходимые для коннекта к базе данных db_name
$server = "localhost";
$username = "root";
$password = "password";
// Тестовое имя базы данных
$dbname = "db_name";
// sql-запрос. Возвращает данные двух работников из одного отдела
$sql = "SELECT DISTINCT a.id, a.date, a.staff, a.otdel 
  FROM db_name.tbl_name a, db_name.tbl_name b
  WHERE a.otdel = b.otdel AND a.id <> b.id
  ORDER BY a.otdel ASC
  LIMIT 2";
// Подключение к серверу...
mysql_connect($server, $username, $password) or
    die("Connect error: ".mysql_error());
// Подключение к базе данных db_name...
mysql_select_db($dbname);
// Делаем sql-запрос к базе данных и получаем результат...
$result = mysql_query($sql);
// Если запрос отработал и мы получили результат,
// тогда представим сие результат в виде
// ассоциативного массива $row, с последующей
// подготовкой для отправки в json-формате  
if ($result)
 while($row = mysql_fetch_assoc($result))
  $json[] = array('id'=>$row['id'], 'date'=>$row['date'], 'staff'=>$row['staff'], 'otdel'=>$row['otdel']);

else
 die();

// Отправляем подготовленный массив $json (в ответ)
header("Content-type: application/json");
echo json_encode($json);
?>

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

$json = array [
                         0 => array [
                                             "id" => "16",
                                             "date" => "11032013",
                                             "staff" => "developer",
                                             "otdel" => "it"
                                           ],
                        1 => array [
                                            "id" => "61",
                                            "date" => "11032013",
                                            "staff" => "tester",
                                            "otdel" => "it"
                                          ]
                       ]

После обработки методом json_encode() получим следующее (json-данные):

[{
    "id":"16",
    "date":"11032013",
    "staff":"developer",
    "otdel":"it"
  }, {
    "id":"61",
    "date":"11032013",
    "staff":"tester",
    "otdel":"it"
}]

Далее отправляем данные клиенту, не забывая указывать тип содержимого ответа header("Content-type: application/json").

Если нужны исходники, то можно скачать по ссылке - download.
Всем удачи.