2016 экзамен ответы вариант 1 (1161203)
Текст из файла
Ответы на вопросы экзамена по курсу«Языки программирования» 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# нужная заготовка была с самого начала — это делегаты. Неслучайно анонимные делегаты(то есть типизированные лямбды) появились в языке ужесо второй версии, а вскоре поспели и настоящие лямда-выражения. Поэтому в C#программа должна выглядеть более естественно, чем в Java. И не надо «тупо»транслировать то, что не транслируется (например, функциональные интерфейсы).Вместо функционального интерфейса просто описываем делегатский типdelegate int Compute(int i);Объекты-делегаты — уже callables – то есть их можно вызывать (точнее применять к нимоперацию вызова «()») напрямую без всяких методов-посредников типа compute(i).Окончательно получаемpublic class Generator{public delegate int Compute(int i);static void Main(String[] args) {generate(x=>x*x, 10);generate(x=>x*x*x, 10);}static void generate(Compute func, int n) {for (int i = 1; i <= n; ++i) {System.Console.Write(func(i)); // обратите внимание на отсутствие вызоваfunc.compute(i) - он больше не нуженSystem.Console.Write(' ');}}}И все!Задача 1-6Объявление шаблонного класса CalcSort на языке С++ предполагает, что над параметром шаблона Tвыполняются 4 арифметические операции (+,-,*,/) и операции сравнения:template <typename T> class CalcSort { … };Напишите эквивалентное объявление обобщенного класса CalcSort на языке Java (опустив, как и выше,все объявления членов класса), добавив при необходимости нужные объявления типов вне этого класса.ОтветСм.
Характеристики
Тип файла PDF
PDF-формат наиболее широко используется для просмотра любого типа файлов на любом устройстве. В него можно сохранить документ, таблицы, презентацию, текст, чертежи, вычисления, графики и всё остальное, что можно показать на экране любого устройства. Именно его лучше всего использовать для печати.
Например, если Вам нужно распечатать чертёж из автокада, Вы сохраните чертёж на флешку, но будет ли автокад в пункте печати? А если будет, то нужная версия с нужными библиотеками? Именно для этого и нужен формат PDF - в нём точно будет показано верно вне зависимости от того, в какой программе создали PDF-файл и есть ли нужная программа для его просмотра.