Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Функция main(): разбор параметров командной строки
При запуске программы мы, как правило, передаем ей информацию в командной строке. Например, можно написать prog -d -o of lie dataO Фактические параметры являются аргументами функции main() и могут быть получены из массива C-строк с именем argv; мы покажем, как их использовать. Во всех предыдущих примерах определение main() содержало пустой список: int main() {... } Развернутая сигнатура main() позволяет получить доступ к параметрам, которые были заданы пользователем в командной строке: int main( int argc, char *argv[] ){...} argc содержит их количество, а argv – C-строки, представляющие собой отдельные значения (в командной строке они разделяются пробелами). Скажем, при запуске команды prog -d -o ofile data0 argc получает значение 5, а argv включает следующие строки:
argv[ 0 ] = " prog"; argv[ 1 ] = " -d"; argv[ 2 ] = " -o"; argv[ 3 ] = " ofile"; argv[ 4 ] = " dataO";
В argv[0] всегда входит имя команды (программы). Элементы с индексами от 1 до argc-1 служат параметрами. Посмотрим, как можно извлечь и использовать значения, помещенные в argv. Пусть программа из нашего примера вызывается таким образом: prog [-d] [-h] [-v] [-o output_file] [-l limit_value] file_name [ file_name [file_name [... ]]] Параметры в квадратных скобках являются необязательными. Вот, например, запуск программы с их минимальным количеством – одним лишь именем файла: prog chap1.doc Но можно запускать и так:
prog -l 1024 -o chap1-2.out chapl.doc chap2.doc prog d chap3.doc prog -l 512 -d chap4.doc При разборе параметров командной строки выполняются следующие основные шаги: 1. По очереди извлечь каждый параметр из argv. Мы используем для этого цикл for с начальным индексом 1 (пропуская, таким образом, имя программы): for ( int ix = 1; ix < argc; ++ix ) { char *pchar = argv[ ix ]; //... } 2. Определить тип параметра. Если строка начинается с дефиса (-), это одна из опций { h, d, v, l, o}. В противном случае это может быть либо значение, ассоциированное с опцией (максимальный размер для -l, имя выходного файла для -o), либо имя входного файла. Чтобы определить, начинается ли строка с дефиса, используем инструкцию switch: switch ( pchar[ 0 ] ) { case '-': { // -h, -d, -v, -l, -o }
default: { // обработаем максимальный размер для опции -1 // имя выходного файла для -o // имена входных файлов... } } Реализуем обработку двух случаев пункта 2. Если строка начинается с дефиса, мы используем switch по следующему символу для определения конкретной опции. Вот общая схема этой части программы:
Опция -d задает необходимость отладки. Ее обработка заключается в присваивании переменной с объявлением bool debug_on = false; значения true: case 'd': debug_on = true; break; В нашу программу может входить код следующего вида: if ( debug_on ) display_state_elements( obj ); Опция -v выводит номер версии программы и завершает исполнение:
case 'v': cout < < program_name < < ":: " < < program_version < < endl; return 0; Опция -h запрашивает информацию о синтаксисе запуска и завершает исполнение. Вывод сообщения и выход из программы выполняется функцией usage(): case 'h': // break не нужен: usage() вызывает exit() usage(); Опция -o сигнализирует о том, что следующая строка содержит имя выходного файла. Аналогично опция -l говорит, что за ней указан максимальный размер. Как нам обработать эти ситуации? Если в строке параметра нет дефиса, возможны три варианта: параметр содержит имя выходного файла, максимальный размер или имя входного файла. Чтобы различать эти случаи, присвоим true переменным, отражающим внутреннее состояние: // если ofi1e_on==true, // следующий параметр - имя выходного файла bool ofi1e_on = false;
// если ofi1e_on==true, // следующий параметр - максимальный размер bool limit_on = false; Вот обработка опций -l и -o в нашей инструкции switch: case 'l': limit_on = true; break;
case 'o': ofile_on = true; break; Встретив строку, не начинающуюся с дефиса, мы с помощью переменных состояния можем узнать ее содержание:
Если аргумент является именем выходного файла, сохраним это имя и выключим ofile_on: if ( ofile_on ) { ofile_on = false; ofile = pchar; } Если аргумент задает максимальный размер, мы должны преобразовать строку встроенного типа в представляемое ею число. Сделаем это с помощью стандартной функции atoi(), которая принимает строку в качестве аргумента и возвращает int (также существует функция atof(), возвращающая double). Для использования atoi() включим заголовочный файл ctype.h. Нужно проверить, что значение максимального размера неотрицательно и выключить limit_on: // int limit; else if ( limit_on ) { limit_on = false; limit = atoi( pchar ); if ( limit < 0 ) { cerr < < program_name < < ":: " < < program_version < < " : error: " < < " negative value for limit.\n\n"; usage( -2 ); } } Если обе переменных состояния равны false, у нас есть имя входного файла. Сохраним его в векторе строк:
else file_names.push_back( string( pchar )); При обработке параметров командной строки важен способ реакции на неверные опции. Мы решили, что задание отрицательной величины в качестве максимального размера будет фатальной ошибкой. Это приемлемо или нет в зависимости от ситуации. Также можно распознать эту ситуацию как ошибочную, выдать предупреждение и использовать ноль или какое-либо другое значение по умолчанию. Слабость нашей реализации становится понятной, если пользователь небрежно относится к пробелам, разделяющим параметры. Скажем, ни одна из следующих двух строк не будет обработана: prog - d dataOl prog -oout_file dataOl (Оба случая мы оставим для упражнений в конце раздела.) Вот полный текст нашей программы. (Мы добавили инструкции печати для трассировки выполнения.)
} a.out -d -l 1024 -o test_7_8 chapter7.doc chapters.doc Вот трассировка обработки параметров командной строки:
демонстрация обработки параметров в командной строке: argc: 8 argv[ 1 ]: -d встретился '-' встретилась -d: отладочная печать включена argv[ 2 ]: -l встретился '-' встретилась -l: ограничение ресурса argv[ 3 ]: 1024 default: параметр без дефиса: 1024 argv[ 4 ]: -o встретился '-' встретилась -o: выходной файл argv[ 5 ]: test_7_8 default: параметр без дефиса: test_7_8 argv[ 6 ]: chapter7.doc default: параметр без дефиса: chapter7.doc argv[ 7 ]: chapter8.doc default: параметр без дефиса: chapter8.doc Заданное пользователем значение limit: 1024 Заданный пользователем выходной файл: test_7_8 Файлы, подлежащий(е) обработке: chapter7.doc chapter8.doc
|
Последнее изменение этой страницы: 2019-04-09; Просмотров: 305; Нарушение авторского права страницы