Операции С, их приоритеты и использование. Преобразование типов
Цель работы: Изучить основные логические, арифметические и другие операции С,научиться правильно составлять выражения С, изучить приоритеты операций С, научиться использовать преобразование типов.
Теоретические сведения
Язык С имеет мощную арифметическую и логическую основу, которая позволяет быстро, компактно и эффективно писать код программы. В С разработано множество базовых арифметических и логических операций, а также функции библиотеки математической поддержки языка. Операндами операций могут быть выражения определённых видов, зависящих от операции. В простейшем случае операндами являются переменные. Переменные, прежде чем они будут использованы, должны быть объявлены с определённым спецификатором типа.
Таблица 19 - допустимые операции над переменными
АРИФМЕТИЧЕСКИЕ ОПЕРАЦИИ | ||
Операция | Пояснение | Пример |
* | Умножение | A=b*c; |
/ | Деление (для целых – нацело) | a=b/c; |
% | Остаток от деления (для целых) | a=b%c; |
<операция x> = + = ; - = ; * = ; / = ; % = | составное присваивание Изменить и заменить | a+=3; или a=a+3; a%=c; или a=a%c; |
++ | Инкремент(увеличить на 1) | с++ ; или с=с+1; + + а |
-- | Декремент(уменьшить на 1) | с-- ; или с=с-1; - - а |
+ | Бинарный плюс (сложение) | A=b+c; |
- | Бинарный минус (вычитание) | A=b-c; |
ЛОГИЧЕСКИЕ ОПЕРАЦИИ | ||
Операция | Пояснение | Пример |
&& | "И" | a&&b |
|| | "ИЛИ" | a||b |
! | "НЕ" | !a |
== | "РАВНО" | a= =b |
!= | "НЕ РАВНО" | a!=b |
> | "БОЛЬШЕ" | a>b |
>= | "БОЛЬШЕ ИЛИ РАВНО" | a>=b |
< | "МЕНЬШЕ" | a<b |
<= | "МЕНЬШЕ ИЛИ РАВНО" | a<=b |
ПОБИТОВЫЕ ОПЕРАЦИИ (ПОРАЗРЯДНЫЕ) | ||
Операция | Пояснение | Пример |
& | “И” (and) | 1&1=1; 1&0=0 ;0&0=0; |
| | “ИЛИ” (or) | 1 | 1=1 ; 1 | 0 =1 ; 0 | 0=0; |
^ | “ИСКЛЮЧАЮЩЕЕ ИЛИ” | (xor) 1^1 = 0 ; 1 ^ 0=1 ; 0^0=0; |
~ | “ОТРИЦАНИЕ” (not) | ~1=0; ~0=; |
<< | “СДВИГ ВЛЕВО” (shl) | 0001b<<2=0100b; (буква b означает что число двоичное) |
>> | “СДВИГ ВПРАВО” (shr) | 0010b >> 1=0001b; |
<операция_х>= | составное присваивание. Изменить и заменить, где <операция_х> может быть: &,|,^,>>,<<. | а&=b или a = &b a^=bилиa = a^b a<<=bили a<<b |
Приоритет операций и порядок выполнения (ассоциативность)
Приоритет и ассоциативность операций влияют на порядок группирования операндов и порядок вычислений в выражениях С. Например, приоритет выполнения операций необходимо учитывать при составлении сложных арифметических формул.
Операции, приведенные в одной группе таблицы, имеют одинаковый приоритет и ассоциативность. Порядок убывания приоритета сверху вниз.
Таблица 20 - Приоритет операций
Приоритет | Знак операции | Тип операции | Ассоциативность (порядок выполнения) | |||
() [ ] .–> | Первичные | → слева направо | ||||
– ~ ! * & ++ -- sizeof, приведение типов ( ) | Унарные | ← справа налево | ||||
* / % | Мультипликативные | → | ||||
+ - | Аддитивные | → | ||||
<< >> | Сдвиги | → | ||||
< > <= > = | Отношение | → | ||||
= = ! = | Отношение | → | ||||
& | Поразрядное "и" | → | ||||
^ | Поразрядное исключающее "или" | → | ||||
| | Поразрядное включающее "или" | → | ||||
&& | Логическое "и" | → | ||||
| | | Логическое "или" | → | ||||
? : | Условная (тернарная) | ← | ||||
= | * = | / = | % = | Простое и составное присваивание | ← | |
+ = | – = | << = | >> = | |||
& = | | = | ^ = | ||||
, | Последовательное вычисление | → |
Если несколько операций одного приоритета встречаются в выражении, то они применяются в соответствии с ассоциативностью.
Примеры. а = b&ÆхFF + 5; // вычисляется как а = b&(Æх FF + 5);
b=а + с >> 1; // как b=(а +с) >> 1;
с = а + + + b/5; //какс=(а + +) + ( b/5);
Мультипликативные, аддитивные и поразрядные операции обладают свойством коммутативности. Компилятор вычисляет выражения с учётом приоритета в любом порядке, даже если есть скобки. Определённый порядок вычисления (,) операндов гарантируют операции: последовательного вычисления, логические «И» (&&)и «ИЛИ» (||), условная операция(? :).
Запятые в вызовах функций не являются операциями последовательного вычисления и не обеспечивают гарантий вычисления слева направо. Логические операции вычисляют минимальное число операндов, необходимых для определения результатов выражения.
func (i + 1, i = j + 2); //. Не гарантирует порядок вычисления фактических
// аргументов
i= 0;// iимеет тип int по умолчанию
a [++ i] = i; // порядок вычисления левого и правого операндов не
// гарантируются a [0] = 0 или a[1]=1
(x - 5) && ++ i // Если x =5, то ++ i не вычисляется
int x, y, z, f();
z = x > y || f(x, y); // Если x > y,то значение z = 1 «Истина», а f( ) –не
// вызывается
// если x £ y, то f() вызывается, тогда z=0,
// eсли f( ) возвращает нулевое значение, или z = 1,
// если f( ) возвращает не нулевое значение
// printf (“%d %d \n“, ++n, p()2, n)
//в функцию может передаваться n или n+1.
Преобразование типов
В выражениях С переменные различных типов в ряде случаев могут использоваться совместно; например, переменные типа char могут присутствовать в выражениях одновременно с переменными типа int.
Пример совместного использования целых и символьных переменных.
char ch='a', ans; //объявление переменныхchиans
printf("значение ch + 3 = %d", ch+3); //вывод значенияch+3
ans = ch % 3;// определение остатка от целочисленного деления
printf("\n\n значение ans = % d\n", ans);
Поскольку char это целый тип, для него применимы все операции, операнды которых могут иметь тип int. Целые по умолчанию - это величины со знаком signed.
С переменными вещественного типа (float, double и др.) применимы все операции, допустимые для целого типаint,за исключением операции остатка от деления (%).
Преобразования типов бывают явные и неявные. Синтаксис операции явного преобразования типа
(<новый_тип>) <операнд>
или
<новый_тип> (<операнд>).
Ряд операций может в зависимости от типов своих операндов вызывать неявное преобразование значения операнда из одного типа в другой (преобразование по умолчанию).
Рассмотрим результаты таких преобразований.
Данные типа charили short intмогут использоваться везде, где используется тип int. Во всех случаях значение преобразуется к целому типу
Арифметические операции над числами с плавающей точкой (floatиdouble) по умолчанию выполняются с двойной точностью.
Преобразования целочисленных значений в вещественные (плавающие) выполняется без осложнений, но возможна потеря точности, если для результата не предусмотрено достаточного количества битов. Преобразование значений с плавающей точкой к целочисленному типу машинно-зависимо. Результат неопределен, если значение не попадает в отведенный диапазон.
Если целое без знака (unsigned)используется вместе с простым целым, то простое целое и результат преобразуются в целое без знака.
Подавляющее большинство операций вызывает преобразование и определяет типы результата в соответствии с вышеприведенными правилами. Приведенная ниже схема преобразований реализуется по умолчанию при вычислении выражений С.
Сначала любые операнды типов char, unsigned char или short преобразуются в int, а любые операнды типа float преобразуются в double.
Затем, если какой-либо операнд имеет тип double, то другой преобразуется к типу double и типом результата будет double.
В случае, если какой-либо операнд имеет тип unsigned long, то другой преобразуется к типу unsigned long и это же будет и типом результата.
В случае, если какой-либо операнд имеет тип long, то другой преобразуется к типу long и это же будет типом результата.
В случае, если операнд имеет тип unsigned, то другой операнд преобразуется к типу unsigned, и это будет типом результата.
Объект типа void* (указатель на пустой)может быть объявлен для указания на объекты неизвестного типа.
Преобразование типа такого указателя задаётся с помощью явной операции преобразования типов.
Указатель может преобразовываться в любой из целых типов, достаточно большой для того, чтобы вместить его.
Указатель на один тип может быть преобразован в указатель на другой тип. При этом возможно преобразование указателя в указатель на объект меньшего размера и обратно без изменений.
Например, функция выделения памяти может принимать размер (в байтах) объекта, для которого выделяется память, и возвращать указателю несоответствующий тип, который может таким образом использоваться.
extern void* allos ();
doube* dp;
dp = (doube*) allos (sizeof (doube));
*dp = 2,6/8,4
Пример 17
#include <stdio.h>
#include <conio.h>
#include <math.h>
main()
{float r1,r2;
int a,b,b1;
unsigned c,d;
char e,f;
unsigned char g;
float f1,f2;
clrscr();
printf("ввод первого u второго вещественных чисел: ");
scanf("%f %f",&r1,&r2);
//printf("\n");
printf("вывод результатов операций для чисел: %5.2f %5.2f\n",r1,r2);
printf("!r1= %d ",!r1); printf("!r2= %d ",!r2);
printf("r1>r2 %d ",r1>r2); printf("r1<r2 %d\n",r1<r2);
printf("r1||r2 %d ",r1||r2); printf("r1&&r2 %d ",r1&&r2);
printf("r1==r2 %d ",r1==r2); printf("r1>=r2 %d\n",r1>=r2);
printf("r1<=r2 %d ",r1<=r2); printf("r1!=r2 %d\n",r1!=r2);
//Вложенный блок, переменные переобъявлены: int r1,r2; float b;
{int r1,r2;
float b;
printf("ввод первого u второго целого числа: ");
scanf("%d %d",&r1,&r2);
// printf("\n");
printf("вывод результатов операций для целых чисел: %2d %2d\n",r1,r2);
printf("!r1= %d ",!r1); printf("!r2= %d ",!r2);
printf("r1>r2 %d ",r1>r2); printf("r1<r2 %d\n" ,r1<r2);
printf("r1||r2 %d ",r1||r2); printf("r1&&r2 %d ",r1&&r2);
printf("r1==r2 %d ",r1==r2); printf("r1>=r2 %d\n" ,r1>=r2);
printf("r1<=r2 %d ",r1<=r2); printf("r1!=r2 %d ",r1!=r2);
printf("~r1 %d ",~r1); printf("r1|r2 %d\n" ,r1|r2);
printf("r1^r2 %d ",r1^r2); printf("r1&r2 %d ",r1&r2);
printf("r1<<r2 %d ",r1<<r2); printf("r1>>r2 %d\n" ,r1>>r2);
printf("Исходные значения: r1=%d r2=%d\n",r1,r2);
r2=r1++; //Постфиксные операции а1++ а1--
printf("r2=r1++; r1=%d r2=%d\n",r1,r2);
--r1; r2=++r1; //Префиксные операции ++а1 --а1
printf("--r1; r2=++r1; r1=%d r2=%d\n",r1,r2);
r1-=4; r2+=5; //Составное присваивание
printf("r1-=4; r2+=5; r1=%d r2=%d\n",r1,r2);
a=r2-=2,r1+=5; //Составное присваивание
printf("a=r2-=2,r1+=5; r1=%d r2=%d a=%d\n",r1,r2,a);
a=(r1<r2)?r1:r2;//Тернарная операция если r1<r2, то а=r1 иначе а=r2
printf("a=(r1<r2)?r1:r2; a=%d\n",a);
a=r2%r1; //Остаток от деления целых
printf("а=r1%r2; "); printf("а=%d\n",r2%r1);
a=r2/r1; //Деление целых
printf("a=r2/r1; a=%d\n",a);
b=(float)r2/(float)r1; //Деление c преобразованием типов
printf("b=(float)r2/(float)r1; b=%f\n",b);
}
float q=1.3,q1=2.4,raz;
printf("Введите переменные a-(int), \
c-(unsigned), g-(unsigned char)\n");
scanf("%i,%u,%uc",&a,&c,&g);
b = (a & (c<<3));
b1 = (a & 3) << 7;
f = (a & 3) << 7;
f1 = q / (c | 0x3E);
f2 = a / (c | 0x3E);
raz=exp(q+q1)/4;
printf("g=%u, q=%5.2f, q1=%7.2f, b=%i, b1=%i, \
\n",g,q,q1,b,b1);
printf("f=%i, f1=%6.3f, f2=%6.3f, raz=%f\n",f,f1,f2,raz);
getch(); return 0;
}
/* ввод первого u второго вещественных чисел: 56 7
вывод результатов операций для чисел: 56.00 7.00
!r1= 0 !r2= 0 r1>r2 1 r1<r2 0
r1||r2 1 r1&&r2 1 r1==r2 0 r1>=r2 1
r1<=r2 0 r1!=r2 1
ввод первого u второго целого числа: 45 2
вывод результатов операций для целых чисел: 45 2
!r1= 0 !r2= 0 r1>r2 1 r1<r2 0
r1||r2 1 r1&&r2 1 r1==r2 0 r1>=r2 1
r1<=r2 0 r1!=r2 1 ~r1 -46 r1|r2 47
r1^r2 47 r1&r2 0 r1<<r2 180 r1>>r2 11
Исходные значения: r1=45 r2=2
r2=r1++; r1=46 r2=45
--r1; r2=++r1; r1=46 r2=46
r1-=4; r2+=5; r1=42 r2=51
a=r2-=2,r1+=5; r1=47 r2=49 a=49
a=(r1<r2)?r1:r2; a=47
а=r1%r2; а=2
a=r2/r1; a=1
b=(float)r2/(float)r1; b=1.042553
Введите переменные a-(int), c-(unsigned), g-(unsigned char)
-34 6 7
g=122, q =1.30, q1=2.40, b=512, b1=256,
f=0, f1=0.010, f2=519.000, raz=10.111827 */
Ход работы
1 Изучить теоретические сведения.
2 Для использования арифметических, логических и других операций, приведенных в таблице задаться выражениями, содержащими указанные операции. В качестве базы принять лабораторную работу №5.
3 Ознакомившись с приоритетом операций, показать порядок выполнения операций в конкретных выражениях с использованием скобок.
4 Для преобразования типов переменных использовать явное и неявное преобразование типов.
5 Разработать алгоритм и программу, отладить ее на компьютере.
6 Изучить выполнение операций и тип результата.
7 Получить результаты и сделать выводы по работе.
8 Оформить отчет.
9 Подготовиться к защите лабораторной работы, изучив вопросы по данной теме.
Индивидуальное задание к лабораторной работе
Составить программу для вычисления арифметических, логических и битовых выражений. Преобразовать полученные результаты согласно индивидуальному заданию приведенному в таблице 21.
Таблица 21 - Индивидуальные задания
вариант | арифметическая операция | арифметическая операция | логическая операция | битовая операция | преобразование: явное |
(a + b)*с | (c/ab) | чётное | a << = b | int®short | |
(a*b)-с | a|=b-c | нечётное | a >> = b | long®int | |
(a / b)+++b | a<<=b/c | (a==c)&& (b<a) | a^=b | signed®unsigned | |
++b-(~a) | a%=b | a > b | a%=b+c | double®float | |
(a+b)* sizeof(c) | (a+b)1/c | a < b | a>>=5 | int®char | |
--c*(*&a+b) | (a+b)/5 | a>=b | a&=abs(c) | long double ®double | |
A2+b2+c2 | 15ab-(1/4c) | a!=b | a<<=6 | float ®long | |
5b3-2a+c | c2+8b+10a | a||b | a&=b+c | float®char | |
4a2+5b2 | 3a2+4b-8 | a&&b | a^=b | double®int | |
3ab-4c | A3+b2-8c | !a | a%=(c+10) | double®unsigned long int | |
c2+5a3-b | A2+b2-6c | (a<b)|| (c>5) | a|=20 | float®unsigned | |
2a+4c-b4 | A+2b+3c | a>=b | a&=(b+c) | int®char | |
A2+b2 | 2(a+b)-c4 | (a>=b)|| (b<c) | a^=abs(b-c) | long double ®double | |
(a+b)2 | c2-b3 | кратное а | (a&b)^c | double®float | |
2ac-3cb | 3a-4cb | (c!=b)|| (a==10) | (a|b)>>c | double®unsigned long int | |
5c+2a4 | c5-2ab | (c<=a)&&(b!=a) | (b&&c)|(a--) | signed®unsigned | |
A+b+c | 6a+3b3+c | (b==0)|| (c<=a) | a|=b+c | int®short | |
2a+3b+4c | 4abc | (a==1)|| (b<c) | a|= (c+10) | double®int | |
A2+b3+c4 | A2+(b-c)5/3 | (a<b)&& (a>c) | a|=20 | double®float | |
A+2b+3c | (a+4b)1/3-c2 | (a>=b)|| (a<=10) | (a&b)^c | int®char | |
2(a+b)-c4 | A1/3+(b3-c) | (b<c)&& ( b!=a) | a|=b+c | long double ®double | |
c2-b3 | B3+(a-4c)1/5 | (b<c)|| (a<b) | a&=b+c | double®float | |
3a-4cb | A+2b+3c | (a==1)&&( c!=0) | a&=abs(c-b) | int®char | |
c5-2ab | 2(a+b)-c4 | (c==0)|| (b!=100) | a%=b+c | long double ®double | |
6a+3b3+c | c2-b3 | (b!=0)&& (b<c) | (a&b)^c | int®char | |
4abc | 3a-4cb | (b!=a)|| (b<=c) | a%=b+c | long double ®double | |
A2+(b-c)5/3 | c5-2ab | (c<=12)&&(c>=24) | (b|c)|(a--) | double®unsigned long int | |
(a+4b)1/3-c2 | 6a+3b3+c | ((a-b)<c)|| ((a*c) <100) | a<<=6 | float®unsigned | |
A1/3+(b3-c) | 4abc | (a<10)? (b):(b-c) | (b&c)|(a--) | int®char | |
B3+(a-4c)1/5 | A2+(b-c)5/3 | (b<=10)|| ((a+b)< (b-c)) | a^=abs(b-c) | long double ®double |
Контрольные вопросы для подготовки и самостоятельной работы
1 Какие операции называются унарными, бинарными, тернарными?
2 Сколько групп приоритетов принято в С?
3 В какой последовательности выполняются операции с одинаковым приоритетом?
4 Что означает свойство коммутативности?
5 Какие операции гарантируют порядок вычисления своих операндов?
6 Для чего применяют первичные операции?
7 Какой тип операндов допустим для различных операций?
8 Все ли операнды вычисляются в выражениях, содержащих логические операции?
9 Для чего применяют преобразование типов?
10 Назовите правила неявного преобразования типов. В каких случаях возможна потеря информации при преобразовании типов?
11 В каком порядке будет выполняться конструкция f(x)&&g(y) и как будет интерпретироваться результат вызова функций, результат выражения в целом?
12 Объясните примеры, приведенные в теоретической части.
Лабораторная работа №10
Массивы. Селективная обработка массивов
Цель работы: изучить работу с массивом как с составным типом данных, приёмы ввода и вывода данных, обработку одномерных массивов.
Теоретические сведения
Массивы и переменные с индексами. Математическим понятием, которое привело к появлению в языках программирования понятия "массив", являются матрица и ее частные случаи: вектор-столбец или вектор-строка. Элементы матриц в математике принято обозначать с использованием индексов. Существенно, что все элементы матриц либо вещественные, либо целые и т.п. Такая "однородность" элементов свойственна и массиву, определение которого описывает тип элементов, имя массива и его размерность, т.е. число индексов, необходимое для обозначения конкретного элемента. Кроме того, в определении указывается количество значений, принимаемых каждым индексом. Например, int a[10]; определяет массив из 10 элементов а[0], а[1], ..., а[9]. float Z[13][[6]; определяет двумерный массив, первый индекс которого принимает 13 значений от 0 до 12, второй индекс принимает 6 значений от 0 до 5. Таким образом, элементы двумерного массива Z можно перечислить так:
Z[0][0], Z[0] [1], Z[0][2],...,Z[12][4], Z[12][5]
В соответствии с синтаксисом Си в языке существуют только одномерные массивы, однако элементами одномерного массива, в свою очередь, могут быть массивы. Поэтому двумерный массив определяется как массив массивов. Таким образом, в примере определен массив Z из 13 элементов-массивов, каждый из которых, в свою очередь, состоит из 6 элементов типа float. Нумерация элементов любого массива всегда начинается с 0, т.е. индекс изменяется от 0 до N-1, где N -количество значений индекса.
Ограничений на размерность массивов, т.е. на число индексов у его элементов, в языке Си теоретически нет. Стандарт языка Си требует, чтобы транслятор мог обрабатывать определения массивов с размерностью до 31. Однако чаще всего используются одномерные и двумерные массивы. Рассмотрим на простых вычислительных задачах некоторые приемы работы с массивами.
Вычисление среднего. Введя значение n из диапазона (0<n<=100) и значения n первых элементов массива х[0], х[1],...,х[n-1], вычислить среднее и оценку дисперсии значений введенных элементов массива. Задачу решает следующая программа:
/* Вычисление среднего */
#include <stdio.h>
void main ( )
{ /*n - количество элементов */
int i,n;/*b-среднее */
float b,x[100];
while (1)
{
printf("\n Введите Значение n=");
scanf("%d", &n);
if ( n > 0 && n <= 100 ) break;
printf("\n Ошибка! Необходимо 0<n<101 ") ;
} /* Конец цикла ввода значения n */
printf("\n Введите Значения элементов:\n");
for( b=0.0,i=0; i<n; i++)
{
printf("x[%d] =", i);
scanf("%f", &x[i]);
b+=x[i]; /* Вычисление суммы элементов */
}
b/=n;/* Вычисление среднего */
printf("\n Среднее =%f, b) ;
}
В программе определен массив х со 100 элементами, хотя в каждом конкретном случае используются только первые n из них. Ввод значения п сопровождается проверкой допустимости вводимого значения. В качестве условия после while записано заведомо истинное выражение 1, поэтому выход из цикла (оператор break) возможен только при вводе правильного значения n, удовлетворяющего неравенству 0<n<101. Следующий цикл обеспечивает ввод n элементов массива и получение их суммы (b).
Инициализация массивов. Инициализация - это объединение определения объекта с одновременным присваиванием ему конкретного значения. Использование инициализации позволяет изменить формат определения массива. Например, можно явно не указывать количество элементов одномерного массива, а только перечислить их начальные значения в списке инициализации:
double d[ ]={1.0, 2.0, 3.0, 4.0, 5.0};
В данном примере длину массива компилятор вычисляет по количеству начальных значений, перечисленных в фигурных скобках. После такого определения элемент d[0] равен 1.0, d[l] равен 2.0 и т.д. до d[4], который равен 5.0.
Если в определении массива явно указан его размер, то количество начальных значений не может быть больше количества элементов в массиве. Если количество начальных значений меньше, чем объявленная длина массива, то начальные значения получат только первые элементы массива (с меньшими значениями индекса):
int M[8]={8,4,2};
В данном примере определены значения только переменных М[0], М[1] и М[2], равные соответственно 8, 4 и 2. Элементы М[3],..., М[7] не инициализируются.
Правила инициализации многомерных массивов соответствуют определению многомерного массива как одномерного, элементами которого служат массивы, размерность которых на единицу меньше, чем у исходного массива. Одномерный массив инициализируется заключенным в фигурные скобки списком начальных значений. В свою очередь, начальное значение, если оно относится к массиву, также представляет собой заключенный в фигурные скобки список начальных значений. Например, присвоить начальные значения вещественным элементам двумерного массива А, состоящего из трех "строк" и двух "столбцов", можно следующим образом:
double А[3][2]={{10,20}, (30,40), {50,60}};
Эта запись эквивалентна последовательности операторов присваивания: А[0][0]=10; А[0][1]=20; А[1][0]=30; А[1][1]=40; А[2][0]=50; А[2][1]=60;. Тот же результат можно получить с одним списком инициализации:
double A[3][2]={10,20,30,40,50,60};
С помощью инициализаций можно присваивать значения не всем элементам многомерного массива. Например, чтобы инициализировать только элементы первого столбца матрицы, ее можно описать так:
double Z[4][6]={{1}, {2}, (3), {4}};
Следующее описание формирует "треугольную" матрицу в целочисленном массиве из 5 строк и 4 столбцов:
int х[5][4]={{1), {2,3}, {4,5,6}, {7,8,9,10} };
В данном примере последняя пятая строка х[4] остается незаполненной. Первые три строки заполнены не до конца.
Ход работы
1 Изучить теоретические сведения.
2 В соответствии с индивидуальным заданием разработать алгоритм инициализации массива, селективной обработки массива.
3 Разработать и набрать программу, отладить её на компьютере, изучить работу операторов.
4 Получить результаты.
5 Оформить отчет.
6 Подготовиться к защите лабораторной работы, изучив контрольные вопросы по данной теме.
Индивидуальное задание к лабораторной работе
Составить программу для обработки массива согласно индивидуальному заданию приведенному в таблице 22
Таблица 22 - индивидуальное задание
Вар. | Условие задачи |
Найти сумму четных чисел массива | |
Вычислить произведение отрицательных чисел массива | |
Определить количество нечетных чисел массива | |
Найти сумму отрицательных чисел массива | |
Определить количество отрицательных чисел массива | |
Вычислить произведение положительных чисел массива | |
Найти сумму положительных чисел массива | |
Определить количество четных чисел массива | |
Вычислить произведение четных чисел массива | |
Найти сумму нечетных чисел массива | |
Определить количество кратных 3 чисел массива | |
Вычислить произведение нечетных чисел массива | |
Найти сумму кратных 3 чисел массива | |
Определить количество не кратных 3 чисел массива | |
Вычислить произведение кратных 3 чисел массива | |
Найти сумму не кратных 3 чисел массива | |
Определить количество кратных 4 чисел массива | |
Вычислить произведение не кратных 3 чисел массива | |
Найти сумму кратных 4 чисел массива | |
Определить количество не кратных 4 чисел массива | |
Вычислить произведение кратных 4 чисел массива | |
Найти сумму не кратных 4 чисел массива | |
Определить количество кратных 5 чисел массива | |
Вычислить произведение не кратных 4 чисел массива | |
Найти сумму кратных 5 чисел массива | |
Вычислить среднее арифметическое положительных четных элементов массива | |
Найти среднее геометрическое отрицательных нечетных элементов массива | |
Найти произведение отрицательных не кратных пяти элементов массива | |
Найти среднее арифметическое элементов массива, находящихся в интервале [-10,20] | |
Найти среднее геометрическое элементов массива, находящихся в интервале [5,20] |
Контрольные вопросы для подготовки и самостоятельной работы
1 С какого числа начинается индексация массивов в языке С?
2 Как объявляется 1-но мерный массив?
3 Какие типы языка С можно и нельзя указывать в качестве типа при объявлении массива?
4 В каких случаях размерность массива при объявлении можно не указывать?
5 Какой тип имеет имя массива?
6 Как осуществляется инициализация элементов массива?
7 Как можно инициализировать массив с элементами типа char?
8 Можно ли использовать средство typedef для объявления типа “массив”?
9 Какие альтернативные формы записи элементов массива можно использовать? Приведите примеры.
10 Каковы правила использования индексных выражений?
11 Существуют ли операции работы с массивами?
12 Какие классы памяти можно использовать при объявлении массивов?
Лабораторная работа №11
Формирование рабочих массивов с помощью
операций селекции исходного массива
Цель работы: изучить и научиться применять обработку массивов по заданным логическим условиям, формирование новых массивов.
Теоретические сведения
Смотри теоретические сведения по предыдущей работе.
Пример 18
/* Разработал Петров Ю.В.
Объявить массивы заданной размерности, выполнить их
инициализацию с применением функции random() и явно.
Получить доступ к элементам массивов с использованием
операторов организации цикла. Переписать положительные
элементы массива x[1],x[2],...,x[N] в массив y[t], а
отрицательные - в массив z[p]. Элементы в массивах y[t]
и z[p] располагать подряд, элементы массива y1[t]
рассчитать для положительных x[i] по формуле
y1[t]=y1[t]+2*exp(b*y[t]-y[t]*y[t]),где b=N/5 */
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
# define N 20
main()
{ clrscr();
randomize();
int i,t=0,p=0,b=N/5;
int x[N],y[N],z[N]; //Объявление одномерного массива (вектора)
float y1[N]={2.3,3.4,4.0,5.2,6.6,7.9,8.34,9.8,10.4,11.2,\
10.1,9.9,8.7,7.5}; //Инициализация первых 14, остальные -0
printf("\nВывод элементов исходного массива y1[ ]\n");
for(i=0;i<N;i++)
{printf(" y1[%2d]=%4.1f",i+1,y1[i]);
if ((i+1)%5==0) printf("\n");
}
printf("\nИнициализация одномерного массива x[N]\n");
for(i=0;i<N;i++)
{ x[i]=random(40)-20;
printf(" x[%2d]=%2d ",i+1,x[i]); //Вывод элементов
if ((i+1)%5==0) printf("\n"); //массива x[ ]
if (x[i]>=0) //Выбор положительных значений
{ y[t]=x[i]; //Расчет элементов массива y1[ ]
y1[t]=y1[t]+2*exp(b*y[t]-y[t]*y[t]); t++;
}
else {z[p]=x[i]; p++;} //Выбор отрицательных значений
}
printf("\nВывод элементов массива y[ ]>0\n");
i=0;
while ( i<t )
{ printf(" y[%2d]=%2d ",i+1,y[i]);
if ((i+1)%5==0) printf("\n");
i++;
}
printf("\n");
printf("\nВывод элементов массива y1[ ] после расчета\n");
i=0;
do
{ printf(" y1[%2d]=%3.2f",i+1,y1[i]);
if ((i+1)%5==0) printf("\n");
i++;
} while ( i<t );
printf("\n");
printf("\nВывод элементов массива z[ ]<0\n");
for(i=0;i<p;i++)
{ printf(" z[%2d]=%2d ",i+1,z[i]);
if ((i+1)%5==0) printf("\n");
}
getch();
return 1;
}
/* Вывод элементов исходного массива y1[ ]
y1[ 1]= 2.3 y1[ 2]= 3.4 y1[ 3]= 4.0 y1[ 4]= 5.2 y1[ 5]= 6.6
y1[ 6]= 7.9 y1[ 7]= 8.3 y1[ 8]= 9.8 y1[ 9]=10.4 y1[10]=11.2
y1[11]=10.1 y1[12]= 9.9 y1[13]= 8.7 y1[14]= 7.5 y1[15]= 0.0
y1[16]= 0.0 y1[17]= 0.0 y1[18]= 0.0 y1[19]= 0.0 y1[20]= 0.0
Инициализация одномерного массива x[N]
x[ 1]= 8 x[ 2]= 10 x[ 3]=- 7 x[ 4]= 13 x[ 5]=- 1
x[ 6]=-14 x[ 7]= 5 x[ 8]= 17 x[ 9]=-14 x[10]=-19
x[11]= 13 x[12]= 8 x[13]=-10 x[14]=-16 x[15]= 5
x[16]= 9 x[17]=-11 x[18]=-12 x[19]=-16 x[20]=- 3
Вывод элементов массива y[ ]>0
y[1]= 8 y[2]=10 y[3]=13 y[4]= 5 y[5]=17
y[6]=13 y[7]= 8 y[8]= 5 y[9]= 9
Вывод элементов массива y1[ ] после расчета
y1[1]=2.30 y1[2]=3.40 y1[3]=4.00 y1[4]=5.21 y1[5]=6.60
y1[6]=7.90 y1[7]=8.34 y1[8]=9.81 y1[9]=10.40
Вывод элементов массива z[ ]<0
z[ 1]=- 7 z[ 2]=- 1 z[ 3]=-14 z[ 4]=-14 z[ 5]=-19
z[ 6]=-10 z[ 7]=-16 z[ 8]=-11 z[ 9]=-12 z[10]=-16
z[11]=- 3 */
Ход работы
1 Изучить теоретические сведения
2 В соответствии с индивидуальным заданием, на основе программы предыдущей работы разработать алгоритм, обеспечивающий формирование рабочих массивов по заданным логическим условиям. Операции с массивами вынести в отдельную функцию.
3 Разработать программу, набрать и отладить программу на компьютере.
4 Изучить работу операторов.
5 Получить результаты.
6 Оформить отчет.
7 Подготовиться к защите лабораторной работы, изучив контрольные вопросы по данной теме.
Индивидуальное задание к лабораторной работе
Составить программу для обработки массивов согласно индивидуальному заданию приведенному в таблице 23.
Таблица 23 - Индивидуальное задание
Вар. | Условие задачи |
Дан массив X(15). Сформировать новый массив из четных чисел исходного | |
Дан массив X(25). Сформировать новый массив из нечетных чисел исходного | |
Дан массив D(15). Сформировать новый массив из кратных 3 чисел исходного | |
Дан массив A(10). Сформировать новый массив из отрицательных чисел исходного | |
Дан массив Z(15). Сформировать новый массив из положительных четных чисел исходного | |
Дан массив X(25). Сформировать новый массив из чисел исходного, лежащих в интервале [-3,7] | |
Дан массив Y(10). Сформировать новый массив из нечетных положительных чисел исходного | |
Дан массив D(12). Сформировать новый массив из положительных кратных 3 чисел исходного | |
Дан массив A(8). Сформировать новый массив из отрицательных четных чисел исходного | |
Дан массив C(15). Сформировать новый массив из больших 8 чисел исходного | |
Дан массив B(21). Сформировать новый массив из кратных 4 чисел исходного | |
Дан массив A(12). Сформировать новый массив из отрицательных нечетных чисел исходного | |
Дан массив X(8). Сформировать новый массив из отрицательных не кратных 3 чисел исходного | |
Дан массив G(9). Сформировать новый массив из четных чисел исходного массива, стоящих на нечетных местах | |
Дан массив Y(15). Сформировать новый массив из нечетных, кратных 3 чисел исходного | |
Дан массив A(18). Сформировать новый массив из нечетных, кратных 5 чисел исходного | |
Дан массив Z(10). Сформировать новый массив из четных чисел исходного, лежащих в интервале [1,12] | |
Дан массив A(11). Сформировать новый массив из нечетных чисел исходного, лежащих в интервале [-3,15] | |
Дан массив B(10). Сформировать новый массив из номеров отрицательных четных чисел исходного | |
Дан массив A(8). Сформировать новый массив из номеров отрицательных нечетных чисел исходного | |
Дан массив C(12). Сформировать новый массив из отрицательных чисел исходного, стоящих на четных местах | |
Дан массив F(13). Сформировать новый массив из отрицательных чисел исходного, стоящих на нечетных местах | |
Дан массив H(12). Сформировать новый массив из положительных чисел исходного, стоящих на четных местах | |
Дан массив V(19). Сформировать новый массив из отрицательных чисел исходного, лежащих в диапазоне [-20,-5] | |
Дан массив N(11). Сформировать новый массив из отрицательных кратных 5 чисел исходного | |
Дан массив K(15). Сформировать новый массив из положительных чисел исходного, стоящих на нечетных местах | |
Дан массив Y(11). Сформировать новый массив из отрицательных не кратных 5 чисел исходного | |
Дан массив Z(14). Сформировать новый массив из положительных кратных 5 чисел исходного | |
Дан массив R(13). Сформировать новый массив из отрицательных кратных 10 чисел исходного | |
Дан массив N(11). Сформировать новый массив из отрицательных кратных 8 чисел исходного |
Контрольные вопросы для подготовки и самостоятельной работы
1 Как производится доступ к элементам массива?
2 Какое количество операторов цикла необходимо для обработки главной или побочной диагонали массива?
3 Какие методы сортировки элементов Вы знаете?
4 Можно ли использовать указатель на тип элементов массива в качестве имени массива и что для этого необходимо?
5 Адрес какого элемента содержит имя массива?
6 Какие классы памяти можно использовать при объявлении массива?
7 Какие классы памяти используются по умолчанию?
8 Как размещаются элементы массива в памяти?
9 Как определяется количество байтов, на которое смещается указатель индексного выражения? Зависит ли смещение указателя от типа элементов массива?
Лабораторная работа №12
Сортировка одномерных массивов
Цель работы: изучить и научиться применять обработку массивов по заданным логическим условиям, формирование новых массивов и их сортировка.
Теоретические сведения
Упорядочение в одномерных массивах. Для демонстрации некоторых особенностей вложения циклов и работы с массивами рассмотрим простейшие алгоритмы сортировки. Необходимо, введя значение переменной 1<n<=100 и значения n первых элементов массива а[0],а[1],...,а[n-1], упорядочить эти первые элементы массива по возрастанию их значений. Текст первого варианта программы:
/* Упорядочение элементов массива */
#include <stdio.h>
main( )
{
int n,i,j;
double a[100],b;
while(1)
{
printf("\n Введите количество элементов n=") ;
scanf("%d",&n);
if (n > 1 && n <= 100) break;
printf ("Ошибка! Необходимо 1<n<=100! ") ;
}
printf("\n Введите значения элементов массива:\n");
for(j=0; j<n;j++)
{
printf("a[%d]=”, j+1) ;
scanf(“%lf”,&a[j]);
}
for(i=0; i<n-1; i++)
for(j=i+l; j<n; j++)
if(a[i]>a[j])
{
b=a[i]; a[i]=a[j];. a[j]=b;
}
printf("\n Упорядоченный массив: \n") ;
for(j=0; j<n; j++)
printf("a[%d]=%f\n", j+1,a[j]);
}
При заполнении массива и при печати результатов его упорядочения индексация элементов выполнена от 1 до n, как это обычно принято в математике. В программе на Си это соответствует изменению индекса от 0 до (n-1).
В. программе реализован алгоритм прямого упорядочения - каждый элемент a[i], начиная с а[0] и кончая а[n-2], сравнивается со всеми последующими, и на место a[i] выбирается минимальный. Таким образом, а[0] принимает минимальное значение, а[1] - минимальное из оставшихся и т.д. Недостаток этого алгоритма состоит в том, что в нем фиксированное число сравнений, не зависимое от исходного расположения значений элементов. Даже для уже упорядоченного массива придется выполнить то же самое количество итераций (n-1)*n/2, так как условия окончания циклов не связаны со свойствами, т.е. с размещением элементов массива.
Алгоритм попарного сравнения соседних элементов позволяет в ряде случаев уменьшить количество итераций при упорядочении. В цикле от 0 до n-2 каждый элемент a[i] массива сравнивается с последующим a[i+l] (0<i<n-l). Если a[i]>a[i+l], то значения этих элементов меняются местами. Упорядочение заканчивается, если оказалось, что a[i] не больше a[i+l] для всех i. Пусть k - количество перестановок при очередном просмотре. Тогда упорядочение можно осуществить с помощью такой последовательности операторов:
do {
for (i=0, k=0; i<n-l; i++)
if ( a[i] > a[i+l] )
{
b=a[i]; a[i]=a[i+1]; a[i+1]=b;
k=k+l;
}
n--;
}
while ( k > 0 ) ;
Здесь количество повторений внешнего цикла зависит от исходного расположения значений элементов массива. После первого завершения внутреннего цикла элемент а[n-1] становится максимальным. После второго окончания внутреннего цикла на место а[n-2] выбирается максимальный из оставшихся элементов и т.д. Таким образом, после j-гo выполнения внутреннего цикла элементы a[n-j],...,a[n-l] уже упорядочены, и следующий внутренний цикл достаточно выполнить только для 0<i<(n-j-l). Именно поэтому после каждого окончания внутреннего цикла значение n уменьшается на 1.
В случае упорядоченности исходного массива внешний цикл повторяется только один раз, при этом выполняется (n-1) сравнений, k остается равным 0. Для случая, когда исходный массив упорядочен по убыванию, количество итераций внешнего цикла равно (n-1), а внутренний цикл последовательно выполняется (n-1)*n/2 раз.
Задание. Написать программу на СИ для задачи, указанной в таблице 24. Имя и размер массива выбрать самостоятельно.
Таблица 24
Вар. | Условие задачи |
Найти сумму двух наибольших четных чисел массива | |
Найти произведение двух наибольших нечетных чисел массива | |
Найти произведение двух наибольших четных чисел массива | |
Найти сумму двух наибольших нечетных чисел массива | |
Найти сумму трех наибольших четных чисел массива | |
Найти сумму двух наименьших четных чисел массива | |
Найти сумму двух наименьших нечетных чисел массива | |
Найти сумму трех наименьших нечетных чисел массива | |
Найти сумму двух наименьших положительных чисел массива | |
Найти сумму двух наибольших отрицательных чисел массива | |
Найти сумму трех наименьших положительных чисел массива | |
Найти произведение двух наименьших положительных чисел массива | |
Найти произведение двух наибольших отрицательных чисел массива | |
Найти произведение трех наибольших кратных 5 чисел массива | |
Найти произведение трех наименьших не кратных 4 чисел массива | |
Найти произведение трех наибольших положительных кратных 3 чисел массива | |
Найти произведение трех наименьших отрицательных нечетных чисел массива | |
Найти сумму трех наименьших положительных четных чисел массива | |
Найти сумму трех наибольших нечетных, лежащих в интервале [1,30], чисел массива | |
Найти произведение четырех наименьших, лежащих в интервале [-20,20], чисел массива | |
Найти сумму четырех наименьших кратных 5 и не больших 50 чисел массива | |
Найти произведение двух наибольших и двух наименьших положительных четных чисел массива | |
Найти сумму двух наибольших и двух наименьших отрицательных четных чисел массива | |
Найти произведение двух наибольших и двух наименьших отрицательных нечетных чисел массива | |
Найти сумму двух наибольших и двух наименьших нечетных чисел массива, лежащих в интервале [1,25] | |
Найти произведение двух наибольших и двух наименьших положительных кратных 3 чисел массива | |
Найти сумму двух наибольших и двух наименьших кратных 3 и не меньших 10 чисел массива | |
Найти произведение двух наибольших и двух наименьших кратных 5 и не больших 20 чисел массива | |
Найти сумму трех наибольших, не кратных 5 положительных чисел массива | |
Найти произведение трех наименьших отрицательных кратных 3 чисел массива |
Лабораторная работа № 13
Многомерные массивы.