2016 пересдача ответы вариант 1 (Решённые задачи прошлых лет)
Описание файла
Файл "2016 пересдача ответы вариант 1" внутри архива находится в папке "Решённые задачи прошлых лет". PDF-файл из архива "Решённые задачи прошлых лет", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст из PDF
Ответы на вопросы экзамена по курсу«Языки программирования» 09.01.2017В ответах курсивом выделены необязательные пояснения, которые можно опустить(особенно на экзамене)Вариант 1Задача 1-1Есть ли ошибка в тексте приведенной ниже функции r_vowels(s) на языке JavaScript(функция подсчитывает число гласных букв русского алфавита в строке-аргументе s)?Если есть, то объясните, в чем она состоит и как изменить текст функции, чтобы онаработала правильно во всех реализациях языка?function r_vowels(s) {var i,cnt = 0; const vowels = 'АЕЁИОУЫЭЮЯаеёиоуыэюя';for (i=0; i<s.length; ++i) if (vowels.indexOf(s[i])>=0) ++cnt;return cnt;}ОтветОшибка состоит в том, что операцию индексирования в JavaScript некорректно применятьк строкам (поэтому большинство современных руководств по языку прямо запрещаетиндексирование строк).
Это связано с тем, что операция индексирования строки корректновыдает символ с соответствующим индексом только в случае использования кодировки сфиксированной длиной представления символа (однобайтовые кодировки типа Win1251,кодировка Юникода UTF16 и т. п.). В случае кодировок с переменной длиной, таких каккодировка Юникода UTF8 (а именно эта кодировка используется в большинствереализаций JavaScript!), i-й байт строки может не иметь отношения к i-му символу.Исправить ошибку можно (как минимум) двумя способами — либо использоватьоперацию выделения i-го символа из строки (s.substr(i,1) или s.slice(i,i+1) )вместо индексирования s[i], либо разбить строку s на символы с помощью операцииsplit() с пустой строкой-разделителем (перед циклом написать s=s.split('')),получив массив строк из одного символа, который вполне корректно индексировать.Задача 1-2Что будет выдано в стандартный канал вывода после выполнения следующей программына С++? Считать, что все нужные директивы include и using добавлены в текст.class TT {char * _p;public:TT(const TT& t) { _p = strdup(t._p); cout << "TT& " << _p<< endl;}explicit TT(const char * p = "") {_p = strdup(p); cout << "Hello, "<< _p << endl; }TT& operator = (const TT& t) {if (this != &t) {cout << "goodbye, " << _p << endl; free(_p); _p = strdup(t._p);}cout << "Hello, " << _p << endl; return *this;}~TT() { cout << "goodbye, " << _p << endl; free(_p);}};int main() { TT t("world"); t = TT("bar"); return 0; }Добавьте в класс TT РОВНО ОДИН метод так, чтобы результатом стали следующиестроки:Hello, worldHello, barHello, bargoodbye, worldgoodbye, barОтветБудет выдано (нумерацию строк игнорировать):123456Hello, worldHello, bargoodbye, worldHello, bargoodbye, bargoodbye, barОбъяснение:строка 1; конструктор TT(const char*) для объекта t с параметром «world»строка 2; конструктор TT(const char*) для временного объекта с параметром «bar»строка 3,4; операция присваивания TT::operator =(const T&) для объекта t с параметромвременным объектом.
Теперь t содержит строку “bar” так же, как и временный объектстрока 5; деструктор временного объектастрока 6; деструктор объекта tДля обеспечения требуемой выдачи можно добавить перегрузку операции присваивания ссемантикой перемещения (move-семантикой). Внутри этой операции меняем местамиуказатели _p. В список методов класса добавляем строки:TT& operator = (TT&& t) {char * p = t._p; t._p = _p; _p = p;cout << "Hello, " << _p << endl;return *this;}Задача 1-3Объясните, что означает понятие «сопрограммы Кнута».
В чем отличие сопрограмм языка Python отсопрограмм Кнута? Приведите пример языка, который ближе, чем Python, реализует сопрограммы Кнута (спримерами соответствующих языковых конструкций).ОтветГлавное свойство сопрограммы состоит в том, что управление всегда передается в точку,непосредственно следующую за местом, где оно покинуло сопрограмму (в начальныймомент — на первый оператор сопрограммы).
В сопрограммах Кнута существует явныйоператор передачи управления на сопрограмму (обычно называемый resume или transfer),в котором указывается имя или ссылка на вызываемую сопрограмму. Этот операторявляется обобщением оператора вызова подпрограммы.Поскольку информация о точке возврата в сопрограмму не может храниться в общемстеке, если любая сопрограмма может вызвать любую другую сопрограмму, то иногдаговорят о том, что сопрограммы Кнута реализуют бесстековый механизм.
НАДОПОНИМАТЬ, что речь идет о реализации механизма хранения информации о точкахвозврата, и что отсутствует здесь общий стек возвратов (как в случае подпрограмм) итолько, а при этом каждая сопрограмма может обладать своим стеком — вызыватьфункции и т. п. Но из любой функции сопрограммы можно вызвать оператор передачиуправления на другую сопрограмму, и вот тут-то информация о том, куда надо будетвернуться, уже не может быть сохранена в общем стеке, а нужно использовать болееобщий механизм (чаще всего это — продолжения или континуации, о которых мы в курсеничего не говорили).
Однако нельзя говорить о том, что-де в сопрограммах Кнута стеканет (какого именно стека?), а в сопрограммах Питона стек есть — или наоборот — вПитоне стека нет, а в СК — есть. Это неправильная постановка вопроса. Кроме тогосуществуют облегченные варианты сопрограмм, реализация которых использует общийстек (что накладывает на них ряд ограничений). Опять-таки здесь снова речь омеханизме реализации хранилища точек возврата.Отличие сопрограмм Кнута от сопрограмм Питона (и Шарпа ) состоит в том, что в Питонепредложение yield, с помощью которого реализуются сопрограммы (точнее —генераторы), не содержит информации о том, куда передается управление.
Поэтомунекоторые источники (например, David Beasley) утверждают, что сопрограммыПитона — это не просто генераторы, а такие генераторы, управление на которыепередается с помощью send, а сами сопрограммы явно принимают управление и данные спомощью специальной формы предложения yield.К концепции сопрограмм Кнута ближе, чем Питон, подошла реализация языка Модула-2.Там есть специальная процедура TRANSFER(VAR FROM,TO: ADDRESS), которая служитдля передачи управления на сопрограмму, контекст которой, включая и адрес возврата,хранится в TO, а контекст текущей сопрограммы упрятывается в FROM.
Начальноезначение контекста задается процедурой NEWPROCESS(P:PROC; VARCONTEXT:ADDRESS; N:CARDINAL), где P – процедура, по которой будет работатьсопрограмма, N – размер области хранения контекста.Заметим, что и Модула-2 не дает полной реализации сопрограмм Кнута, посколькудетали организации хранилища контекстов (включая даже размер!) полностьювозлагает на программиста.Задача 1-4На языке Java написан класс Generator (не компилируется из-за отсутствия объявления имени и знаковвопроса в вызовах метода generate):public class Generator {public static void main(String[] args) {generate(???, 10); // заменить ??? на правильное значениеgenerate(???, 10); // заменить ??? на правильное значение}static void generate(Compute func, int n) {for (int i = 1; i <= n; ++i) { System.out.print(func.compute(i)); System.out.print(' ');}}}Объявить тип данных Compute и заменить вопросы в вызовах метода generate на правильные лямбдавыражения так, чтобы в канал вывода было выдано:1 4 9 16 25 36 49 64 81 100 1 8 27 64 125 216 343 512 729 1000ОтветВо-первых, надо определить функциональный интерфейсметодом compute(int x):Computec единственнымpublic interface Compute {int compute(int x);}Во-вторых, вставить вместо вопросов лямбда-выражения квадрата и куба :generate(x->x*x, 10);generate(x->x*x*x, 10);Замечание: на удивление много человек пыталось решать эту задачу без лямбд, хотя вусловии ПРЯМО указывалось на них.
Также намекалось, что нужно объявить ТИПданных (а не класс!) Собственно, лямбда-функции и появились в языках типа Java длятого, чтобы можно было избежать появления классов, единственным назначениемкоторых являлась обертка функций в методы (поскольку двадцать лет назадбольшинство программистов вдруг решило, что все в программировании можновыразить объектами...). Задача является демонстрацией того, насколько прощеиспользовать (лямбда-)функции, когда нужны именно функции. Так что людирасписавшие классы типа типа Compute (или еще хуже Printer из второго варианта)могут утешаться тем, что у них есть готовый ответ на вопрос, зачем же все-такинужны лямбда-функции в Java. Чтобы не плодить джи-код.Задача 1-5Переписать программу из задачи №4 на языке С# так, чтобы она выдавала в стандартный вывод те же самыезначения (набор и сигнатуры методов класса Generator должны остаться без изменения). Для выводаиспользовать System.Console.Write(…).ОтветВ отличие от Java, в которой «пришивание» лямбд пришлось делать слегка череззадний ...вход — то есть придумав концепцию «функционального интерфейса» введенияcallable-объектов, в C# нужная заготовка была с самого начала — это делегаты.