Навигация
Главная
Поиск
Форум
FAQ's
Ссылки
Карта сайта
Чат программистов

Статьи
-Delphi
-C/C++
-Turbo Pascal
-Assembler
-Java/JS
-PHP
-Perl
-DHTML
-Prolog
-GPSS
-Сайтостроительство
-CMS: PHP Fusion
-Инвестирование

Файлы
-Для программистов
-Компонеты для Delphi
-Исходники на Delphi
-Исходники на C/C++
-Книги по Delphi
-Книги по С/С++
-Книги по JAVA/JS
-Книги по Basic/VB/.NET
-Книги по PHP/MySQL
-Книги по Assembler
-PHP Fusion MOD'ы
-by Kest
Professional Download System
Реклама
Услуги

Автоматическое добавление статей на сайты на Wordpress, Joomla, DLE
Заказать продвижение сайта
Программа для рисования блок-схем
Инженерный калькулятор онлайн
Таблица сложения онлайн
Популярные статьи
OpenGL и Delphi... 65535
Форум на вашем ... 65535
21 ошибка прогр... 65535
HACK F.A.Q 65535
Бип из системно... 65535
Гостевая книга ... 65535
Invision Power ... 65535
Пример работы с... 65535
Содержание сайт... 65535
ТЕХНОЛОГИИ ДОСТ... 65535
Организация зап... 65535
Вызов хранимых ... 65535
Создание отчето... 65535
Имитационное мо... 65535
Программируемая... 65535
Эмулятор микроп... 65535
Подключение Mic... 65535
Создание потоко... 65535
Приложение «Про... 65535
Оператор выбора... 65535
Реклама
Сейчас на сайте
Гостей: 12
На сайте нет зарегистрированных пользователей

Пользователей: 13,363
новичок: xopumun11
Новости
Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ
Delphi, Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog, 3D MAX, Компас 3D
Заказать программу для Windows Mobile, Symbian

Моделирование работы аэропорта на GPSS + Пояснительная записка
Обработка задач на ЭВМ на GPSS + Пояснительная записка
Движение шарика в эллиптическои параболоиде на Delphi [OpenGL] + Блок схемы

Веб-программирование на Cи
Информация
Язык программирования C — это традиционный инструмент разработки программного обеспечения, используемый на протяжении последних 30 лет (с момента появления Unix). С учетом того, что Unix в настоящее время является основной серверной средой, умение программировать CGI-скрипты на C является одним из необходимых условий успешной работы Web-инженера. Вникнув повнимательнее в спецификацию CGI, любой программист поймет, что спецификация создавалась с расчетом на Unix и С. Работа с переменными окружения и потоками стандартного ввода/вывода построена с учетом особенностей среды и средств программирования. При адаптации спецификации CGI в других средах, например, MS-Windows, программирование многих механизмов обмена приходится модифицировать. В данной статье речь пойдет о программировании CGI-скриптов на классическом C без .

Общая структура C-скрипта

Скрипт на языке C ничем не отличается от обычной C-программы. Собственно, это набор процедур, среди которых есть главная процедура. Этой главной процедуре передается управление при загрузке программы в оперативную память. Главная процедура контролирует вызов других процедур и весь ход выполнения программы. Простой скрипт — это одна главная процедура.При разработке С-скрипта следует всегда помнить, что в отличие от скрипта на Bash и Perl, С-скрипт, прежде чем выполнить, нужно еще и откомпилировать, т.е. превратить в исполняемый компьютером код. Если в системе нет компилятора для C, то программировать С-скрипты будет довольно сложно.Синтаксически главная процедура выглядит следующим образом:
#include
#include
void main(argc,argv,env)
int *argc;
char *argv[];
char *env[];
{
/* тело программы */
}



В этом фрагменте представлены все основные элементы программирования CGI-скриптов на С. Строки в начале программы (#include ... ) позволяют включить в текст программы декларации (описатели) стандартных функций. Строка "void main ..." — это объявление главной процедуры. В качестве параметров в данную процедуру (функцию) передаются: число аргументов командной строки — argc;
указатель на массив аргументов командной строки — argv;
указатель на массив переменных окружения — env.
Само тело программы помещается между символами фигурных скобок "{...}". Фраза "тело программы" размещена между парой "/* ... */". Это комментарий. Сама программа на С состоит из операторов. Операторы могут быть простые и составные. Простые операторы – это, например, оператор присваивания. Составной оператор — это блок. Блок представляет собой последовательность операторов, заключенную в фигурные скобки "{...}". В конце простого оператора должен стоять символ ";". В нашем примере объявление (декларирование) переменных перед блоком тела программы — это последовательность простых операторов. Про С часто говорят, что в языке только пять операторов, а все остальное — это библиотека стандартных функций. Операторов в нем, конечно, больше, но такая характеристика в целом верна.

Стандартный поток вывода

Стандартный поток вывода в С ассоциируется с дескриптором STDOUT. Самым распространенным способом записи данных в этот поток является функция форматного вывода printf. Если скрипт должен что-то передать браузеру пользователя, то первое, что нужно сделать — это применить printf для формирования HTTP-заголовка:
main()
{
printf("Content-type: text/html\n\n");
printf("

C и CGI

");
}



Первый вызов printf формирует заголовок — определяет тип тела HTTP-отклика, а второй вызов формирует заглавие первого уровня в HTML-документе. В общем случае у функции printf три аргумента: printf(FILE,"format",VARS_LIST); FILE — дескриптор файла, "format" — формат вывода данных, VARS_LIST — список переменных, чьи значения подлежат выводу. Если дескриптор файла опущен, то вывод направляется в поток стандартного вывода. Список переменных указывается в том случае, если в формате вывода есть шаблоны вывода для переменных из этого списка. Для каждого типа данных в С существует свой шаблон вывода. Перечислим только некоторые из них:
%d — вывод целого числа;
%s — вывод массива символов (строки);
%f — вывод вещественного числа;
%x — вывод целого числа в шестнадцатеричном виде.
Для того, чтобы распечатать аргументы командной строки, можно применить следующий формат:
int i;
...
for(i=0;i {
printf("arg[%d]=%s\n",i,argv[i]);
}




В данном случае переменная цикла i — это целая константа, поэтому в квадратных скобках указано [%d]. Второй аргумент списка переменных — указатель на массив символов (строка, содержащая значение аргумента командной строки), поэтому после знака равенства ("=") применен шаблон вывода массива символов %s.

Переменные окружения

Третий аргумент главной процедуры — указатель на массив переменных окружения, каждый элемент которого представляет собой строковую константу вида "имя-значение". Неудобство работы с этим массивом заключается в том, что заранее не известно, сколько элементов он содержит. Список переменных окружения кончается в тот момент, когда при его переборе встречается указатель NULL. Пример такого перебора представлен ниже:
#include
#include
void main(argc,argv,env)
int argc;
char *argv[];
char *env[];
{
int i;
i=0;
while(env[i])
{
printf("%d:%s\n",i,env[i]);
i++;
}
}




В данном случае перебор идет до тех пор, пока значение указателя больше 0. При этом переменные окружения выдаются в виде "имя:значение". Для того, чтобы воспользоваться этими значениями, придется разбирать каждую строку, выделяя имя и значение переменной при помощи манипуляций с адресами внутри строки. Любые адресные операции — это потенциальные ошибки (хотя они и позволяют писать быстрые программы).К счастью, в С есть функция getenv(). В качестве аргумента этой функции достаточно указать имя переменной окружения, и система вернет указатель на его значение. Например, необходимо знать, сколько символов нужно считать со стандартного ввода скрипта:
int i,n;
char *query;
...
n = atoi(getenv("CONTENT_LENGTH"));
query = (char *) malloc(n+1);
for(i=0;i {
query[i] = getc();
}
...
free(query);




В этом примере при помощи последовательного применения getenv и atoi (ascii to integer) из переменной окружения в переменную целого типа помещается значение переменной окружения — CONTENT_LENGTH. Последовательное применение функций здесь необходимо, т.к. значение переменной окружения — строка, а мы хотим использовать число, следовательно, строку символов следует не только получить, но еще и преобразовать в число. Для преобразования строк в числа часто используют функцию форматного ввода sscanf. В нашем случае это выглядело примерно следующим образом:
char *length;
int n;
...
length = getenv("CONTENT_LENGTH");
sscanf(length,"%d",&n);

...



Следует заметить, что sscanf — это довольно сложная функция. Она предназначена для ввода любой информации и ее преобразования. Как показывает практика, иногда sscanf работает не так, как предполагает программист. Поэтому незачем стрелять из пушки по воробьям — применяйте лучше специализированные функции преобразования, например, atoi, если это возможно.

Аргументы командной строки

Аргументы командной строки передаются в С-скрипт через второй параметр главной процедуры. Второй параметр — массив указателей на строковые константы, которые и есть аргументы командной строки. Число таких аргументов определяется первым параметром главной процедуры. В этом смысле просмотреть все аргументы командной строки можно в цикле for:
#include
#include
main(argc,argv,env)
int argc;
char *argv[];
char *env[];
{
int i;
printf("Content-type: text/plain\n\n");
for(i=0;i {
printf("argv[%d]=%s\n",i,argv[i]);
}
}



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

Стандартный поток ввода

Cчитывать данные в программу на C принято из файлов. При этом файлы ассоциируются с потоками данных. Поток данных — это последовательность октетов (8 бит, или более привычно — байт). Если считывается текстовый файл, то мы имеем дело с последовательностью символов. Если считываем двоичный файл — имеем дело с октетами (байтами). Все функции С, которые работают с файлами ориентированы на эту модель — на потоки данных.С каждым файлом при открытии потока данных связан дескриптор файла, который, являясь совокупностью данных о потоке, описывает поток. Со стандартным потоком ввода в С связывают дескриптор с именем STDIN. Во многих случаях это имя указывать не надо, т.к. оно предполагается по умолчанию. Самый простой способ чтения потока стандартного ввода обеспечивает функция посимвольного чтения getc():
#include
#include
#include
void main(argc,argv,env)
int argc;
char *argv[];
char *env[];
{
char *query;
int length;
length = atoi(getenv("CONTENT_LENGTH"));
query = (char *) malloc(length+1);
memset(query,'\000',length+1);
for(int i=0;i {
query[i] = getc();
}
free(query);
}



Функция getc() доставляет по одному символу из потока стандартного ввода. Не следует думать, что это медленный способ чтения. Во-первых, сервер передает данные через канал (pipe), а во-вторых, поток буферизуется. Поэтому даже посимвольное чтение данных происходит достаточно быстро. Можно прочитать и все данные сразу. Для этого пользуются функцией fread():
#include
#include
#include
void main(argc,argv,env)
int argc;
char *argv[];
char *env[];
{
char *query;
int length;
length = atoi(getenv("CONTENT_LENGTH"));
query = (char *) malloc(length+1);
memset(query,'\000',length+1);
fread(query,length,1,STDIN);
free(query);
}



В данном случае мы читаем из потока стандартного ввода STDIN в буфер query ровно length символов. Последнее замечание. В наших примерах используется функция malloc(). Эта функция отводит память под данные, которые мы считываем со стандартного ввода. После завершения скрипта нужно обязательно освободить эту память, не уповая на то, что после завершения программы вся память все равно освободится. Здесь учитывается два момента. Во-первых, использование такого способа размещения данных связано с попыткой избежать переполнения при использовании областей памяти фиксированной длины, которое приводит к аварийному завершению программы. Во-вторых, при переходе от CGI-скриптов к FastCGI-скриптам это позволяет избежать "утечки" памяти. В FastCGI скрипт не завершается после ответа клиенту, а остается "висеть" в памяти в ожидании следующего запроса. Если память не освободить, то при новом обращении произойдет резервирование новой области памяти. В конечном итоге свободной памяти может и не оказаться.

Типы данных и переменные

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

Целые числа

Целое число декларируется как:
int a;
unsigned int au;
short b;
long c;



Нас интересуют только первые две строки. Последняя строка декларирует длинное целое число. Короткое число попадает в интервал -214<a<214. Если у числа указан модификатор unsigned, то оно попадает в интервал 0<a<215. Одновременно с декларированием число можно проинициализировать, что вообще-то рекомендуется делать всегда:
int a=0,b=0;



Как видно из этого примера, в одном операторе декларирования (объявления) переменных можно указать сразу несколько переменных одного типа и при этом их можно инициализировать. Переменные целого типа необходимы в CGI-программировании при обработке обращений по методу POST. Для того, чтобы считать данные из потока стандартного ввода, нужно указать скрипту, сколько байтов оттуда следует считать. При этом сначала текстовую константу из переменной окружения CONTENT_LENGTH следует преобразовать в число, а затем использовать в операторах чтения или цикла:
#include
#include
void main()
{
char *length,*buf;
int n,i;
length = (char *) getenv("CONTENT_LENGTH");
n = atoi(length);
buf = (char *) malloc(n+1);
memset(buf,'\000',n+1);
for(i=0;i {
buf[i] = getc();
}
printf("Content-type: text/plain\n\n%s\n",
buf);
free(buf);



Функция getenv() позволяет получить значение переменной CONTENT_LENGTH, а функция atoi() — преобразовать это значение в целое число, которое потом используется в качестве границы при посимвольном чтении данных из стандартного потока ввода.

Строки символов

В С нет специального типа данных, который позволял бы работать со строками символов. Для этой цели используются массивы символов. Одиночный символ или массив символов можно объявить через оператор char:
char a='\000';
char buf[];



char buf[20];В первом случае переменная a — это просто одиночный символ. В зависимости от реализации компилятора на него будет отводиться разное число байтов. В наиболее экономичном варианте — 1 байт, если символ отображается на короткое целое — 2 байта, если в архитектуре аппаратной платформы нет числа меньше четырех байтов — на четыре байта. Одним словом, не следует думать, что под символ всегда отводится 1 байт. Символы можно использовать в арифметических операциях:
#include
#include
void main()
{
unsigned char a='a';
a++;
printf("%c\n",a);
}



Опубликовал Kest October 27 2008 12:41:13 · 0 Комментариев · 14321 Прочтений · Для печати

• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •


Страница 1 из 2 1 2 >
Комментарии
Нет комментариев.
Добавить комментарий
Имя:



smiley smiley smiley smiley smiley smiley smiley smiley smiley
Запретить смайлики в комментариях

Введите проверочный код:* =
Рейтинги
Рейтинг доступен только для пользователей.

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

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Поделиться ссылкой
Фолловь меня в Твиттере! • Смотрите канал о путешествияхКак приготовить мидии в тайланде?
Загрузки
Новые загрузки
iChat v.7.0 Final...
iComm v.6.1 - выв...
Visual Studio 200...
CodeGear RAD Stud...
Шаблон для новост...

Случайные загрузки
Microsoft SQL Ser...
SUIPack
Отключение и вклю...
PHP: Полезные приемы
Пример работы с б...
Самоучитель PHP 5...
Rotolabel
DAlarm
BSButton
Секреты программи...
Bitmap [для кнопок]
TMS
PCXReader. Програ...
Win-Prolog 3.618
Последнее загруж...
Голосование для ...
Пишем программы и...
Swing. Эффектные...
Counter [Исходник...
Assembler. Практикум

Топ загрузок
Приложение Клие... 100774
Delphi 7 Enterp... 97831
Converter AMR<-... 20268
GPSS World Stud... 17014
Borland C++Buil... 14191
Borland Delphi ... 10290
Turbo Pascal fo... 7373
Калькулятор [Ис... 5983
Visual Studio 2... 5207
Microsoft SQL S... 3661
Случайные статьи
Поле-шаблон
Типы онлайновой ин...
Обзор уязвимостей ...
Именование объектов
Active Directory— ...
Реализация обобщен...
Грузоперевозки Самара
Степень улучшения ...
Создание баз LSDB ...
Управление целостн...
другого пользователя
Деструктор
Да! При проектиров...
Palladium
Пример ЭС, основан...
Проектирование
Умеете ли вы делат...
Модемы стандарта V.90
Atari 5200 SuperSy...
Различия во встрое...
Настраиваемый клас...
• Negotiate Securi...
Элементы вектора
Сеть CDN
Точная настройка д...
Статистика



Друзья сайта
Программы, игры


Полезно
В какую объединенную сеть входит классовая сеть? Суммирование маршрутов Занимают ли таблицы память маршрутизатора?