Программирование для чайников

Здравствуйте, мальчики и девочки! Сегодня я расскажу вам, как сделать первые шаги на поприще программирования. Я не буду рассказывать про выбор первого языка, с какой книги начать, как пройти собеседование. Это все не важно. Я помогу вам написать вашу первую программу.

Как-то так получилось, что, работая разработчиком в нашей компании, мне приходилось давать уроки программирования двум нашим заказчикам. Пару лет назад я пытался научить программированию свою девушку. В студенческие годы мне не раз приходилось помогать своим друзьям. И все они страдали от одной и той же проблемы. Они пытались написать все и сразу, а потом искать ошибки и думать, почему же программа не работает.

Только вот даже я, давно занимаясь программированием, так и не научился писать программы с первого раза.

Решение

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

Пример

Дабы проиллюстрировать эту идею, давайте вместе напишем небольшую программу, которая шифрует фразу кодом Цезаря. Для начала откройте Википедию и узнайте, как работает шифр Цезаря. Возьмите в руки карандаш и бумагу и попробуйте зашифровать несколько фраз. Очень важно понимать саму задачу и знать, что именно вам нужно сделать.

Начнем с пошагового плана. На первый взгляд, он довольно прост.

  • 1. Получить фразу и ключ от пользователя.
  • 2. Зашифровать фразу, используя полученный от пользователя ключ.
  • 3. Вывести зашифрованную фразу.

Но как только мы приступим к реализации первого пункта, вы поймете, что он включает в себя такие пункты:

  • 1. Получить фразу и ключ от пользователя.
    • 1.1. Попросить пользователя ввести фразу для шифрования.
    • 1.2. Считать фразу, введенную пользователем.
    • 1.3. Проверить, не ввел ли пользователь пустую строку.
    • 1.4. Попросить пользователя ввести ключ.
    • 1.5. Ключ - это число. Попробовать конвертировать строку в число.
    • 1.6. Проверить, ввел ли пользователь правильный ключ.

Пришло время писать код.

// 1.1) Попросить пользователя ввести фразу для шифрования
Console.WriteLine("Please enter a phrase to encrypt...");

// 1.2) Считать фразу, введенную пользователем
string input = Console.ReadLine();

// 1.3) Проверить, не ввел ли пользователь пустую строку
if (input == null || input == "")

{
    Console.WriteLine("Looks like you've entered nothing.");
    Console.ReadKey();
    return;
}

// 1.4) Попросить пользователя ввести ключ
Console.WriteLine("Please enter encryption key...");

// 1.5) Ключ - это число. Попробовать конвертировать строку в число
int key = 0;
int.TryParse(Console.ReadLine(), out key);

// 1.6) Проверить, ввел ли пользователь правильный ключ
if (key <= 0)
{
    Console.WriteLine("Looks like you've entered invalid key. Key must be a positive integer number.");
    Console.ReadKey();
    return;
}

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

Я рекомендую не писать этот код за один раз. Вместо этого реализуйте первый пункт нашего плана: «Попросить пользователя ввести фразу для шифрования». Запустите программу и убедитесь, что в консоль выводится сообщение: «Please enter a phrase to encrypt...». Затем приступайте ко второму пункту нашего плана.

Во втором пункте мы должны считать фразу, введенную пользователем. На этом этапе важно убедиться, что наш код работает именно так, как нужно и переменная input содержит именно фразу, введенную пользователем. Поэтому сразу после того, как вы считали фразу, выведите ее в консоль и убедитесь, что переменная input содержит именно то, что нужно.

// 1.2) Считать фразу, введенную пользователем
string input = Console.ReadLine();
Console.WriteLine(input);

Не забудьте удалить эту последнюю строку, так как она нам была нужна только для того, чтобы проверить, что все идет как надо. После того, как вы в этом убедились, можете переходить к следующему пункту нашего плана. И не забудьте убедиться, что каждая новая часть программы работает правильно! Я же перейду сразу к шифрованию.

A Цитата из Википедии гласит:

Если сопоставить каждому символу алфавита его порядковый номер (нумеруя с 0), то шифрование и дешифрование можно выразить формулами модульной арифметики:

y = (x + k) mod n,

где x — символ открытого текста, y — символ шифрованного текста, n — количество букв в алфавите, а k — ключ.

Согласно этой цитате, наш план для второго шага должен выглядеть следующим образом:

  • 2. Зашифровать фразу, используя полученный от пользователя ключ:
    • 2.1. Для каждой буквы незашифрованной фразы делаем следующее:
      • 2.1.1. Находим порядковый номер исходного символа x. Для этого нужно знать, что такое ASCII таблица и как в ней хранятся буквы от «a» до «z» и от «A» до «Z»;
      • 2.1.2. Шифруем исходный символ x, используя формулу, приведенную выше. Ключ мы уже знаем. Параметр формулы n положим равным 26 – количеству букв в английском алфавите;
      • 2.1.3. В результате шифрования мы получаем не символ, а номер буквы от 0 до 25. Теперь нужно конвертировать его обратно в символ.
    • 2.2. Пробелы, цифры и прочие символы шифровать не нужно.

А вот и код.

char[] output = input.ToCharArray();
for (int i = 0; i < input.Length; i++)
{
    // Исходный незашифрованный символ
    char unencripted = input[i];

    // 2.1) Шифруем только буквы. Остальные символы оставляем как есть
    if (char.IsLetter(unencripted))
    {
        // 2.1.1) Находим порядковый номер исходного символа x.
        // Нужно просто знать, что такое ASCII таблица и как в ней хранятся буквы от «a» до «z» и от «A» до «Z»
        int offset = (char.IsUpper(unencripted) ? 'A' : 'a');
        int x = unencripted - offset;

        // 2.1.2) Шифруем исходный символ x, используя формулу
        int y = (char) ((x + key) % 26);

        // 2.1.3) Конвертируем номер буквы в символ
        char encrypted = (char) (y + offset);

        output[i] = encrypted;
    }
    else
    {
        // 2.2)	Пробелы, цифры и прочие символы шифровать не нужно.
        output[i] = input[i];
    }
}

Наверное, этот код выглядит еще более непонятным. Но не нужно писать его весь и сразу. Начните с пунктов 2.1 и 2.2. Но забудьте пока что про шифрование и вместо зашифрованных символов выводите «*».

char[] output = input.ToCharArray();
for (int i = 0; i < input.Length; i++)
{
    // Исходный незашифрованный символ
    char unencripted = input[i];

    // 2.1) Шифруем только буквы. Остальные символы оставляем как есть
    if (char.IsLetter(unencripted))
    {
        Console.Write("*");
    }
    else
    {
        // 2.2)	Пробелы, цифры и прочие символы шифровать не нужно.
        output[i] = input[i];
    }
}

Далее займитесь кодом шифрования. Для начала попробуйте конвертировать буквы в числа от 0 до 25. Убедитесь, что этот кусочек кода работает правильно. Для этого просто выводите результаты работы вашей программы на консоль.

int offset = (char.IsUpper(unencripted) ? 'A' : 'a');
int x = unencripted - offset;
Console.Write(x);

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

char encrypted = (char) (x + offset);
Console.Write(x);

Теперь вам останется написать один единственный кусочек кода для шифрования символа. Благодаря тому, что вы проверили, что все остальные кусочки кода работают и делают именно то, что вам нужно, это будет легкой задачей. Даже если вы не сможете написать его с первого раза, вы будете знать, что ошибка (скорее всего) именно в этой строке.

int y = (char) ((x + key) % 26);

Ну, я надеюсь, вы поняли идею. Просто будьте последовательны, разделяйте сложную задачу на подзадачи и тестируйте их.

И, напоследок, самое сложное. Третий пункт нашего плана. Нам предстоит вывести зашифрованную фразу. Вы готовы?

// 3) Вывести зашифрованную строку
Console.WriteLine("Encrypted phrase: " + new string(output));
Console.ReadKey();

Все :)