Что вам нужно знать об.htaccess. Аргументы функции MAIN()
Бывает, что данные в программу передаются из командной строки при ее вызове. Такие данные называются аргументами командной строки. Выглядит это так, например:
./a.out test.txt ls -lt /home/peter/
Здесь вызываются программы a.out (из текущего каталога) и ls (из одного каталога, указанного в переменной окружения PATH). Первая программа из командной строки получает одно слово - test.txt, вторая - два: -lt и /home/peter/.
Если программа написана на языке C, то при ее запуске управление сразу передается в функцию main() , следовательно, именно она получает аргументы командной строки, которые присваиваются ее переменным-параметрам.
До этого мы определяли функцию main() так, как-будто она не принимает никакие параметры и ничего не возвращает. На самом деле в языке C любая функция по-умолчанию (если не определено ничего иного) возвращает целое число. В этом можно убедиться. Если записать код таким образом:
main() { printf ("Hi\n " ) ; return 0 ; }
То никакого предупреждения или ошибки при компиляции не возникнет. То же самое будет, если записать int main() . Это доказывает, что функция по-умолчанию возвращает целое число, а не ничто (void). Хотя то, что возвращает функция всегда можно "переопределить", например, voidmain() или float main() .
При вызове программы из командной строки в нее всегда передается пара данных:
- целое число , обозначающее количество слов (элементов, разделенных пробелами) в командной строке при вызове,
- указатель на массив строк , где каждая строка - это отдельное слово из командной строки.
Следует иметь в виду, что само имя программы также считается. Например, если вызов выглядит так:
./a.out 12 theme 2
То первый аргумент программы имеет значение 4, а массив строк определяется как {"./a.out", "12", "theme", "2"}.
Обратите внимание на терминологию, есть всего два аргумента программы (число и массив), но сколько угодно аргументов командной строки. Аргументы командной строки "преобразуются" в аргументы программы (в аргументы функции main()).
Эти данные (число и указатель) передаются в программу даже тогда, когда она просто вызывается по имени без передачи в нее чего-либо: ./a.out. В таком случае первый аргумент имеет значение 1, а второй указывает на массив, состоящий всего из одной строки {"./a.out"}.
То, что в программу передаются данные, вовсе не означает, что функция main() должна их принимать. Если функция main() определена без параметров, то получить доступ к аргументам командной строки невозможно. Хотя ничего вам не мешает их передавать. Ошибки не возникнет.
Чтобы получить доступ к переданным в программу данным, их необходимо присвоить переменным. Поскольку аргументы сразу передаются в main() , то ее заголовок должен выглядеть таким образом:
main (int n, char *arr)
В первой переменной (n) содержится количество слов, а во второй - указатель на массив строк. Часто второй параметр записывают в виде **arr . Однако это то же самое. Вспомним, что сам массив строк, содержит в качестве своих элементов указатели на строки. А в функцию мы передаем указатель на первый элемент массива. Получается, что передаем указатель на указатель, т.е. **arr .
Задание
Напишите такую программу:
#include
Она выводит количество слов в командной строке при ее вызове и каждое слово с новой строки. Вызовите ее без аргументов командной строки и с аргументами.
В программе мы использовали переменные-параметры argc и argv. Принято использовать именно такие имена, но на самом деле они могут быть любыми. Лучше придерживаться этого стандарта, чтобы ваши программы были более понятны не только вам, но и другим программистам.
Практическое значение передачи данных в программу
Если у вас есть опыт работы в командной строке GNU/Linux, вы знаете, что у большинства команд есть ключи и аргументы. Например, при просмотре содержимого каталогов, копировании, перемещении в качестве аргументов указываются объекты файловой системы, над которыми выполняется команда. Особенности ее выполнения определяются с помощью ключей. Например, в команде
Cp -r ../les_1 ../les_101
cp - это имя команды, -r - ключ, а../les_1 и../les_101 - аргументы команды.
Вообще чаще всего в программы при их запуске передаются адреса файлов и "модификаторы" (это ключи) процесса выполнения программы.
Напишем программу, которая открывает указанные пользователем в командной строке файлы на запись или добавление и записывает (добавляет) туда одну и туже информацию, которую пользователь вводит с клавиатуры в процессе выполнения программы:
#include
Пояснения к коду:
- Создается массив из пяти файловых указателей. Следовательно можно одновременно открыть не более пяти файлов. Файловый указатель первого файла будет хранится в элементе массива f, второго - в f и т.д.
- Проверяется количество аргументов командной строки. Их должно быть не меньше трех, т.к. первый - это имя программы, второй - режим открытия файла, третий - первый или единственный файл, в который будет производится запись. Поскольку программа позволяет открыть только пять файлов, то общее число аргументов командной строки не может быть больше семи. Поэтому если количество аргументов меньше 3 или больше 7, то программа завершается, т.к. оператор return приводит к выходу из функции, даже если после него есть еще код. Возвращаемое из функции значение неравное 0, может быть интерпретировано родительским процессом, как сообщение о том, что программа завершилась с ошибкой.
- Проверяется корректность второго аргумента командной строки. Если он не равен ни "-w", ни "-a", то условное выражение во втором if возвращает 1 (true). Функция strcmp() позволяет сравнивать строки и возвращает 0 в случае их равенства.
- В цикле for открываются файлы по указанным адресам, которые начинаются с третьего элемента массива argv. Именно поэтому к i прибавляется 2, чтобы получать элементы массива argv, начиная с третьего. Выражение argc-2 указывает на количество переданных имен файлов; т.к. в argc хранится общее число аргументов командной строки, первые два из которых не являются именами файлов.
- Выражение argv+1 позволяет "вырезать" из строки "-w" (или "-a") подстроку "w" (или "a"), т.к. argv по сути указатель на первый элемент строки. Прибавляя к указателю единицу, мы смещаем его к следующему элементу массива.
- Если файл отрыть не удается, то функция fopen() возвращает NULL. В таком случае программа завершается.
- Каждый символ, введенный пользователем с клавиатуры, записывается во все открытые файлы.
- В конце файлы закрываются.
При создании консольного приложения в языке программирования С++, автоматически создается строка очень похожая на эту:
Int main(int argc, char* argv) // параметры функции main()
Эта строка — заголовок главной функции main() , в скобочках объявлены параметры argс и argv. Так вот, если программу запускать через командную строку, то существует возможность передать какую-либо информацию этой программе, для этого и существуют параметры argc и argv . Параметр argc имеет тип данных int , и содержит количество параметров, передаваемых в функцию main . Причем argc всегда не меньше 1, даже когда мы не передаем никакой информации, так как первым параметром считается имя функции. Параметр argv это массив указателей на строки. Через командную строку можно передать только данные строкового типа. Указатели и строки — это две большие темы, под которые созданы отдельные разделы. Так вот именно через параметр argv и передается какая-либо информация. Разработаем программу, которую будем запускать через командную строку Windows, и передавать ей некоторую информацию.
// argc_argv.cpp: определяет точку входа для консольного приложения.
#include "stdafx.h"
#include // код Code::Blocks // код Dev-C++ // argc_argv.cpp: определяет точку входа для консольного приложения.
#include После того как отладили программу, открываем командную строку Windows и перетаскиваем в окно командной строки экзэшник нашей программы, в командной строке отобразится полный путь к программе(но можно прописать путь к программе в ручную), после этого можно нажимать ENTER
и программа запустится (см. Рисунок 1). Рисунок 1 — Параметры функции main Так как мы просто запустили программу и не передавали ей никаких аргументов, появилось сообщение Not arguments . На рисунке 2 изображён запуск этой же программы через командную строку, но уже с передачей ей аргумента Open . Рисунок 2 — Параметры функции main Аргументом является слово Open , как видно из рисунка, это слово появилось на экране. Передавать можно несколько параметров сразу, отделяя их между собой запятой. Если необходимо передать параметр состоящий из нескольких слов, то их необходимо взять в двойные кавычки, и тогда эти слова будут считаться как один параметр. Например, на рисунке изображен запуск программы, с передачей ей аргумента, состоящего из двух слов — It work . Рисунок 3 — Параметры функции main А если убрать кавычки. То увидим только слово It . Если не планируется передавать какую-либо информацию при запуске программы, то можно удалить аргументы в функции main() , также можно менять имена данных аргументов. Иногда встречается модификации параметров argc и argv , но это все зависит от типа создаваемого приложения или от среды разработки. Htaccess - это дополнительный конфигурационный файл Apache, который позволяет настраивать работу веб-сервера для каждой отдельной директории, не влияя на глобальные настройки Apache. Локальная аналогия httpd.conf
. Обычно он отвечает за редиректы и управление доступом к директориям. Название начинается с точки. Можно сказать, это файл без названия с расширением htaccess. Настройки.htaccess действуют на каталог, в котором он расположен, и на все дочерние каталоги. Создайте файл и поместите в нужную вам директорию. Например, в корень проекта. Теперь нужно его наполнить. Посмотрим, что вообще умеет.htaccess, но для начала изучим пример простейшего редиректа. Убедитесь, что в конфигурационном файле Apache httpd.conf
активирован mod_rewrite
. То есть, раскомментирована соответствующая строка: LoadModule rewrite_module modules/mod_rewrite.so Или, если не хотите открывать в текстовом редакторе файл, можно воспользоваться командой в терминале: Sudo a2enmod rewrite mod_rewrite - это модуль Apache, предназначенный для преобразования URL-ов. Рассмотрим на примере, как он работает. Допустим, пользователь вводит следующий адрес: C помощью mod_rewrite можно отправить содержание с другого URL, например такого: Http://www.example.com/public/src/view/page.html Зачем это нам? Легко догадаться, что писать полный путь до страницы долго и просто неудобно. Посетителям сайта не нужно думать о внутренней структуре сайта - им важно максимально быстро попасть на искомую страницу. В адресной строке пользователь будет всё также видеть введенное им: Http://www.example.com/page.html Это пример самого простого редиректа. Разберем конфигурационный файл, используемый в одном из наших проектов. Так мы будем понимать, какую строчку править в случае возникновения проблем. Php_value short_open_tag 1
php_value upload_max_filesize 10M
php_value post_max_size 10M
RewriteEngine On
RewriteBase /
RewriteRule ^(application|modules|system) -
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php/$0 Php_value/php_flag имя_директивы_php flag/value Директива short_open_tag
разрешает использование короткого синтаксиса для оформления PHP-кода: Php_value short_open_tag 1 upload_max_filesize
определяет максимальный размер загружаемого файла. Php_value upload_max_filesize 10M А post_max_size
устанавливает максимально допустимый размер данных, отправляемых методом POST. Php_value post_max_size 10M Включает/выключает механизм mod_rewrite
. RewriteEngine On RewriteRule просто преобразовывает строку в соответствии с регулярными выражениями. Синтаксис:
RewriteRule regular_expression # На входе RewriteRule "index.php"
RewriteRule ^index.php main.php [R]
# На выходе: "index.php" -> "main.php" Мы преобразовали index.php в main.php и выполнили редирект. Важно
: RewriteRule обычно принимает два аргумента: что
нужно заменить и на что
нужно заменить. Если нам не нужно выполнять замену то можно записать в виде: Символ «-» означает «не преобразовывать» После всех RewriteRule, в силу вступает RewriteBase. Если получившийся после преобразований запрос является относительным и отличается от исходного, RewriteBase восстановит его, сделав абсолютным. RewriteBase просто допишет себя к запросу слева. Потому что значение RewriteBase - путь от корня сайта до.htaccess. В нашем случае.htaccess лежит прямо в корне, поэтому: Синтаксис
: RewriteBase URL-path-from-.htaccess-file-to-site-root Например: # .htaccess находится в /dir/
# Путь от корня сайта до.htaccess /dir/
RewriteBase /dir/
# Запрос http://example.com/dir/logo.gif
# На вход RewriteRule попадает "logo.gif"
RewriteRule ^logo.gif$ logo-orange.gif
# После RewriteRule: "logo.gif" -> "logo-orange.gif"
# После RewriteBase: "logo-orange.gif" -> "/dir/logo-orange.gif" Регулярные выражения, которые вам могут встретиться в.htaccess. Также может быть использовано для Back-Reference
(смотри пример)
Back-Reference example:
RewriteRule ^/(+)
/(.*)
$ /home?page=$1
&id=$2
/album/123 → /home?page=album
&id=123
Больше regular expressions Синтаксис
: RewriteRule regular_expression [флаг1,флаг2,флаг3] Borland С++ поддерживает три аргумента main(). Первые два - это традиционные argc и argv. Это единственные аргументы функции main(), определяемые стандартом ANSI С. Они позволяют передавать аргументы командной строки в программу. Аргументы командной строки - это информация, следующая за именем программы в командной строке операционной системы. Например, когда программа компилируется с помощью строчного компилятора Borland, набирается, как правило, bcc имя_ программы
Где имя_программы
- это программа, которую необходимо откомпилировать. Имя программы передается компилятору в качестве аргумента. Параметр argc содержит число аргументов командной строки и является целым числом. Он всегда равен, по крайней мере, 1, поскольку имя программы квалифицируется как первый аргумент. Параметр argv - это указатель на массив символьных указателей. Каждый элемент данного массива указывает на аргумент командной строки. Все аргументы командной строки - это строки. Все числа конвертируются программой во внутренний формат. Следующая программа выводит «Hello», а затем имя пользователя, если его набрать прямо за именем программы:
#include Если назвать данную программу name, а имя пользователя Сергей, то для запуска программы следует набрать: Аргументы командной строки должны отделяться пробелами или табуляциями. Запятые, точки с запятыми и им подобные символы не рассматриваются как разделители. Например: Состоит из трех строк, в то время как Herb,Rick,Fred Это одна строка - запятые не являются разделителями. Если необходимо передать строку, содержащую пробелы или табуляции в виде одного аргумента, следует ее заключить в двойные кавычки. Например, это один аргумент:
"this is a test" Важно правильно объявить argv. Наиболее типичным методом является: Пустые скобки указывают на то, что массив не имеет фиксированной длины. Можно получить доступ к отдельным элементам с помощью индексации argv. Например, argv указывает на первую строку, всегда содержащую имя программы. argv указывает на следующую строку и так далее. Ниже приведен небольшой пример по использованию аргументов командной строки. Он отсчитывает в обратном порядке от значения, указанного в командной строке, и при достижении нуля подает сигнал. Обратим внимание, что первый аргумент содержит число, преобразованное в целое число с использованием стандартной функции atoi(). Если в качестве второго аргумента присутствует строка "display", то на экране будет отображаться сам счетчик.
/* программа отсчета */
#include Обратим внимание, что если не указаны аргументы, появляется сообщение об ошибке. Это наиболее типично для программ, использующих аргументы командной строки для выдачи инструкций, если была попытка запустить программу без правильной информации. Для доступа к отдельным символам командной строки следует добавить второй индекс к argv. Например, следующая программа выводит все аргументы, с которыми она вызывалась, по одному символу за раз:
#include Надо помнить, что первый индекс предназначен для доступа к строке, а второй - для доступа к символу строки. Обычно argc и argv используются для получения исходных команд. Теоретически можно иметь до 32767 аргументов, но большинство операционных систем не позволяют даже близко подойти к этому. Обычно данные аргументы используются для указания имени файла или опций. Использование аргументов командной строки придает программе профессиональный вид и допускает использование программы в командных файлах. Если подсоединить файл WILDARGS.OBJ, поставляемый с Borland С++, то можно будет использовать шаблоны в аргументах типа *.EXE. (Borland С++ автоматически обрабатывает шаблоны и соответствующим образом увеличивает argc.) Например, если подсоединить к следующей программе WILDARGS.OBJ, она выдаст, сколько файлов соответствует имени указанного в командной строке файла:
/* Скомпонуйте данную программу с WILDARGS.OBJ */
#include Если назвать данную программу WA, затем запустить ее как указано ниже, получим число файлов, имеющих расширение ЕХE, и список имен этих файлов: Помимо argc и argv Borland С++ также предоставляет третий аргумент командной строки -env. Параметр env позволяет программе получить доступ к информации о среде операционной системы. Параметр env должен следовать за argc и argv и объявляется следующим образом: Как можно видеть, env объявляется так же, как и argv. Так же, как и argv, это указатель на массив строк. Каждая строка - это строка среды, определенная операционной системой. Параметр env не имеет аналога параметра argc, который сообщал бы, сколько имеется строк среды. Вместо этого последняя строка среды нулевая. Следующая программа выводит все строки среды, определенные на текущий момент в операционной системе:
/* данная программа выводит все строки окружения */
#include Обратим внимание, что хотя argc и argv не используются программой, они должны присутствовать в списке параметров. С не знает имена параметров. Вместо этого их использование определяется по порядку объявления параметров. Фактически можно обозвать параметр как угодно. Поскольку argc, argv и env - это традиционные имена, то лучше их использовать и далее, чтобы любой человек, читающий программу, мог мгновенно понять, что это аргументы функции main(). Для программ типичной задачей является поиск значения, определенного в строке среды. Например, содержимое строки PATH позволяет программам использовать пути поиска. Следующая программа демонстрирует, как найти строки, объявляющие стандартные пути поиска. Она использует стандартную библиотечную функцию strstr(), имеющую следующий прототип: Char *strstr(const char *str1, const char *str2); Функция strstr() ищет строку, на которую указывает str1 в строке, на которую указывает str2. Если такая строка найдена, то возвращается указатель на первое положение. Если не найдено соответствий, то функция возвращает NULL.
/* программа ищет среди строк окружения строку, содержащую PATH */
#include mod_rewrite и редиректы
Сразу к практике
Общий синтаксис директив
RewriteEngine
RewriteRule
RewriteBase
Regular expressions
Символ
Значение
Пример
.
Один любой
символ
c.t
это cat
, cot
, cut
, и т. д.
+
Один или несколько одинаковых
символов
a+
это a
, aa
, aaa
, и т. д.
*
Ноль
или несколько одинаковых
символов
a*
работает также как и a+
но в случае a*
условию удовлетворит и пустая строка
?
Совпадение опционально
colou?r
подойдет как color
, так и colour
.
^
Символ, с которого начинается
строка
^a
соответствует строка, которая начинается с a
$
Символ, которым заканчивается
строка
a$
соответствует строка, которая заканчивается a
.
()
Находит и запоминает соответствие группы
символов.
(ab)+
удовлетворит ababab
Один из
возможных символов
ct
подойдет cut
, cot
или
cat
.
Флаги
Флаг
Описание
[F]
Forbidden
- возвращает ошибку 403 Forbidden (запрещено).
[L]
Last
- остановить процесс преобразования на этом месте и не применять больше никаких правил преобразований.
Query String Append
- этот флаг указывает механизму преобразований на добавление, а не замену
, строки запроса из URL к существующей, в строке подстановки.
PassThrough
- останавливает процесс преобразования и передает полученную новую ссылку дальше по цепочке.
[R]
Redirect
- останавливает процесс преобразования и возвращает результат браузеру клиента как редирект на новую страницу.
[S]
Skip
- пропускает следующее правило, если текущее правило сработало. Можно указать количество последующих игнорируемых правил .
{
if(argc!=2)
{
printf ("You forgot to type your name\n");
return 1;
}
printf("Hello %s", argv);
return 0;
}
name Сергей.
В результате работы программы появится:
«Hello Сергей».
#include
# include
int main(int argc, char *argv)
{
int disp, count;
if(argc<2)
{
printf("You must enter the length of the count\n");
printf ("on the command line. Try again.\n");
return 1;
}
if (argc==3 && !strcmp(argv,"display")) disp = 1;
else disp = 0;
for(count=atoi(argv); count; -count)
if (disp) printf("%d ", count);
printf("%c", "\a"); /* на большинстве компьютеров это звонок */
return 0;
}
int main(int argc, char *argv)
{
int t, i;
for(t=0; t
i = 0;
while(argv[t][i])
{
printf("%c", argv[t][i]);
}
printf (" ");
}
return 0;
}
int main(int argc, char *argv)
{
register int i;
printf("%d files match specified name\n", argc-1);
printf("They are: ");
for(i=1; i
return 0;
}
int main(int argc, char *argv, char *env)
{
int t;
for(t=0; env[t]/ t++)
printf("%s\n", env[t]);
return 0;
}
#include
int main (int argc, char *argv, char *env)
{
int t;
for(t=0; env[t]; t++)
{
if(strstr(env[t], "PATH"))
printf("%s\n", env[t]);
}
return 0;
}