Передача аргументов методу Main() 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Передача аргументов методу Main()



Многие программы принимают так называемые аргументы командной строки, т.е. информацию, которая указывается в командной строке непосредственно после имени программы при ее запуске на выполнение. В программах на C# такие аргумен­ты передаются затем методу Main(). Для получения аргументов служит одна из при­веденных ниже форм метода Main ().

static void Main(string[ ] args)

static int Main(string[ ] args)

В первой форме метод Main() возвращает значение типа void, а во второй - це­лое значение, как пояснялось выше. Но в обеих формах аргументы командной строки сохраняются в виде символьных строк в массиве типа string, который передается ме­тоду Main(). Длина этого массива (args) должна быть равна числу аргументов ко­мандной строки, которое может быть и нулевым.

В качестве примера ниже приведена программа, выводящая все аргументы команд­ной строки, вместе с которыми она вызывается.

Листинг 8.27

// Вывести все аргументы командной строки.

 

using System;

 

class CLDemo

{

static void Main(string[] args) {

Console.WriteLine("Командная строка содержит " +

args.Length +

" аргумента.");

 

Console.WriteLine("Вот они: ");

for(int i=0; i < args.Length; i++)

Console.WriteLine(args[i]);

}

}

Если программа CLDemo запускается из командной строки следующим образом:

CLDemo один два три

то ее выполнение дает такой результат.

Командная строка содержит 3 аргумента.

Вот они: один два три

Для того чтобы стало понятнее, каким образом используются аргументы командной строки, рассмотрим еще один пример программы, в которой применяется простой подстановочный шифр для шифровки или расшифровки сообщений. Шифруемое или расшифровываемое сообщение указывается в командной строке. Применяемый шифр действует довольно просто. Для шифровки слова значение каждой его буквы инкрементируется на 1. Следовательно, Буква "А" становится буквой "Б" и т.д. А для расшифровки слова значение каждой его буквы декрементируется на 1. Разумеется, такой шифр не имеет никакой практической ценности, поскольку его нетрудно раз­гадать. Тем не менее он может стать приятным развлечением для детей.

Листинг 8.28

// Зашифровать и расшифровать сообщение, используя

// простой подстановочный шифр.

 

using System;

 

class Cipher

{

public static int Main(string[] args)

{

 

// Проверить наличие аргументов.

if(args.Length < 2)

{

Console.WriteLine("Применение: " +

"слово1: <зашифровать>/<расшифровать> " +

"[слово2... словоN]");

return 1; // возвратить код неудачного завершения программы

}

 

// Если аргументы присутствуют, то первым аргументом должно быть

// слово <зашифровать> или же слово <расшифровать>.

if(args[0]!= "зашифровать" & args[0]!= "расшифровать")

{

Console.WriteLine("Первым аргументом должно быть слово " +

"<зашифровать> или <расшифровать>.");

return 1; // возвратить код неудачного завершения программы

}

 

// Зашифровать или расшифровать сообщение.

for(int n=1; n < args.Length; n++) {

for(int i=0; i < args[n].Length; i++) {

if(args[0] == "зашифровать")

Console.Write((char) (args[n][i] + 1));

else

Console.Write((char) (args[n][i] - 1));

}

Console.Write(" ");

}

 

Console.WriteLine();

 

return 0;

}

}

Для того чтобы воспользоваться этой программой, укажите в командной строке имя программы, затем командное слово "зашифровать" или "расшифровать" и далее сообщение, которое требуется зашифровать или расшифровать. Ниже приведены два примера выполнения данной программы, при условии, что она называется Cipher.

C:\Cipher зашифровать один два

пейо егб

 

C:\Cipher расшифровать пейо егб

один два

Данная программа отличается двумя интересными свойствами. Во-первых, обра­тите внимание на то, как в ней проверяется наличие аргументов командной строки перед тем, как продолжить выполнение. Это очень важное свойство, которое можно обобщить. Если в программе принимается во внимание наличие одного или более ар­гументов командной строки, то в ней должна быть непременно организована проверка факта передачи ей предполагаемых аргументов, иначе программа будет работать не­правильно. Кроме того, в программе должна быть организована проверка самих ар­гументов перед тем, как продолжить выполнение. Так, в рассматриваемой здесь про­грамме проверяется наличие командного слова "зашифровать" или "расшифровать" в качестве первого аргумента командной строки.

И во-вторых, обратите внимание на то, как программа возвращает код своего завер­шения. Если предполагаемые аргументы командной строки отсутствуют или указаны неправильно, программа возвращает код 1, указывающий на ее аварийное завершение. В противном случае возвращается код 0, когда программа завершается нормально.

Рекурсия

В C# допускается, чтобы метод вызывал самого себя. Этот процесс называется рекур­сией, а метод, вызывающий самого себя, - рекурсивным. Вообще, рекурсия представля­ет собой процесс, в ходе которого нечто определяет самое себя. В этом отношении она чем-то напоминает циклическое определение. Рекурсивный метод отличается главным образом тем, что он содержит оператор, в котором этот метод вызывает самого себя. Рекурсия является эффективным механизмом управления программой.

Классическим примером рекурсии служит вычисление факториала числа. Факто­риал числа N представляет собой произведение всех целых чисел от 1 до N. Напри­мер, факториал числа 3 равен 1´2´3, или 6. В приведенном ниже примере программы демонстрируется рекурсивный способ вычисления факториала числа. Для сравнения в эту программу включен также нерекурсивный вариант вычисления факториала числа.

Листинг 8.29

// Простой пример рекурсии.

 

using System;

 

class Factorial

{

// Это рекурсивный метод.

public int FactR(int n)

{

int result;

 

if(n==1) return 1;

result = FactR(n-1) * n;

return result;

}

 

// Это итерационный метод.

public int FactI(int n)

{

int t, result;

 

result = 1;

for(t=1; t <= n; t++) result *= t;

return result;

}

}

 

class Recursion

{

static void Main() {

Factorial f = new Factorial();

 

Console.WriteLine("Факториалы, рассчитанные рекурсивным методом.");

Console.WriteLine("Факториал числа 3 равен " + f.FactR(3));

Console.WriteLine("Факториал числа 4 равен " + f.FactR(4));

Console.WriteLine("Факториал числа 5 равен " + f.FactR(5));

Console.WriteLine();

 

Console.WriteLine("Факториалы, рассчитанные итерационным методом.");

Console.WriteLine("Факториал числа 3 равен " + f.FactI(3));

Console.WriteLine("Факториал числа 4 равен " + f.FactI(4));

Console.WriteLine("Факториал числа 5 равен " + f.FactI(5));

}

}

При выполнении этой программы получается следующий результат.

Факториалы, рассчитанные рекурсивным методом.

Факториал числа 3 равен 6

Факториал числа 4 равен 24

Факториал числа 5 равен 120

 

Факториалы, рассчитанные итерационным методом.

Факториал числа 3 равен 6

Факториал числа 4 равен 24

Факториал числа 5 равен 120

Принцип действия нерекурсивного метода FactI() вполне очевиден. В нем ис­пользуется цикл, в котором числа, начиная с 1, последовательно умножаются друг на друга, постепенно образуя произведение, дающее факториал.

А рекурсивный метод FactR() действует по более сложному принципу. Если ме­тод FactR() вызывается с аргументом 1, то он возвращает значение 1. В противном случае он возвращает произведение FactR(n-1)*n. Для вычисления этого произве­дения метод FactR() вызывается с аргументом n-1. Этот процесс повторяется до тех пор, пока значение аргумента n не станет равным 1, после чего из предыдущих вызовов данного метода начнут возвращаться полученные значения. Например, когда вычисля­ется факториал числа 2, то при первом вызове метода FactR() происходит второй его вызов с аргументом 1. Из этого вызова возвращается значение 1, которое затем умно­жается на 2 (первоначальное значение аргумента п). В итоге возвращается результат 2, равный факториалу числа 2 (1*2). Было бы любопытно ввести в метод FactR() опе­раторы, содержащие вызовы метода WriteLine(), чтобы наглядно показать уровень рекурсии при каждом вызове метода FactR(), а также вывести промежуточные ре­зультаты вычисления факториала заданного числа.

Когда метод вызывает самого себя, в системном стеке распределяется память для новых локальных переменных и параметров, и код метода выполняется с этими новы­ми переменными и параметрами с самого начала. При рекурсивном вызове метода не создается его новая копия, а лишь используются его новые аргументы. А при возврате из каждого рекурсивного вызова старые локальные переменные и параметры извле­каются из стека, и выполнение возобновляется с точки вызова в методе. Рекурсивные методы можно сравнить по принципу действия с постепенно сжимающейся и затем распрямляющейся пружиной.

Ниже приведен еще один пример рекурсии для вывода символьной строки в об­ратном порядке. Эта строка задается в качестве аргумента рекурсивного метода DisplayRev().

Листинг 8.30

// Display a string in reverse by using recursion.

 

using System;

 

class RevStr {

 

// Вывести символьную строку в обратном порядке, используя рекурсию.

public void DisplayRev(string str)

{

if(str.Length > 0)

DisplayRev(str.Substring(1, str.Length-1));

else

return;

 

Console.Write(str[0]);

}

}

 

class RevStrDemo {

static void Main() {

string s = "Это тест";

RevStr rsOb = new RevStr();

 

Console.WriteLine("Исходная строка: " + s);

 

Console.Write("Перевернутая строка: ");

rsOb.DisplayRev(s);

 

Console.WriteLine();

}

}

Вот к какому результату приводит выполнение этого кода.

Исходная строка: Это тест

Перевернутая строка: тсет отЭ

Всякий раз, когда вызывается метод DisplayRev(), в нем происходит проверка длины символьной строки, представленной аргументом str. Если длина строки не равна нулю, то метод DisplayRev() вызывается рекурсивно с новой строкой, кото­рая меньше исходной строки на один символ. Этот процесс повторяется до тех пор, пока данному методу не будет передана строка нулевой длины. После этого начнет­ся раскручиваться в обратном порядке механизм всех рекурсивных вызовов метода DisplayRev(). При возврате из каждого такого вызова выводится первый символ строки, представленной аргументом str, а в итоге вся строка выводится в обратном порядке.

Рекурсивные варианты многих процедур могут выполняться немного медленнее, чем их итерационные эквиваленты из-за дополнительных затрат системных ресурсов на неоднократные вызовы метода. Если же таких вызовов окажется слишком много, то в конечном итоге может быть переполнен системный стек. А поскольку параметры и локальные переменные рекурсивного метода хранятся в системном стеке и при каж­дом новом вызове этого метода создается их новая копия, то в какой-то момент стек может оказаться исчерпанным. В этом случае возникает исключительная ситуация, и общеязыковая исполняющая среда (CLR) генерирует соответствующее исключение. Но беспокоиться об этом придется лишь в том случае, если рекурсивная процедура выполняется неправильно.

Главное преимущество рекурсии заключается в том, что она позволяет реализовать некоторые алгоритмы яснее и проще, чем итерационным способом. Например, ал­горитм быстрой сортировки довольно трудно реализовать итерационным способом. А некоторые задачи, например искусственного интеллекта, очевидно, требуют именно рекурсивного решения.

При написании рекурсивных методов следует непременно указать в соответству­ющем месте условный оператор, например if, чтобы организовать возврат из мето­да без рекурсии. В противном случае возврата из вызванного однажды рекурсивного метода может вообще не произойти. Подобного рода ошибка весьма характерна для реализации рекурсии в практике программирования. В этом случае рекомендуется пользоваться операторами, содержащими вызовы метода WriteLine(), чтобы сле­дить за происходящим в рекурсивном методе и прервать его выполнение, если в нем обнаружится ошибка.



Поделиться:


Последнее изменение этой страницы: 2016-12-30; просмотров: 315; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 52.91.84.219 (0.061 с.)