Какую задачу решает программа
Перейти к содержимому

Какую задачу решает программа

Создание сложной программы

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

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

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

Должна быть определена и семантика языка программирования. Семантика языка программирования — это набор правил, по которым исполнитель выполняет программы на этом языке. Пользуясь семантикой языка, можно однозначно определить результат выполнения программы с заданными входными данными.

При чтении программы необходимо сначала определить, к какому виду она относится. Условно программы можно разделить на два вида: простая программа без использования подпрограмм (кроме стандартных процедур ввода\вывода) и программа, использующая подпрограммы (подалгоритмы). Такая программа может включать в свою структуру как стандартные подпрограммы, так и подпрограммы, написанные пользователем.

Для чтения простой программы необходимо выяснить:

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

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

Существенно облегчает чтение программ наличие комментариев — поясняющего текста. Комментарии можно добавлять в любое место программы. Наличие комментариев — обязательное условие хорошо и грамотно написанной программы.

Примеры чтения программ на языках Pascal, QBASIC

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

Пример 1. Дана программа на двух языках программирования. Определить, какую задачу она решает.

Решение. Проанализируем тексты программы:

  1. формируется тело программы и описываются переменные;
  2. вводятся натуральные числа М и N, причем проверяется условие корректности ввода: числа должны быть положительные. Если введенные значения не удовлетворяют условию, то ввод повторяют, пока условие не будет выполнено;
  3. выбирается наименьшее значение из М и N, результат записывается в K;
  4. NOD присваивается значение 1;
  5. в цикле от двух до K генерируется число I;
  6. тело цикла — в условном операторе проверяется, является ли значение переменной I одновременно делителем М и N. Если условие выполняется, то текущее значение I сохраняется в переменной NOD; если условие не выполняется, NOD не изменит своего значения;
  7. после перебора всех значений I в NOD или запишется наибольший делитель двух чисел М и N, или останется значение 1;
  8. последний оператор программы служит для вывода результата работы программы — значения переменной NOD.

Переменные, используемые в программе:

N, М — исследуемые числа;

I — переменная цикла;

NOD — наибольший общий делитель;

К — наименьшее из М и N.

Ответ: данная программа позволяет определить для двух чисел М и N их наибольший общий делитель NOD.

Примечание. Эту же задачу можно решить, используя алгоритм Евклида.

Пример 2. Дана программа на двух языках программирования. Определить, какую задачу она решает.

10 шагов по решению задач в программировании

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

1. Прочитайте условия задачи как минимум трижды (или хотя бы столько раз, сколько вам будет удобно)

Вы не сможете решить задачу, если не поймёте её. Есть разница между задачей и задачей, которую, как вам кажется, вы решаете. Можно прочитать первые несколько строк, а насчёт остального выстроить предположения, поскольку всё выглядит похожим на то, с чем вы сталкивались раньше. Даже если вы делаете популярную игру наподобие Виселицы, удостоверьтесь, что прочитали все её правила, пусть даже вы играли в неё раньше.

Иногда можно попробовать объяснить задачу другу и посмотреть, поймёт ли он ваше объяснение. Вы же не хотите пройти половину пути и обнаружить, что неправильно поняли требования. Так что лучше потратить в начале больше времени, чтобы всё прояснить. Чем лучше поймёте задачу, тем легче будет её решить.

Допустим, мы создаём простую функцию selectEvenNumbers , которая берёт массив чисел и возвращает массив evenNumbers с одними лишь чётными числами. Если чётных чисел в исходном массиве нет, то массив evenNumbers возвращается пустым.

Какие вопросы можно себе задать:

  • Как компьютер может сказать, что число является чётным? Разделить на 2 и проверить, чтобы результат получился целым.
  • Что я передаю этой функции? Массив.
  • Что содержит этот массив? Одно или несколько чисел.
  • Какие типы данных у элементов массива? Числа.
  • Какова цель этой функции? Что я возвращаю в конце её выполнения? Цель — получить все чётные числа и вернуть их в массиве. Если нет чётных чисел, то массив возвращается пустым.

2. Пройдите по задаче вручную как минимум с тремя наборами данных

Возьмите лист бумаги и пройдите по задаче вручную. Выберите не менее трёх наборов данных для проверки. Выберите предельно допустимые и крайние случаи.

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

Крайние случаи: проблемы или ситуации, возникающие только при экстремальных (минимальных или максимальных) значениях параметров функционирования.

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

[1]
[1, 2]
[1, 2, 3, 4, 5, 6]
[-200.25]
[-800.1, 2000, 3.1, -1000.25, 42, 600]

Когда только начинаешь, то зачастую пренебрегаешь какими-то шагами. Поскольку наш мозг уже знаком с чётными числами, то можно просто посмотреть на набор чисел и сразу передать в массив 2, 4, 6 и так далее, не думая о том, как наш мозг выбирает конкретные числа. Если вы замечаете это за собой, то лучше взять большой набор данных, чтобы помешать мозгу решать задачу, просто глядя на числа. Это поможет придерживаться настоящего алгоритма.

Давайте пройдём по массиву [1]

  1. Смотрим на единственный элемент массива [1] .
  2. Определяем, является ли он чётным. Не является.
  3. Замечаем, что других элементов в массиве нет.
  4. Определяем, что здесь нет чётных чисел.
  5. Возвращаем пустой массив.
  1. Смотрим на первый элемент массива [1, 2]
  2. Это 1 .
  3. Определяем, является ли он чётным. Не является.
  4. Смотрим на следующий элемент.
  5. Это 2 .
  6. Определяем, является ли он чётным. Является.
  7. Создаём массив evenNumbers и добавляем в него 2 .
  8. Замечаем, что других элементов в массиве нет.
  9. Возвращаем массив evenNumbers — [2] .

3. Упрощайте и оптимизируйте свой алгоритм

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

  1. Создадим функцию selectEvenNumbers .
  2. Создадим новый пустой массив evenNumbers для хранения чётных чисел.
  3. Проходим по каждому элементу массива [1, 2] .
  4. Находим первый элемент.
  5. Делим его на 2 и определяем, чётный ли он. Если да, то прибавляем к evenNumbers .
  6. Находим следующий элемент.
  7. Повторяем шаг №4.
  8. Повторяем шаги №5 и №4, пока не кончатся элементы в массиве.
  9. Возвращаем массив evenNumbers вне зависимости от того, есть ли в нём что-то.
  1. Доказываем истинность для n = 1 , n = 2 , .
  2. Предполагаем, что будет истинно для n = k .
  3. Доказываем истинность для n = k + 1 .

4. Пишите псевдокод

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

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

Применительно к нашему случаю есть много разных вариантов. Например, можно использовать filter , но ради простоты примера воспользуемся простым циклом for (однако при последующем рефакторинге мы ещё столкнёмся с filter ).

Вот пример псевдокода, в основном состоящего из слов:

А вот псевдокод, в котором слов гораздо меньше:

Главное, писать код построчно и понимать логику каждой строки.

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

5. Преобразуйте псевдокод в нормальный код и отладьте его

Когда ваш псевдокод будет готов, преобразуйте каждую строку в реальный код на вашем языке. Здесь мы воспользуемся JavaScript.

Если вы писали на бумаге, то перенесите всё в редактор в виде комментариев, а затем замените каждую строку.

Теперь вызовите функцию и дайте ей некоторые из ранее использованных наборов данных. Так можно проверить, возвращает ли код нужный результат. Также можете написать тесты для проверки соответствия выходных данных ожидаемому результату.

После каждой переменной или строки можно использовать console.log() . Это поможет проверить, ведут ли себя значения и код так, как ожидается, прежде чем двигаться дальше. Таким образом вы выловите любые проблемы, не зайдя слишком далеко. Вот пример того, какие значения можно проверить при начале работы.

Ниже приведён код, полученный после обработки каждой строки псевдокода. Символы // обозначают строки из псевдокода. Жирным выделен реальный код на JavaScript.

Уберём псевдокод, чтобы не путаться.

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

6. Упрощайте и оптимизируйте код

Возможно, вы заметили, что упрощение и оптимизация — это повторяющиеся темы.

Эдсгер Дейкстра, нидерландский учёный и один из первопроходцев в ряде областей информатики

В нашем примере одним из путей оптимизации будет фильтрация элементов в массиве посредством возвращения нового массива с помощью filter . В этом случае нам не нужно определять переменную evenNumbers , потому что filter вернёт новый массив с копиями элементов, которые соответствуют фильтру. При этом исходный массив не изменится. Также нам не нужно использовать цикл for . filter пройдёт по каждому элементу, и если вернёт true, то элемент попадёт в массив, а если false , то будет пропущен.

Может потребоваться несколько итераций упрощения и оптимизации кода, по мере того как вы будете находить новые способы.

Задавайте себе такие вопросы:

  • Каковы цели упрощения и оптимизации? Цели зависят от принятого в вашей команде стиля или ваших личных предпочтений. Вы пытаетесь максимально уплотнить код? Или вы хотите сделать его более читабельным? В таком случае вы можете добавить отдельные строки с определением переменной или вычислением чего-либо, а не пытаться всё сделать в одной строке.
  • Как ещё можно сделать код более читабельным?
  • Можно ли ещё уменьшить количество шагов?
  • Есть ли переменные или функции, которые не нужны или не используются?
  • Какие-то шаги повторяются? Посмотрите, можно ли определить в другой функции.
  • Существуют ли более эффективные способы обработки крайних случаев?

Джеральд Сассман и Гарольд Абельсон, авторы “Structure and Interpretation of Computer Programs”

7. Отлаживайте

Этот шаг необходимо выполнять в ходе всего процесса. Сквозная отладка поможет раньше выловить любые ошибки синтаксиса или недостатки логики. Воспользуйтесь преимуществами своего IDE (Integrated Development Environment) и отладчика. При обнаружении бага рекомендуется просматривать код построчно, стараясь найти неожиданные вещи. Несколько советов:

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

Брайан Керниган, профессор информатики в Принстонском университете

8. Пишите полезные комментарии

Через месяц вы можете и не вспомнить, что означает каждая строка кода. А тот, кто будет работать с вашим кодом, вообще этого не знает. Поэтому важно писать полезные комментарии, чтобы избежать проблем и сэкономить впоследствии время, когда придётся снова вернуться к этому коду.

Избегайте таких комментариев:

// Это массив. Итерируем его.
// Это переменная.

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

  • Для чего этот код?
  • Что он делает?

9. Получайте отзывы посредством ревизии кода

Получайте отзывы от коллег, руководителей и других разработчиков. Читайте Stack Overflow. Смотрите, как другие решали аналогичные задачи и учитесь у них. Нередко бывает несколько способов решения задачи. Узнайте, что они собой представляют, и вам будет быстрее и проще приходить к ним самостоятельно.

Дядя Боб Мартин, программный инженер и соавтор манифеста Agile

10. Практикуйтесь, практикуйтесь, практикуйтесь

Даже опытные разработчики постоянно практикуются и учатся. Если вы получили полезный отклик, внедрите его. Снова решите задачу, или аналогичные задачи. Заставляйте себя. С каждой решённой задачей вы становитесь лучше как разработчик. Радуйтесь каждому успеху и не забывайте, как много вы уже прошли. Помните, что программирование, как и любая деятельность, со временем будет даваться всё проще и легче.

Урок 10
§7(3). Анализ программ с помощью трассировочных таблиц

liniya

Пример 6. Выясним, для чего предназначена следующая программа:

Прежде всего, обратим внимание на то, что в ней кроме переменной п целого типа используется строка nd, для которой символ « + » обозначает операцию сцепления строк. Начальное значение n вводится с клавиатуры, поэтому зададим его по своему усмотрению, например n = 12.

Выполните программу для n = 25. Какую задачу, по вашему мнению, решает эта программа?

Cкачать материалы урока

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *