straustrup2 (852740), страница 23
Текст из файла (страница 23)
(*1.5) Напишите программу, которая печатает размеры основных типов и типа указателя.Используйте операцию sizeof.5. (*1.5) Напишите программу, которая печатает буквы от 'a' до 'z' и цифры от '0' до '9' и их целыезначения. Проделайте то же самое для других видимых символов.
Проделайте это, используяшестнадцатеричную запись.6. (*1) Напечатайте последовательность разрядов представления указателя 0 на вашей машине.Подсказка: см.$$2.6.2.7. (*1.5) Напишите функцию, печатающую порядок и мантиссу параметра типа double.8. (*2) Каковы на используемой вами машине наибольшие и наименьшие значения следующих типов: char,short,int,long, float, double, long double, unsigned, char*, int* и void*? Есть ли какие-то особыеограничения на эти значения? Например, может ли int* быть нечетным целым? Как выравниваются впамяти объекты этих типов? Например, может ли целое иметь нечетный адрес?9.
(*1) Какова максимальная длина локального имени, которое можно использовать в вашей реализацииС++ ? Какова максимальная длина внешнего имени? Есть ли какие-нибудь ограничения на символы,которые можно использовать в имени?10. (*1) Напишите функцию, которая меняет местами значения двух целых. В качестве типа параметровиспользуйте int*. Напишите другую функцию с тем же назначением, используя в качестве типапараметров int&.68Бьерн Страуструп.Язык программирования С++11. (*1) Каков размер массива str в следующем примере: char str[] = "a short string"; Какова длинастроки "a short string"?12. (*1.5) Составьте таблицу из названий месяцев года и числа дней в каждом из них.
Напишитепрограмму, печатающую ее. Проделайте это дважды: один раз - используя массивы для названиймесяцев и количества дней, а другой раз - используя массив структур, каждая из которых содержитназвание месяца и количество дней в нем.13. (*1) С помощью typedef определите типы: unsigned char, константный unsigned char, указатель нацелое, указатель на указатель на символ, указатель на массив символов, массив из 7 указателей нацелое, указатель на массив из 7 указателей на целое и массив из 8 массивов из 7 указателей на целое.14. (*1) Определить функции f(char), g(char&) и h(const char&) и вызвать их, используя в качествепараметров 'a', 49, 3300, c, uc, и sc, где c - char, uc - unsigned char и sc - signed char. Какой вызовявляется законным? При каком вызове транслятору придетсязавести временную переменную?69Бьерн Страуструп.Язык программирования С++ГЛАВА 3.
ВЫРАЖЕНИЯ И ОПЕРАТОРЫ"Но с другой стороны не следует забывать про эффективность"(Джон Бентли)С++ имеет сравнительно небольшой набор операторов, который позволяет создавать гибкие структурыуправления, и богатый набор операций для работы с данными.
Основные их возможности показаны вэтой главе на одном завершенном примере. Затем приводится сводка выражений, и подробнообсуждаются операции преобразования типа и размещение в свободной памяти. Далее дана сводкаоператоров, а в конце главы обсуждается выделение текста пробелами и использование комментариев.3.1 КалькуляторМы познакомимся с выражениями и операторами на примере программы калькулятора.
Калькуляторреализует четыре основных арифметических действия в виде инфиксных операций над числами сплавающей точкой. В качестве упражнения предлагается добавить к калькулятору переменные.Допустим, входной поток имеет вид:r=2.5area=pi*r*r(здесь pi имеет предопределенное значение). Тогда программа калькулятора выдаст:2.519.635Результат вычислений для первой входной строки равен 2.5, а результат для второй строки - это19.635.Программа калькулятора состоит из четырех основных частей: анализатора, функции ввода, таблицыимен и драйвера.
По сути – это транслятор в миниатюре, в котором анализатор проводитсинтаксический анализ, функция ввода обрабатывает входные данные и проводит лексический анализ,таблица имен хранит постоянную информацию, нужную для работы, а драйвер выполняетинициализацию, вывод результатов и обработку ошибок. К такому калькулятору можно добавить многодругих полезных возможностей, но программа его и так достаточно велика (200 строк), а введениеновых возможностей только увеличит ее объем, не давая дополнительной информации для изученияС++.3.1.1 АнализаторГрамматика языка калькулятора определяется следующими правилами:программа:ENDсписок-выражений END// END - это конец вводасписок-выражений:выражение PRINT// PRINT - это '\n' или ';'выражение PRINT список-выраженийвыражение:выражение + термвыражение - термтермтерм:терм / первичноетерм * первичноепервичное70Бьерн Страуструп.Язык программирования С++первичное:NUMBER// число с плавающей запятой в С++NAME// имя в языке С++ за исключением '_'NAME = выражение- первичное( выражение )Иными словами, программа есть последовательность строк, а каждая строка содержит одно илинесколько выражений, разделенных точкой с запятой.
Основные элементы выражения - это числа,имена и операции *, /, +, - (унарный и бинарный минус) и =. Имена необязательно описывать доиспользования.Для синтаксического анализа используется метод, обычно называемый рекурсивным спуском. Этораспространенный и достаточно очевидный метод. В таких языках как С++, то есть в которых операциявызова не сопряжена с большими накладными расходами, это метод эффективен.Для каждого правила грамматики имеется своя функция, которая вызывает другие функции.Терминальные символы (например, END, NUMBER, + и -) распознаются лексическим анализаторомget_token().
Нетерминальные символы распознаются функциями синтаксического анализатора expr(),term() и prim(). Как только оба операнда выражения или подвыражения стали известны, оновычисляется. В настоящем трансляторе в этот момент создаются команды, вычисляющие выражение.Анализатор использует для ввода функцию get_token(). Значение последнего вызова get_token()хранится в глобальной переменной curr_tok. Переменная curr_tok принимает значения элементовперечисления token_value:enum token_value {NAME,NUMBER,END,PLUS='+', MINUS='-', MUL='*',PRINT=';', ASSIGN='=', LP='(',};token_value curr_tok;DIV='/',RP=')'Для всех функций анализатора предполагается, что get_token() уже была вызвана, и поэтому в curr_tokхранится следующая лексема, подлежащая анализу.
Это позволяет анализатору заглядывать на однулексему вперед. Каждая функция анализатора всегда читает на одну лексему больше, чем нужно дляраспознавания того правила, для которого она вызывалась. Каждая функция анализатора вычисляет"свое" выражение и возвращает его результат. Функция expr() обрабатывает сложение и вычитание.Она состоит из одного цикла, в котором распознанные термы складываются или вычитаются:double expr(){double left = term();for(;;)switch(curr_tok) {case PLUS:get_token();left += term();break;case MINUS:get_token();left -= term();break;default:return left;}}// складываети вычитает// ``вечно''// случай '+'// случай '-'Сама по себе эта функция делает немного. Как принято в высокоуровневых функциях большихпрограмм, она выполняет задание, вызывая другие функции.
Отметим, что выражения вида 2-3+4вычисляются как (2-3)+4, что предопределяется правилами грамматики. Непривычная запись for(;;) - это71Бьерн Страуструп.Язык программирования С++стандартный способ задания бесконечного цикла, и его можно обозначить словом "вечно". Этовырожденная форма оператора for, и альтернативой ей может служить оператор while(1).
Операторswitch выполняется повторно до тех пор, пока не перестанут появляться операции + или - , а тогда поумолчанию выполняется оператор return (default).Операции += и -= используются для выполнения операций сложения и вычитания. Можно написатьэквивалентные присваивания: left=left+term() и left=left-term(). Однако вариант left+=term() и left-=term()не только короче, но и более четко определяет требуемое действие. Для бинарной операции @выражение x@=y означает x=x@y, за исключением того, что x вычисляется только один раз. Этоприменимо к бинарным операциям:+-*/%&|^<<>>поэтому возможны следующие операции присваивания:+=-=*=/=%=&=|=^=<<=>>=Каждая операция является отдельной лексемой, поэтому a + =1 содержит синтаксическую ошибку (из-запробела между + и =).
Расшифровка операций следующая: % - взятие остатка, &, | и ^ - разрядныелогические операции И, ИЛИ и Исключающее ИЛИ; << и >> сдвиг влево и сдвиг вправо. Функции term()и get_token() должны быть описаны до определения expr(). В главе 4 рассматривается построениепрограммы в виде совокупности файлов. За одним исключением, все программы калькулятора можносоставить так, чтобы в них все объекты описывались только один раз и до их использования.Исключением является функция expr(), которая вызывает функцию term(), а она, в свою очередь,вызывает prim(), и уже та, наконец,вызывает expr().