Операции С, их приоритеты и использование. Преобразование типов

Цель работы: Изучить основные логические, арифметические и другие операции С,научиться правильно составлять выражения С, изучить приоритеты операций С, научиться использовать преобразование типов.

Теоретические сведения

Язык С имеет мощную арифметическую и логическую основу, которая позволяет быстро, компактно и эффективно писать код программы. В С разработано множество базовых арифметических и логических операций, а также функции библиотеки математической поддержки языка. Операндами операций могут быть выражения определённых видов, зависящих от операции. В простейшем случае операндами являются переменные. Переменные, прежде чем они будут использованы, должны быть объявлены с определённым спецификатором типа.

Таблица 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

 

Многомерные массивы.