Как передать аргументы в main c
В прошлых темах функция main определялась без параметров. Однако также можно определить данную функцию с параметрами:
int main(int argc, char* argv[]) < // инструкции >
Первый параметр, argc , представляет тип int и хранит количество аргументов командной строки. Второй параметр, argv[] , представляет собой массив указателей и хранит все переданные аргументы командной строки в виде строк. Таким образом, благодаря данным параметрам мы можем при вызове программы в консоли передать ей некоторые данные.
Например, определим следующую программу:
#include int main(int argc, char* argv[]) < // выводим все переданные аргументы в цикле for (int i <>; i < argc; ++i) < std::cout >
В данном случае просто выводим все аргументы командной строки на консоль. Скомпилируем и просто запустим программу, не передавая ей никаких аргументов:
c:\cpp>g++ hello.cpp -o hello & hello hello
В моем случае код программы расположен в файле «hello.cpp» и компилируется в файл с именем hello. После запуска программы, даже если мы не передаем ей никакх аргументов, в массиве argv[] будет как минимум один элемент — название файла программы. То есть в моем случае в массиве будет одна строка «hello». А первый параметр, argc , будет равен 1.
Передадим программе какие-нибудь аргументы
c:\cpp>g++ hello.cpp -o hello & hello Tom 38 hello Tom 38
Здесь программе при запуске передается два значения — «Tom» и «38». Передаваемые аргументы разделяются пробелом. Причем даже если передается число (как в случае с вторым аргументом), то программа все равно получает его в виде строки. Соответственно теперь в массиве argv будет три элемента.
Передача аргументов в программу
Бывает, что данные в программу передаются из командной строки при ее вызове. Такие данные называются аргументами командной строки. Выглядит это так, например:
./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, а массив строк определяется как .
Обратите внимание на терминологию, есть всего два аргумента программы (число и массив), но сколько угодно аргументов командной строки. Аргументы командной строки «преобразуются» в аргументы программы (в аргументы функции main() ).
Эти данные (число и указатель) передаются в программу даже тогда, когда она просто вызывается по имени без передачи в нее чего-либо: ./a.out. В таком случае первый аргумент имеет значение 1, а второй указывает на массив, состоящий всего из одной строки .
То, что в программу передаются данные, вовсе не означает, что функция main() должна их принимать. Если функция main() определена без параметров, то получить доступ к аргументам командной строки невозможно. Хотя ничего вам не мешает их передавать. Ошибки не возникнет.
Чтобы получить доступ к переданным в программу данным, их необходимо присвоить переменным. Поскольку аргументы сразу передаются в main() , то ее заголовок должен выглядеть таким образом:
int main(int n, char *arr[])
В первой переменной (n) содержится количество слов, а во второй — указатель на массив строк. Часто второй параметр записывают в виде **arr . Однако это то же самое. Вспомним, что сам массив строк, содержит в качестве своих элементов указатели на строки. А в функцию мы передаем указатель на первый элемент массива. Получается, что передаем указатель на указатель, т.е. **arr .
Напишите такую программу:
#include int main(int argc, char **argv) { int i; printf("%d\n", argc); for (i=0; i argc; i++) puts(argv[i]); }
Она выводит количество слов в командной строке при ее вызове и каждое слово с новой строки. Вызовите ее без аргументов командной строки и с аргументами.
В программе мы использовали переменные-параметры argc и argv. Принято использовать именно такие имена, но на самом деле они могут быть любыми. Лучше придерживаться этого стандарта, чтобы ваши программы были более понятны не только вам, но и другим программистам.
Практическое значение передачи данных в программу
Если у вас есть опыт работы в командной строке GNU/Linux, вы знаете, что у большинства команд есть ключи и аргументы. Например, при просмотре содержимого каталогов, копировании, перемещении в качестве аргументов указываются объекты файловой системы, над которыми выполняется команда. Особенности ее выполнения определяются с помощью ключей. Например, в команде
cp -r ../les_1 ../les_101
cp — это имя команды, -r — ключ, а ../les_1 и ../les_101 — аргументы команды.
Нередко в программы при их запуске передаются адреса файлов и «модификаторы» (это ключи) процесса выполнения программы.
Напишем программу, которая открывает указанные пользователем в командной строке файлы на запись или добавление и записывает (добавляет) туда одну и туже информацию, которую пользователь вводит с клавиатуры в процессе выполнения программы:
#include #include int main (int argc, char **argv) if (strcmp(argv[1], "-w") != 0 && strcmp(argv[1], "-a") != 0) { puts("Первый параметр -w или -a"); return 2; } for (i=0; i argc-2; i++){ f[i] = fopen(argv[i+2], argv[1]+1); if (f[i] == NULL) { printf("Файл %s нельзя открыть\n", argv[i+2]); return 3; } } while ((ch = getchar()) != EOF) for (i=0; i argc-2; i++) putc(ch,f[i]); for (i=0; i argc-2; i++) fclose(f[i]); return 0; }
Пояснения к коду:
- Создается массив из пяти файловых указателей. Следовательно можно одновременно открыть не более пяти файлов. Файловый указатель первого файла будет хранится в элементе массива f[0], второго — в f[1] и т.д.
- Проверяется количество аргументов командной строки. Их должно быть не меньше трех, т.к. первый — это имя программы, второй — режим открытия файла, третий — первый или единственный файл, в который будет производится запись. Поскольку программа позволяет открыть только пять файлов, то общее число аргументов командной строки не может быть больше семи. Поэтому если количество аргументов меньше 3 или больше 7, то программа завершается, т.к. оператор return приводит к выходу из функции, даже если после него есть еще код. Возвращаемое из функции значение неравное 0, может быть интерпретировано родительским процессом, как сообщение о том, что программа завершилась с ошибкой.
- Проверяется корректность второго аргумента командной строки. Если он не равен ни «-w», ни «-a», то условное выражение во втором if возвращает 1 (true). Функция strcmp() позволяет сравнивать строки и возвращает 0 в случае их равенства.
- В цикле for открываются файлы по указанным адресам, которые начинаются с третьего элемента массива argv. Именно поэтому к i прибавляется 2, чтобы получать элементы массива argv, начиная с третьего. Выражение argc-2 указывает на количество переданных имен файлов; т.к. в argc хранится общее число аргументов командной строки, первые два из которых не являются именами файлов.
- Выражение argv[1]+1 позволяет «вырезать» из строки «-w» (или «-a») подстроку «w» (или «a»), т.к. argv[1] по сути указатель на первый элемент строки. Прибавляя к указателю единицу, мы смещаем его к следующему элементу массива.
- Если файл отрыть не удается, то функция fopen() возвращает NULL. В таком случае программа завершается.
- Каждый символ, введенный пользователем с клавиатуры, записывается во все открытые файлы.
- В конце файлы закрываются.
Курс с решением части задач:
pdf-версия
Язык Си в примерах/Использование аргументов командной строки
Программы могут принимать аргументы. Ниже приведен пример программы argv , которая печатает список аргументов, которые были переданы ей в командной строке. Пример ее работы:
bash$ ./argv alpha beta gamma last Argument 0: ./argv Argument 1: alpha Argument 2: beta Argument 3: gamma Argument 4: last
/* Build me with gcc -o argv argv.c */ #include int main (int argc, char * argv[]) int i; for( i = 0 ; i argc; i++) printf("Argument %d: %s\n", i, argv[i]); > if(argc == 1) printf("Command line has no additional arguments\n"); > return 0; >
Например стандартная программа ‘ls’ в Linux в качестве аргумента принимает имена директорий, содержимое которых нужно вывести в стандартный поток вывода. Команда
bash$ ls /home/user
выведет содержимое директории ‘/home/user’.
Команда ‘ls’ имеет множество опций, которые можно передавать в командной строке. О них вы можете узнать, запустив команду ‘ls’ с опцией ‘-h’:
bash$ ls -h
Вообще, программа может получать данные из нескольких источников. Наиболее важные источники это:
- аргументы командной строки;
- стандартный поток ввода;
- файлы;
- средства взаимодействия процессов (signals, sockets, messages, . ).
Научимся использовать первый из них.
Подробнее об аргументах командной строки [ править ]
Основной функцией в программе на языке Си является функция main() . Мы уже познакомились с простейшим способом объявления этой функции:
/* * Простейшая форма main() */ int main() // . return 0; >
Для того, чтобы ваша программа могла анализировать параметры, передаваемые ей через командную строку, функцию main() следует описать несколько сложнее:
/* * main() с обработкой параметров */ int main(int argc, char **argv) // . return 0; >
При такой записи, при вызове вашей программы, параметр argc будет содержать количество параметров командной строки плюс один. Действительные параметры нумеруются с единицы по argc-1 включительно (т.е. всего argc-1 параметров), параметр под номером ноль является служебным — он содержит полный путь и имя исполняемого файла вашей программы.
Для доступа к параметру под номером i следует писать argv[i] . Выражение argv[i] — это строка, передаваемая в соответствии с соглашениями языка Си о строках. С ней можно проделывать все операции, как с обычной строкой (её даже можно модифицировать, но это считается дурным тоном!).
Вот еще один пример программы, работающей со своей командной строкой:
Пример 2 [ править ]
/* * Пример программы, работающей со своей командной строкой */ #include #include int main(int argc, char **argv) if(argc 1) printf("syntax : \n\t%s --help or\n\t./p --add [a] [b]\n", argv[0]); return 0; > if(!strcmp(argv[1], "--help")) printf("You requested help message.\n"); > else if(!strcmp(argv[1], "--add")) if(argc 3) printf("'--add' operation requires two parameters.\n"); > else int a, b; if(sscanf(argv[2], "%d", &a) != 1 || sscanf(argv[3], "%d", &b) != 1) printf("'--add' operation requires two integer parameters.\n"); > else printf("%d + %d = %d\n", a, b, a+b); > > > else printf("Unknown parameter: '%s'. Type %s --help for help.\n", argv[1], argv[0]); > return 0; >
Задачи для самостоятельного решения [ править ]
- Напишите программу, которая интерпретирует свои аргументы как целые числа и выводит на стандартный поток вывода их сумму.
- Напишите программу, которая принимает аргумент — имя файла, и выводит содержимое этого файла.
- в текстовом виде, обозначая не ASCII символы знаками вопроса (если дана опция =-text= );
- в шестнадцатиричном виде (если дана опция =-hex=);
- как есть (по умолчанию).
См. также [ править ]
C – Аргументы командной строки
Можно передать некоторые значения из командной строки вашим программам на Си, когда они выполняются. Эти значения называются аргументами командной строки, и во многих случаях они важны для вашей программы, особенно когда вы хотите управлять своей программой извне, а не жестко кодировать эти значения внутри кода.
Аргументы командной строки обрабатываются с помощью аргументов функции main (), где argc ссылается на количество переданных аргументов, а argv [] – массив указателей, который указывает на каждый аргумент, переданный программе. Ниже приведен простой пример, который проверяет, есть ли какой-либо аргумент из командной строки, и предпринимает соответствующие действия:
#include int main( int argc, char *argv[] ) if( argc == 2 ) printf("The argument supplied is %s\n", argv[1]); > else if( argc > 2 ) printf("Too many arguments supplied.\n"); > else printf("One argument expected.\n"); > >
Когда приведенный выше код компилируется и выполняется с одним аргументом, он дает следующий результат.
$./a.out testing The argument supplied is testing
Когда приведенный выше код компилируется и выполняется с двумя аргументами, он дает следующий результат.
$./a.out testing1 testing2 Too many arguments supplied.
Когда приведенный выше код компилируется и выполняется без передачи аргумента, он дает следующий результат.
$./a.out One argument expected
Следует отметить, что argv [0] содержит имя самой программы, а argv [1] – указатель на первый предоставленный аргумент командной строки, а * argv [n] – последний аргумент. Если аргументы не предоставлены, argc будет один, а если вы передадите один аргумент, argc будет установлен в 2.
Вы передаете все аргументы командной строки, разделенные пробелом, но если сам аргумент имеет пробел, вы можете передать такие аргументы, заключив их в двойные кавычки “” или одинарные кавычки “. Давайте еще раз напишем приведенный выше пример, где мы напечатаем имя программы, а также передадим аргумент командной строки, заключив в двойные кавычки –
#include int main( int argc, char *argv[] ) printf("Program name %s\n", argv[0]); if( argc == 2 ) printf("The argument supplied is %s\n", argv[1]); > else if( argc > 2 ) printf("Too many arguments supplied.\n"); > else printf("One argument expected.\n"); > >
Когда приведенный выше код компилируется и выполняется с одним аргументом, разделенным пробелом, но внутри двойных кавычек, он дает следующий результат.