Навигация
Главная
Поиск
Форум
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
HACK F.A.Q 65535
Гостевая книга ... 65535
Содержание сайт... 65535
Вызов хранимых ... 65535
Эмулятор микроп... 65535
Бип из системно... 65056
Организация зап... 60830
Приложение «Про... 60685
Invision Power ... 60442
Оператор выбора... 59524
Модуль Forms 58524
Подключение Mic... 58443
Создание отчето... 58001
ТЕХНОЛОГИИ ДОСТ... 54265
Программируемая... 52704
Пример работы с... 50773
Имитационное мо... 49698
21 ошибка прогр... 44645
Реклама
Сейчас на сайте
Гостей: 6
На сайте нет зарегистрированных пользователей

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

Калькулятор на Delphi с переводом в другую систему исчисления + Блок схемы
Изменения контуров и сортировка в двумерном массиве чисел на Turbo Pasca...
Моделирование работы обрабатывающего участка цеха в GPSS

Реклама



Подписывайся на YouTube канал о программировании, что бы не пропустить новые видео!

ПОДПИСЫВАЙСЯ на канал о программировании

Веб-программирование на 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 15:41:13 · 0 Комментариев · 11459 Прочтений · Для печати

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


Страница 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...
Шаблон для новост...

Случайные загрузки
Векторный редакто...
Моделирование дви...
EMS QuickExport S...
ActiveX в Delphi
PDJ_Anima
KOL & MCK v1.69
Х. М. Дейтел, П. ...
DelphiXIsoDemo1
Простой пример ка...
WinAmp
3D Октаэдр
Модифицированная ...
PrevInst
Иллюстрированный ...
Работа с базами д...
Создание фракталов
Delphi и технолог...
Delphi Russian Kn...
Алгоритм трассиро...
FileFind

Топ загрузок
Приложение Клие... 100346
Delphi 7 Enterp... 80925
Converter AMR<-... 20031
Borland C++Buil... 10885
GPSS World Stud... 9994
Borland Delphi ... 7925
Turbo Pascal fo... 6930
Visual Studio 2... 4937
Калькулятор [Ис... 4185
FreeSMS v1.3.1 3494
Случайные статьи
Запись видео на ф...
Сканирование фотог...
Разделение абонент...
Все типы в С++ дел...
Модернизация сете...
Проверка существов...
• Распространите S...
подпись ко всем по...
Формат NdefRecord
Адаптация встроенн...
Запуск просмотрщика
Класс TTalk
Просмотр состояния...
Поле "Скрытая" при...
4.5. РЕШЕНИЕ: СПЕЦ...
Класс TGraphic
Взаимнооднозначное...
Общность в поведении
Windows: щелкните ...
Линии границы
Служба самостоятел...
Описание внешних ф...
Взаимодействие Тур...
Активация
Телевидение и Web
Статистика



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


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