Выражение в языке Си, как и в других языках высокого уровня, представляют собой совокупность операндов, объединенных знаками операций и, если необходимо, скобок. Каждый операнд в выражении может быть, в свою очередь, выражением или константой или переменной. В частном случае выражение может состоять из одного операнда. Выражение, состоящее только из констант, называется константным выражением.
Унарные операции | ||
& | получение адреса операнда | |
* | обращение по адресу - результатом операции является значение, на которое "показывает" операнд (указатель) | |
‑ | унарный минус – результатом операции является операнд, взятый с другим знаком | |
~ | побитовая инверсия операнда | |
! | логическое отрицание (НЕ). Если операнд равен 0, результат операции будет равен 1, если операнд – не ноль, результат операции = 0 | |
++ | увеличение операнда на единицу: префиксная операция - увеличивает операнд до его использования, постфиксная операция увеличивает операнд после его использования. | |
- - | уменьшение операнда на единицу: префиксная операция - уменьшает операнд до его использования, постфиксная операция уменьшает операнд после его использования. | |
sizeof() | вычисление размера (в байтах) для объекта того типа, который имеет операнд | |
-> | обращение к элементу структуры (по указателю) | |
. | обращение к элементу структуры | |
Бинарные операции(операции с двумя операндами). | ||
+ | сложение | |
‑ | вычитание | |
* | умножение | |
/ | деление (если операнды целочисленные, то выполняется целочисленное деление) | |
% | получение остатка от деления (только для целочисленных операндов) | |
Поразрядные операции | ||
<< | поразрядный сдвиг влево; x<<y – целочисленный операнд x сдвигается влево на y двоичных разрядов, освободившиеся разряды обнуляются | |
>> | поразрядный сдвиг вправо; x>>y – целочисленный операнд x сдвигается вправо на y двоичных разрядов, освободившиеся разряды обнуляются, если операнд беззнакового типа и заполняются знаковым разрядом в противном случае | |
& | поразрядная операция логического И | |
| | поразрядная операция логического ИЛИ | |
^ | Поразрядная операция сложения по модулю 2 (исключающее ИЛИ) | |
Операции сравнения – результат операции истина (не 0) или ложь (0) | ||
< | меньше | |
> | больше | |
<= | меньше или равно | |
>= | больше или равно | |
== | равно | |
!= | не равно | |
Логические бинарные операции | ||
&& | логическая операция И, используется для в условных операторах, например, условие1 && условие2 | |
|| | логическая операция ИЛИ, используется для в условных операторах, например, условие1 || условие2 | |
Операции присваивания | ||
= | операция простого присваивания | |
+=, -=, *=, /=, %=, >>=, <<=, &=, |=, ^= | операция составного присваивания; выражение вида a += b эквивалентно a = a+b | |
Другие операции | ||
выражение1 ? выражение2 : выражение3 | условная (тернарная) операция. Порядок выполнения операции: вычисляется выражение1, если оно истинно, то результатом операции является значение выражения2, если ложно – значение выражения3. Например, выражение x = x>0?x:-x позволяет получить модуль х. | |
, | операция запятая (операция перечисления). В выражении a,b,c,d результатом операции будет значение последнего операнда, т.е. d | |
(тип) | операция явного преобразования (приведения) типа, например, (int)a – приведение переменной а к типу int | |
Приоритеты операций в выражениях
В следующей таблице показаны приоритеты и очередность вычислений всех операторов. Операторы, перечисленные на одной строке, имеют одинаковый приоритет: строки упорядочены по убыванию приоритетов; так, например, *, / и % имеют одинаковый приоритет, который выше, чем приоритет бинарных + и -.
Операторы | Выполняются |
() [] -> . | слева направо |
! ~ ++ -- + - * & (type) sizeof | справа налево |
* / % | слева направо |
+ - | слева направо |
<< >> | слева направо |
< <= > >= | слева направо |
== != | слева направо |
& | слева направо |
^ | слева направо |
| | слева направо |
&& | слева направо |
|| | слева направо |
?: | справа налево |
= += -= *= /= %= &= ^= |= <<= >>= | справа налево |
, | слева направо |
Содержание отчета
Отчет по лабораторной работе должен содержать:
- задание лабораторной работы, соответствующее варианту
- текст программы
- результаты работы программы
Лабораторная работа 4
Цель работы
Организация циклов в языке Си.
Задание
Составить программу, выполняющую вычисление конечной суммы N элементов и сравнения полученного значения с контрольным значением.
№ | Вид суммы | Контрольное значение |
13+23+33+43+…+N3 | N2*(N+1) 2/4 | |
13+33+53+73+…+(2*N-1)3 | N2*(2N2-1) | |
2+4+6+8+…+N | N*(N+1) | |
12+22+32+42+…+N2 | N*(N+1)(2*N+1)/6 | |
12+32+52+72+…+(2*N-1)2 | N*(4N2-1)/3 | |
1+2+3+4+…+N | N*(N+1)/2 |
Теоретическая часть
Оператор цикла for
Данный оператор цикла имеет вид:
for([выражение1]; [выражение2]; [выражение3])
оператор;
Структурная схема алгоритма выполнения оператора цикла for приведена на рис. 3.
Рис. 3 Алгоритм выполнения оператора for
"Выражение1" выполняется один раз перед началом цикла. Оно НИ В КОЕМ случае не задает начальные условия цикла, поскольку не является обязательным элементом оператора for, но чаще всего используется именно для этих целей J.
"Выражение2" задает условие окончания цикла – когда "выражение2" становится ложным, цикл заканчивается.
"Выражение3" вычисляется в конце выполнения каждого тела цикла, и, наверное, поэтому используется для изменения переменной, используемой в качестве параметра цикла.
Оператор-тело цикла может быть пустым оператором, простым или составным.
Пустой оператор состоит только из символа точка с запятой (;). В операторах цикла пустой оператор используется тогда, когда тела цикла не требуется, но по синтаксису нужен хотя бы один оператор.
Если в операторе цикла for опустить все три выражения, то такой цикл будет бесконечным, поскольку пустое "выражение2" всегда считается истинным.
Оператор цикла while
Оператор цикла while имеет вид:
while(выражение)
оператор;
Структурная схема алгоритма выполнения оператора цикла while приведена на рис. 4.
Рис. 4 Алгоритм выполнения оператора while
Сначала вычисляется значение выражения, если оно ложно, то управление передается на следующий за циклом оператор. Если условие истинно, то выполняется оператор, составляющий тело цикла. Тело цикла может быть пустым, простым или составным оператором.
Оператор do while
Оператор имеет следующую форму записи:
do
оператор;
while(выражение);
Структурная схема алгоритма выполнения оператора цикла while приведена на рис. 5.
Рис. 5 Алгоритм выполнения оператора do-while
Оператор цикла do while используется в тех случаях, когда тело цикла должно выполниться хотя бы один раз. Вначале выполняется оператор, затем вычисляется значение выражения. Если выражение истинно, то цикл повторяется. Если выражение ложно, то управление передается следующему за циклом оператору.
Оператор break
Оператор break используется в операторах цикла и в операторе switch. Его выполнение приводит к выходу из указанных конструкций и переход к следующему оператору программы. Если оператор break находится внутри некоторой совокупности вложенных структур, его действие распространяется только на самую внутреннюю структуру, в которой он непосредственно содержится.
Оператор continue
Его действие заключается в прерывании выполнения тела цикла. После этого вызывается следующая итерация (шаг) этого цикла.
Содержание отчета
Отчет по лабораторной работе должен содержать:
- задание лабораторной работы, соответствующее варианту
- структурную схему алгоритма программы
- текст программы
- результаты работы программы
Лабораторная работа 5
Цель работы
Изучение условных операторов языка Си. Изучение массивов и основных приемов работы с массивами.
Задание
Составить программу, выполняющую действия согласно варианту задания
№ | Задание |
для заданного натурального числа nопределить количество цифр в записи числа, поменяв первую и последнюю цифру в записи числа, определить величину нового числа. | |
для заданных натуральных чисел n,m вычислить сумму m первых и m последних цифр в записи числа n и найти знакочередующуюся сумму цифр числа n. Если m меньше количество цифр в числе n, недостающие цифры принять равными 0. | |
для заданного натурального числа nпоменять все цифры в записи числа n; приписав в начале и конце числа единицы, определить величину нового числа. | |
найти все четверки простых чисел из первых 100 натуральных, принадлежащих одному десятку. | |
для заданного числа n (n<15) построить n строк треугольника Паскаля. | |
найти первые 120 натуральных чисел, сумма цифр которых равна 10 и вывести их на экран в виде матрицы 10Х12. |
Теоретическая часть
Массивы в языке Си
Массив - это группа элементов одинакового типа. Форма объявления массива на языке Си следующая:
тип_данных имя_массива[размер1][[размер2][размер3]…];
"тип_данных" – определяет тип данных, хранящихся в массиве.
"размер1","размер2"… – определяет количество элементов в массиве, т.е. его размерность.
ВНИМАНИЕ!!!Элементы массива в языке Си нумеруются с нуля!
Пример описания одномерного массива из 10 целых чисел и двумерного массива вещественных чисел из 10 строк и 10 столбцов.
int page[9];
float bigmas[9][9];
Обращение к элементам этих массивов происходит следующим образом: page[1] - обращение ко второму элементу массива page, bigmas[0][0] – обращение к первому элементу первой строки массива bigmass.
При задании массива возможна и его инициализация. В этом случае присваиваемые значения указываются в квадратных скобках. Пример инициализации одномерного массива целых чисел:
int s[2]={1,2,3};
Если размер массива не указан, то он определяется по числу начальных значений. Но рекомендуется всегда указывать размер объявляемого массива.
int day[]={31,28,31,30,31,30,31,31,30,31,30,31};
При инициализации многомерных массивов начальные значения для каждой новой строки рекомендуется заключать в фигурные скобки. Если отдельных фигурных скобок нет, то инициализация производится по мере возрастания индексов.
Примеры инициализации двумерного массива:
int s[1][2]={{4,5,6},{7,8,9}};
int f[1][2]={10,11,12,13,14};
char p[2][2]={{'n'},{'y'}};
Массив s инициализируется полностью заданными значениями. В массиве f из его шести значений (размер массива f - 2 строки и 3 столбца) инициализируется только первые 5 элементов (это элементы с индексами 0,0 0,1 0,2 1,0 1,1). В массиве p инициализируются только 2 элемента: p[0][0]='n' и p[1][0]='y'. Если задан размер массива, то значения, не заданные явно, принимают значения, равные 0.
Если не проинициализировать элементы массива перед началом работы с ним, то внешние и статические массивы инициализируются нулем, а автоматические и регистровые будут содержать "мусор", оставшийся в этом участке памяти.
Указатели и массивы
В языке Cи существует сильная взаимосвязь между указателями и массивами, причем эта связь настолько сильна, что указатели и массивы фактически надо рассматривать одновременно.
Любое действие, которое достигается индексированием массива, может быть выполнено и с помощью указателей. Вариант с указателями, в общем-то, будет работать быстрее, но он, по крайней мере для начинающих, несколько тяжеловат для понимания.
Описание int a[10] определяет массив а размером в 10 элементов, т.е. это блок из 10 последовательных объектов, именуемых a[0], a[1],..., a[9]. Запись a[i] обозначает элемент в i-й позиции от начала.
Если pa – это указатель на целое значение, описанный как int *pa, то присваивание pa=&a[0] присваивает pa адрес нулевого элемента массива a, т.е. pa содержит адрес a[0]. Если теперь выполнить присваивание x=*pa, то в переменную x будет скопировано содержимое a[0].
Если pa указывает на отдельный элемент массива а, то по определению pa+1 указывает на следующий элемент, и, вообще, pa-i указывает на i-й элемент перед pa, а pa+i – на i-й элемент после. Таким образом, если pa указывает на a[0], то *(pa+1) относится к содержимому a[1], pa+i есть адрес a[i], a *(pa+i) есть содержимое a[i].
Эти замечания справедливы вне зависимости от типа переменных в массиве а. Определение операции "добавление 1 к указателю" и другой адресной арифметики подразумевает масштабирование, связанное с размером памяти для объекта, на который показывает указатель. Таким образом, при вычислении выражения pa+i значение i, прежде, чем будет добавлено к pa, будет умножено на размер объекта, на который указывает pa.
Фактически любое упоминание массива приводится транслятором к ссылке на начало этого массива, т.е. имя массива есть ссылочное выражение. Это приводит к небольшому числу полезных следствий. Так как имя массива есть синоним для местоположения нулевого элемента, то присваивание pa=&a[0] можно записать и в таком виде: pa=a.
Не удивительно теперь, по крайней мере, на первый взгляд, что значение a[i] можно записать как *(a+i). Вычисляя a[i], транслятор сразу же переводит его в *(a+i) – эти две формы полностью эквивалентны. Применяя операцию & к обеим частям этого равенства, получаем, что &a[i] и a+i также идентичны: a+i - адрес i-го элемента относительно а.
С другой стороны, если pa - указатель, то его можно использовать с индексом: pa[i] идентично *(pa+i). Короче, любой массив и индексное выражение можно записать как указатель и смещение и, наоборот, причем это можно делать даже в одном операторе.
Однако между именем массива и указателем есть одно различие, о котором следует всегда помнить. Указатель есть переменная, так что pa=a и pa++ есть осмысленные операции. Имя же массива – константа, а не переменная, поэтому операторы типа a=pa или a++, или p=&a недопустимы.
Пример. Программа распечатки содержимого одномерного массива с использованием указателей. Массив предварительно проинициализирован.
#include<stdio.h>
void main()
{
int p[5]={1,2,3,4,5};
int *ref;
ref=p;
printf("\n");
for(int i=0;i<5;i++)
printf("%d\t",*(ref+i));
}
Рассмотрим теперь, как получить доступ к элементу многомерного массива, используя указатели. Допустим, в программе описан трехмерный массив и указатель на него:
int arr[L][M][K], *ptr;
ptr=&arr[0][0][0];
Массив arr состоит из L элементов, каждый из которых – двумерный массив MхN. Каждый массив MхN в памяти располагается по строкам. Необходимо получить доступ к элементу arr[i][j[k]. Последовательно это вычисляется следующим образом:
ptr - адрес 0-го массива M на N
ptr+i*(M*N) - адрес i-го массива M на N
ptr+i*(M*N)+j*N - адрес j-й строки i-го массива M на N
ptr+i*(M*N)+i*N+k - адрес элемента arr[i][j][k]
*(ptr+i*(M*N)+i*N+k) - значение элемента arr[i][j][k]
Условный оператор
В языке Си условный оператор имеет две формы записи:
if (выражение)
оператор1
оператор3
и
if (выражение)
оператор1
else
оператор2
оператор3
Если выражение истинно, то выполняется оператор1, если оно ложно, то при использовании первой формы записи условного оператора управление передается оператору3, а при использовании второй формы записи выполняется оператор2. Если же выражение истинно, то выполняется оператор 1
Если в условном операторе необходимо выполнить несколько действий, то в качестве оператора1 (или оператора2) используется составной оператор { }.
В языке Си допускается использование вложенных операторов if. В этом случае, если используется ключевое слове else и нет фигурных скобок, то else относится к ближайшему ключевому слову if.
Пример. Рассмотрим два примера программы
Пример 1
if(a==b)
{
if(a==0)
b=2;
}
else a=3
Пример 2
if(a==b)
if(a==0)
b=2;
else a=3
В первом примере else относится к первому if, а во втором - ко второму.
Дата: 2016-10-02, просмотров: 262.