Главная страница
Навигация по странице:

  • 5.2. Преобразование типов

  • 5.3. Стандартные математические функции

  • Стандартные математические функции

  • Основные математические функции С/C++

  • 5.4. Директивы препроцессора

  • Директива препроцессора include

  • Символические константы и макроподстановка

  • Макрос assert

  • 5.5. Практические задания

  • Лекция 5. Лекция использование основных операций и выражений языка сС. Стандартные функции и директивы препроцессора операции и выражения СС Классификация операций


    Скачать 392.63 Kb.
    НазваниеЛекция использование основных операций и выражений языка сС. Стандартные функции и директивы препроцессора операции и выражения СС Классификация операций
    Дата30.04.2023
    Размер392.63 Kb.
    Формат файлаpdf
    Имя файлаЛекция 5.pdf
    ТипЛекция
    #1099105


    59
    Лекция 5. ИСПОЛЬЗОВАНИЕ
    ОСНОВНЫХ ОПЕРАЦИЙ И ВЫРАЖЕНИЙ
    ЯЗЫКА С/С++. СТАНДАРТНЫЕ ФУНКЦИИ
    И ДИРЕКТИВЫ ПРЕПРОЦЕССОРА
    5.1. Операции и выражения С/С++
    Классификация операций
    Операции бывают
    унарные
    (воздействуют на одно значение или выражение),
    бинарные
    (участвуют два выражения) и
    тернарные
    (три выражения). Основные унарные операции приведены в табл. 5.1.
    Унарные операции выполняются справа налево.
    Таблица 5.1
    Унарные операции
    Операции
    Назначение
    &
    Получение адреса операнда
    *
    Обращение по адресу (разыменование)

    Унарный минус, меняет знак арифметического операнда


    Поразрядное инвертирование внутреннего двоичного кода (побито- вое отрицание)
    !
    Логическое отрицание (НЕ). В качестве логических значений ис- пользуется 0 – ложь и не 0 – истина, отрицанием 0 будет 1, отрица- нием любого ненулевого числа будет 0
    ++
    Инкремент или увеличение на единицу: префиксная операция – уве- личивает операнд до его использования, постфиксная операция уве- личивает операнд после его использования.
    --
    Декремент или уменьшение на единицу: префиксная операция –
    уменьшает операнд до его использования, постфиксная операция уменьшает операнд после его использования sizeof Вычисление размера (в байтах) для объекта того типа, который имеет операнд
    Основные бинарные операции приведены в табл. 5.2, они выпол- няются слева направо.
    Таблица 5.2
    Бинарные операции
    Операции
    Назначение
    +
    Бинарный плюс (сложение арифметических операндов)

    Бинарный минус (вычитание арифметических операндов)
    Аддитивные

    60
    Окончание табл. 5.2
    Операции
    Назначение
    *
    Умножение операндов арифметического типа
    /
    Деление операндов арифметического типа (ес- ли операнды целочисленные, то выполняется целочисленное деление)
    %
    Получение остатка от деления целочисленных операндов (операция по модулю)
    Мультипликатив- ные
    <<
    Сдвиг влево битового представления значения левого целочисленного операнда на количество разрядов, равное значению правого операнда
    >>
    Сдвиг вправо битового представления значения правого целочисленного операнда на количест- во разрядов, равное значению правого операнда
    Операции сдвига
    (определены толь- ко для целочислен- ных операндов)
    &
    Поразрядная конъюнкция (И) битовых пред- ставлений значений целочисленных операндов
    |
    Поразрядная дизъюнкция (ИЛИ) битовых пред- ставлений значений целочисленных операндов
    ^
    Поразрядное исключающее ИЛИ битовых пред- ставлений значений целочисленных операндов
    Поразрядные опера- ции
    <
    Меньше, чем
    >
    Больше, чем
    <=
    Меньше или равно
    >=
    Больше или равно
    ==
    Равно
    !=
    Не равно
    Операции сравнения
    &&
    Конъюнкция (И) целочисленных операндов или отношений, целочисленный результат ложь (0) или истина (1)
    ||
    Дизъюнкция (ИЛИ) целочисленных операндов или отношений, целочисленный результат ложь (0)
    или истина (1)
    Логические бинар- ные операции
    =
    Присваивание, присвоить значение правого операнда левому
    +=
    –=
    *=
    /=
    %=
    |=
    &=
    ^=
    <<=
    >>=
    Выполнить соответствующую операцию с ле- вым операндом и правым операндом и присво- ить результат левому операнду
    Операции присваи- вания и составного присваивания

    61
    Приоритеты операций приведены в табл. 5.3.
    Таблица 5.3
    Приоритеты операций
    Ранг
    Операции
    1
    ( ) [ ] –> .
    2
    ! – ++ -- & * (тип) sizeof тип ( )
    3
    * / % (мультипликативные бинарные)
    4
    + - (аддитивные бинарные)
    5
    << >> (поразрядного сдвига)
    6
    < > <= >= (отношения)
    7
    == != (отношения)
    8
    & (поразрядная конъюнкция «И»)
    9
    ^ (поразрядное исключающее «ИЛИ»)
    10
    | (поразрядная дизъюнкция «ИЛИ»)
    11
    && (конъюнкция «И»)
    12
    || (дизъюнкция «ИЛИ»)
    13
    ?: (условная операция)
    14
    = *= /= %= -= &= ^= |= <<= >>= (операция присваивания)
    15
    , (операция запятая)
    В отличие от унарных и бинарных операций в
    тернарных услов-
    ных операциях
    используется три операнда:
    Выражение1 ? Выражение2 : Выражение3;
    Первым вычисляется значение выражения 1. Если оно истинно, то вычисляется значение выражения 2, которое становится результа- том. Если при вычислении выражения 1 получится 0, то в качестве ре- зультата берется значение выражения 3.
    Выражения
    Комбинация знаков операций и операндов, результатом которой яв- ляется определенное значение, называется
    выражением
    . Каждый операнд в выражении может быть выражением. Значение выражения зависит от расположения знаков операций и круглых скобок в выражении, а также от приоритета выполнения операций. Каждое выражение состоит из од- ного или нескольких операндов, символов операций и ограничителей: x<0 ? -x : x ; //вычисляется абсолютное значение x
    X * 12 + Y val < 3
    -9

    62
    Выражение, после которого стоит точка с запятой – это оператор- выражение.
    Рассмотрим подробнее некоторые операции и варианты их ис- пользования.
    Операция присваивания
    (
    =
    ) рассматривается как выражение, имею- щее значение левого операнда после присваивания. Присваивание может включать несколько операций присваивания, изменяя значения нескольких операндов, например:
    Недопустимыми являются:
    присваивание константе, присваива-
    ние функции и присваивание результату операции
    Операции инкремента и декремента
    (
    ++, --
    )
    относятся к унар- ным арифметическим операциям, которые служат соответственно для увеличения или уменьшения значения, хранимого в переменной целого типа. Например, следующие три оператора дадут один и тот же эффект:
    Операции инкремента и декремента не только изменяют значения переменных, но и возвращают значения. Таким образом, их можно сделать частью более сложного выражения:
    Имеется
    постфиксная
    и
    префиксная
    форма операторов инкремента и декремента. В постфиксной форме записи переменная, к которой int i, j, a; float m, y; m *= y;
    //m = m * y; i += 2;
    //i = i + 2; m /= y + 1;
    //m = m / (y + 1);
    --a;
    //a = a - 1; j = i++;
    //j = i; i = i + 1; j = ++i;
    //i = i + 1; j = i; sum = sum + 1; sum += 1;
    ++sum;
    2 = a + b;
    //ошибка getch() = a;
    //ошибка
    (a + 1) = 2 + b;
    //ошибка long a; char b; int c, x, y, z; a = b = c;
    //эквивалентно b = c; a = b; x = i + (y = 3) - (z = 0);
    //z = 0, y = 3, x = i + y - z;

    63 применена операция, увеличивается (или уменьшается) только после того, как ее значение будет использовано в контексте.
    Типичной ошибкой является попытка использовать в операции инкремента или декремента операнд, отличный от имени простой переменной:
    Общий вид операций сравнения (отношения):
    <выражение 1> <знак операции> <выражение 2>
    Выражениями могут быть любые базовые (скалярные) типы. Зна- чения выражений перед сравнением преобразуются к одному типу.
    Результат операции сравнения – значение 1, если отношение истинно, или 0 в противном случае (ложно). Операция сравнения может ис- пользоваться в любых арифметических выражениях: или
    В
    С/С++
    предусмотрены
    битовые
    операции
    для работы с
    отдельными битами. Эти операции нельзя применять к переменным вещественного типа.
    Операндами операций над битами могут быть только выражения, приводимые к целому типу. Операции (

    ,
    &
    ,
    |
    ,
    ^
    )
    выполняются пораз- рядно над всеми битами операндов (знаковый разряд не выделяется).
    Общий вид операции инвертирования:
    <выражение>
    Остальные операции над битами имеют вид:
    <выражение 1> <знак операции> <выражение 2>
    ++(x + 1); //ошибка
    (
    a < b && b < c)
    //если ОДНОВРЕМЕННО ОБА a < b
    //и b < c, то истина, иначе ложь if (a == 0 || b > 0)
    //если ХОТЯ БЫ ОДИН a==0
    //или b > 0, то истина, иначе ложь
    !0
    //1
    !10
    //0
    !((x = 1) < 0)
    //1 0 < x < 100
    //ошибка
    (0 < x) && (x < 100)
    //верно int b = 5; int c = 10; a = b > c;
    //Запомнить результат сравнения a=0 a = (b > c)* 2;
    //a= 0

    64
    Ниже приведена таблица истинности логических операций
    &
    ,
    |
    и
    ^
    Операнд 1
    Операнд 2
    & | ^
    0 0 0 0 0 0 1 0 1 1 1 0 0 1 1 1 1 1 1 0
    Операция
    &
    часто используется для маскирования некоторого множества бит.
    Операция
    !
    используется для включения (устанавли- вает в единицу те биты, которые были нулями).
    Необходимо отличать побитовые операции
    &
    и
    !
    от логических бинарных операций
    &&
    и
    ||
    Арифметические операции
    задают обычные действия над операн- дами арифметического типа.
    Если арифметическая операция содержит операнды различных ти- пов, то компилятор выполняет автоматическое преобразование их типов.
    Часто арифметические операции используются для обработки чи- сел, например:
    Операции сдвига
    <<
    и
    >>
    осуществляют соответственно сдвиг вправо и влево своего левого операнда на число позиций, задаваемых правым операндом. Операции сдвига выполняются также для всех разрядов с потерей выходящих за границы бит. int n = 12345; int low, i = 6; low = n %10;
    //младшая цифра числа n n = n / 10;
    //отбросить младшую цифру числа n if ( n % i == 0)... //определить - n делится нацело на i ? n = n * 10 + i;
    //добавить цифру i к значению числа n i % j
    //i - ( i/j ) * j
    12 % 6
    //0 13 % 6
    //1 x = 1; y = 2; x & y
    //результат 0, т.к. 0001 & 0010=0000 x && y
    //результат 1, т.к. в операц. сравнения
    //оба операнда истина

    65
    Если левостоящее выражение имеет тип unsigned
    , то при сдвиге вправо освобождающиеся разряды гарантированно заполняются ну- лями (логический сдвиг). Выражения типа signed могут, но не необя- зательно, сдвигаться вправо с копированием знакового разряда
    (арифметический сдвиг). При сдвиге влево освобождающиеся разряды всегда заполняются нулями. Если правостоящее выражение отрица- тельно либо больше длины левостоящего выражения в битах, то ре- зультат операции сдвига не определен.
    Операции сдвига вправо на
    k
    разрядов можно использовать для деления, а сдвиг влево – для умножения целых чисел на 2 в степени
    k
    :
    Операция
    sizeof выполняется на этапе компиляции программы и дает константу, которая равна числу байтов, требуемых для хранения в памяти данного объекта. Объектом может быть имя переменной, массива, структуры или просто спецификация типа.
    Операторы
    Основной источник операторов в программе – выражения. Любое из них, ограниченное символом
    ;
    , превращается в оператор.
    Запись действий, которые должен выполнить компьютер, состоит из операторов. При выполнении программы операторы выполняются один за другим, за исключением операторов управления, которые могут изменить последовательное выполнение программы. Различают опера- торы объявления переменных, операторы управления и операторы- выражения. Простейшей формой оператора является пустой оператор:
    ;
    Он ничего не делает. Однако он может быть полезен в тех случаях, когда синтаксис требует наличие оператора, а он не нужен.
    Любая последовательность операторов, заключенная в фигурные скобки
    {}
    , может выступать в любой синтаксической конструкции как один
    составной оператор
    (
    блок
    ): int i; cout << sizeof(int) << sizeof(i); x << 1; //x * 2 x >> 1; //x / 2 x << 3; //x * 8 0x81 << 1
    //10000001<<1=00000010=0x02 0x81 >> 1
    //10000001>>1=01000000=0x40

    66
    Он позволяет рассматривать несколько операторов как один. Область видимости имени, описанного в блоке, простирается до конца блока.
    Операция запятая
    (
    ,
    ) используется при организации строго га- рантированной последовательности вычисления выражений (исполь- зуется там, где по синтаксису допустима только одна операция, и для организации множественных выражений, расположенных внутри круглых скобок). Форма записи: выражение 1, …, выражение N;
    Выражения вычисляются слева направо. Например:
    Выражения,
    разделенные запятой,
    не должны быть присваиваниями.
    Ниже приведенный пример не является примером хорошего кода:
    5.2. Преобразование типов
    В операциях могут участвовать операнды различных типов, в этом случае они
    неявно
    преобразуются к общему типу в порядке увеличения их объема памяти, необходимого для хранения их значе- ний. Поэтому неявные преобразования всегда идут от «меньших» объектов к «большим». Схема выполнения преобразований операндов арифметических операций: short, char → int → unsigned → long → double float → double
    { a = b + 2; b++;
    }
    int one = 1, two = 2, three = 100, six = 0; six = (++one, ++two, ++three);
    //one = 2, two = 3, three = 101, six = 101 char X, Y;
    (X = Y, Y = getch());
    //присваивает переменной X значение Y, считывает символ,
    //вводимый с клавиатуры, и запоминает его в Y int i, j, k, n; m = ( i = 1, j = i++, k = 6, n = i + j + k);
    //i = 1, j = i = 1, i = 2, k = 6, n = 2 + 1 + 6, m = n = 9

    67
    Значения типов char и short всегда преобразуются в int
    ; если лю- бой из операндов имеет тип double
    , то второй преобразуется в double
    ; если один из операндов long
    , то другой преобразуется в long
    При присваивании значение правой части преобразуется к типу левой, который и является типом результата. При некорректном ис- пользовании операций присваивания могут возникнуть ошибки.
    В любом выражении преобразование типов может быть осущест- влено
    явно
    , в С для этого достаточно перед выражением поставить в скобках идентификатор соответствующего типа:
    (тип) выражение;
    В результате значение выражения преобразуется к заданному типу:
    Эта форма является устаревшей и сохранена в стандарте С++ только для обеспечения обратной совместимости с программами, на- писанными для С и предыдущих версий С++.
    В С++ явное преобразование типов производится при помощи следующих операторов: static_cast
    , dynamic_cast
    , const_cast и reinterpret_cast
    . Хотя иногда явное преобразование необходимо, оно служит потенциальным источником ошибок.
    Явное преобразование типов используется для разыменования ука- зателя void*
    , для того, чтобы избежать стандартного преобразования или выполнить вместо него собственное. Также может использоваться, float a; int i = 6, j = 4; a = (i + j) / 3;
    // a = 3 a = (float)(i + j) / 3; →
    // a = 3.333333 int ival; float fval; double dval; ival + fval + dval;
    //fval и iva1 преобразуются к double перед сложением float x; int i; x = i; i = x;
    //float преобразуется в int, дробная часть отбрасывается

    68 чтобы избежать неоднозначных ситуаций, в которых возможно не- сколько вариантов применения правил преобразования по умолчанию.
    Синтаксис операции явного преобразования: cast-name< type >( expression)
    ;
    Здесь cast-name
    – одно из ключевых слов static_cast
    , const_cast
    , dynamic_cast или reinterpret_cast
    , а type
    – тип, к которому приводится выражение expression
    Так const_cast слу- жит для трансформации константного типа в неконстантный. Любое иное использование const_cast вызывает ошибку компиляции, как и попытка подобного приведения с помощью любого из трех других операторов. С применением static_cast осуществляются те преоб- разования, которые могут быть сделаны неявно, на основе правил по умолчанию:
    Оператор reinterpret_cast работает с внутренними представ- лениями объектов (
    reinterpret
    – другая интерпретация того же внут- реннего представления), причем правильность этой операции целиком зависит от программиста.
    Оператор dynamic_cast применяется при идентификации типа во время выполнения (
    runtime type identification
    ).
    5.3. Стандартные математические функции
    В любой программе, кроме операторов и операций, используются средства библиотек, входящих в среду программирования, которые облегчают создание программ. Часть библиотек стандартизована и поставляется с компилятором. В стандартную библиотеку входят функции, макросы, глобальные константы. Это файлы, хранящиеся в папке include
    Стандартные математические функции
    Математические функции языка С декларированы в файлах
    <сmath>
    и

    В большинстве приведенных здесь функций аргументы x
    , y
    и ре- зультат выполнения имеют тип double
    . В табл. 5.5 приведены основные математические функции С/C++. const double d = 97.0; char ch = static_cast< char >( d );

    69
    Таблица 5.5
    Основные математические функции С/C++
    Описание содержится в math.h|cmath double ceil(double x); float ceilf(float x); long double ceill(long double x);
    Функции округления до наименьшего целого, не меньшего, чем аргумент double cos(double x);
    Возвращает значение косинуса x, где x – это значение в радианах (2
    π ради- ан = 3600) double exp(double x);
    Возвращает значение числа e, возве- денного в степень x double fabs(double x); float fabsf(float x); long double fabsl(long double x);
    Абсолютное значение числа с пла- вающей точкой double floor(double x); float floorf(float x); long double loorl(long double x);
    Наибольшее целое значение, но не большее x double fmod(double x, double y);
    Функция получения остатка от деле- ния (с плавающей точкой) double log(double x);
    Возвращает натуральный логарифм x double log10(double x);
    Возвращает десятичный логарифм x double pow(double x, double y);
    Возвращает значение x в степени y int rand(void);
    Возвращает псевдослучайное число в диапазоне от нуля до
    RAND_MAX
    void srand(unsigned int seed);
    Устанавливает свой аргумент как основу (
    seed
    ) для новой последова- тельности псевдослучайных целых чисел, возвращаемых функцией rand()
    double sin(double x);
    Возвращает значение синуса аргу- мента x, где x указан в радианах double sqrt(double x);
    Функция вычисления квадратного корня double tan(double x);
    Возвращает тангенс аргумента x, где x задан в радианах
    Пример
    В прил. 4 содержится описание заголовочных файлов и стандарт- ных функций языка С++.
    5.4. Директивы препроцессора
    Директивы препроцессора представляют собой инструкции, записан- ные в исходном тексте программы и предназначенные для выполнения
    Z = pow(x,10.0) + 3.7 * pow(x,8.0); //Z = x
    10
    + 3.7·x
    8

    70 препроцессором языка. Директивы начинаются со специального знака
    #
    , помещаемого в первой позиции строки.
    Директивы позволяют:
    • описывать макросы, которые уменьшают трудоемкость написания программы и делают текст программы удобочитаемым и выразительным;
    • включать текст из других текстовых файлов, содержащих про- тотипы библиотечных и разработанных пользователем функций, шаб- лоны структурных переменных и т.д.;
    • организовывать условную компиляцию, т.е. в зависимости от заданных в командной строке или среде параметров получать раз- личный программный код.
    Директива препроцессора
    #include
    Заголовочные файлы включаются в текст программы с помощью директивы препроцессора
    #include
    . Директива применяется для включения копии указанного в директиве файла в то место, где нахо- дится эта директива. Имя файла может быть указано двумя способами:
    Различие между ними заключается в методе поиска препроцессо- ром включаемого файла. Если имя файла заключено в угловые скобки
    (
    < >
    ), считается, что используется стандартный заголовочный файл, и компилятор ищет этот файл в предопределенных местах. Двойные ка- вычки означают, что заголовочный файл – пользовательский, и его по- иск начинается с того каталога, где находится исходный текст проекта.
    Заголовочные файлы содержат объявления и определения (клас- сов, структур, объединений, перечисляемых типов и прототипов функций), общие для различных программных файлов, и поэтому час- то создаются и включаются в файлы программ.
    Символические константы и макроподстановка
    Директива препроцессора
    #define обычно используется для за- мены часто используемых в программе констант, ключевых слов, опе- раторов и выражений осмысленными идентификаторами.
    Идентификаторы, которые заменяют числовые или текстовые константы либо произвольную последовательность символов, назы- ваются именованными константами.
    Идентификаторы, которые представляют некоторую последова- тельность действий, заданную операторами или выражениями языка, называются макроопределениями.
    #include
    #include "file.h"

    71
    Формат директивы определяется как:
    #define идентификатор строка_текста
    Директива обеспечивает замену встречающегося в тексте про- граммы идентификатора на соответствующую строку текста, в том числе и с параметрами. Например:
    #define SIZE 100 //символическая константа
    #define min(a,b) ((a) < (b) ? (a) : (b)) //макрос
    #define PRN(number) printf(#number " = %d\n", number);
    //макрос int scale = 25, param = 10;
    PRN(scale);
    PRN(param); result = min(44,uplimit);
    //result = ((44) < (uplimit) ? (44) : (uplimit));
    Как и в случае символических констант, идентификатор макроса заменяется на замещающий текст до начала компиляции программы.
    Макросы без параметров обрабатываются подобно символическим константам. Если макрос имеет параметры, то сначала в замещающий текст подставляются значения параметров, а затем этот расширенный макрос подставляется в текст вместо идентификатора макроса и спи- ска его параметров.
    Определения символических констант и макросов могут быть ан- нулированы при помощи директивы
    #undef
    Она отменяет самое по- следнее определение поименованного макроопределения.
    В С++ отдается предпочтение использованию именованных пере- менных типа const
    , а не символических констант. Константные пере- менные являются данными определенного типа и их имена видны от- ладчику. Если используется символическая константа, то после того, как она была заменена на текст, только этот текст будет виден отлад- чику. Недостатком переменных типа const является то, что им требу- ется память в объеме, соответствующем их типу. Для символических констант дополнительной памяти не требуется.
    #define TRI 3
    #define F 5
    #undef TRI //TRI теперь не определен
    #define F 10 //F переопределен как 10

    72
    Условные директивы
    Заголовочный файл, который подключается к модулю проекта, также может содержать директивы
    #include
    . Поэтому некоторые заго- ловочные файлы могут оказаться включенными несколько раз. Избе- жать этого позволяют условные директивы препроцессора. Например:
    Условная директива
    #ifndef проверяет, не было ли значение
    FILE_H
    определено ранее (
    FILE_H
    – это константа препроцессора; та- кие константы принято писать заглавными буквами). Препроцессор обрабатывает следующие строки вплоть до директивы
    #endif
    . В про- тивном случае он пропускает строки от
    #ifndef до
    #endif
    Другим распространенным примером применения условных ди- ректив препроцессора является включение в текст программы отла- дочной информации.
    Рассмотрим еще пример:
    Директива
    #ifdef сообщает, что если последующий идентифика- тор
    O
    определяется препроцессором, то выполняются все последую- щие директивы вплоть до первого появления
    #else или
    #endif
    . Когда в программе есть
    #else
    , то программа от
    #else до
    #endif будет вы- полняться, если идентификатор не определен.
    Макрос
    assert
    Макрос assert
    , определенный в заголовочном файле

    , выполняет проверку значения выражения. Если значение выражения
    0 (ложь), то макрос assert выводит сообщение об ошибке и вызывает функцию abort
    (из библиотеки утилит общего назначения

    ), которая завершает выполнение программы. Макрос удобно использо- вать при отладке. Например, переменная х
    в программе не должна при- нимать значение большее, чем 10. В этом случае макрос assert можно
    #ifdef O
    #include "o.h" //выполнится, если O определен
    #define ST 10
    #else
    #include "w.h" //выполнится, если O не определен
    #define ST 20
    #endif
    #define FILE_H
    /* содержимое файла file.h */
    #ifndef FILE_H
    #endif

    73 использовать для проверки значения х
    и вывода сообщения об ошибке, если значение х вышло из допустимого диапазона:
    Если х
    будет иметь значение, большее, чем 10, то программа вы- даст сообщение об ошибке, содержащее номер строки и имя файла, после чего завершит свою работу.
    После того, как в тексте программы объявляется символическая константа
    NDEBUG
    , все последующие вызовы макроса assert будут игнорироваться. Таким образом, когда все они будут больше не нуж- ны (т.е. когда отладка закончена), в начале программы достаточно до- бавить строку вместо ручного удаления каждого макроса assert
    5.5. Практические задания
    Для каждой из задач составить блок-схему алгоритма.
    1.
    Дано действительное число
    x
    . Не пользуясь никакими другими арифметическими операциями, кроме умножения, сложения и вычи- тания, вычислить за минимальное число операций 2
    x
    4
    – 4
    x
    3
    + 2
    x
    – 1.
    2.
    Ввести любой символ и определить его порядковый номер, а также указать предыдущий и последующий символы.
    3.
    Дана длина ребра куба. Найти площадь грани, площадь полной поверхности и объем этого куба.
    4.
    Треугольник задан величинами своих углов и радиусом опи- санной окружности. Найти стороны треугольника.
    5.
    Дано
    a
    . Не используя никаких функций и никаких операций, кроме умножения, получить
    а
    8
    за три операции;
    а
    10
    и
    а
    16
    за четыре операции. assert ( х <= 10 ) ;
    #define NDEBUG;


    написать администратору сайта