Диапазон и размер данных основных типов

Тип Размер (в байтах) Диапазон значений
int (signed int) 2 или 4 определяется процессором -32768 - 32767 или -2147483648 - 2147483647
short (signed short int) -32768 - 32767
unsigned short int 0 - 65535
unsigned long int 0 - 4 294 967 295
signed long int -2147483648 - 2147483647
char 0 - 255
signed char -127 - 128
unsigned char 0 - 255
float 3.4Е-38 - 3.4Е38
double 1.7Е-308 - 1.7Е308
long double 3.4E-4932 - 3.4E+4932
bool true, false

 

Примеры объявлений переменных:

int a,b;

long double y;

unsigned short w;

Переменной при объявлении можно присвоить начальное значение (инициализировать ее).

Примеры инициализации переменной:

int k=0; //инициализация со знаком присваивания

int x (100); //инициализация с использованием круглых скобок

const float pi=3.1459; //объявление именованной константы

Переменная, объявленная с модификатором const, называется именованной константной, или просто константой: изменять ее значение в программе нельзя.

Пример программы вычисления площади прямоугольника:

#include <iostream.h>

#include <conio.h>

void main()

{

float a, b, s; //основание, высота и площадь

cout<<”a, b? “;

cin>>a>>b;

s=a*b;

cout<<”s=”<<s;

getch();

}

В этой программе для переменных, в которых хранятся значения размеров прямоугольника и его площадь, указан вещесвенный тип.

После выделения памяти под переменные a, b и s эти переменные содержат случайные значения. При вводе значений в переменные a и b вводимые значения замещают значения, ранее хранившиеся в них. При присваивании переменной s выражения a*b значение выражения вычисляется для текущих значений переменных a и b, а затем результат выражения заносится в область памяти, выделенную под переменную s. При выводе значения переменной s на экран значение s в памяти не разрушается, так как для вывода на экран используется копия значения s.

 

2.2. Операции

 

Операции языка программирования используются для записи выражений. Операции имеют характеристики: арность и приоритет.

Арность операции определяется количеством операндов операции. В соответствии с количеством операндов операции языка С++ разделяются на:

· унарные (имеют 1 операнд);

· бинарные (имеют 2 операнда);

· тернарные (имеют 3 операнда).

Приоритет операции определяет порядок выполнения операций в выражении. Унарные операции имеют больший приоритет, чем бинарные и тернарная операция. Приритет операций в порядке убывания приритетов приведен в табл. 4.

Таблица 4

Операции С++

Категория приоритета Знак операции Наименование операции
:: ( ) [ ] . -> Указание области видимости Вызов функции Индексация Выбор поля структуры по ее имени Выбор поля структуры по указателю на структуру
.*     -> * Обращение к компоненту класса по имени объекта и указателю на компонент Обращение к компоненту класса по указателю на объект и указателю на компонент
+ - ~ ! ++ - - & * new delete sizeof (тип) тип ( ) Унарный плюс Унарный минус Побитовое отрицание Логическое отрицание (НЕ) Инкремент Декремент Вычисление адреса Косвенная адресация Выделение динамической памяти Освобождение выделенной памяти Вычисление размера объекта Каноническая операция приведения типа Функциональная операция приведения типа
* / % Умножение Деление Остаток от целочисленного деления
+ - Сложение Вычитание
<< >> Сдвиг влево Сдвиг вправо
< > <= >= Меньше Больше Меньше или равно Больше или равно
= = != Равно Не равно
& Поразрядная конъюнкция (И)
^ Поразрядное исключающее ИЛИ
| Поразрядная дизъюнкция (ИЛИ)
&& Конъюнкция (И)
| | Дизъюнкция (ИЛИ)
?: Условная операция
= += -= *= /= %= &= |= ^= <<= >>= Операции присваивания
, Операция запятая

2.2.1. Арифметические операции

Арифметические операции используются в арифметических выражениях. Рассмотрим особенности использования некоторых арифметических операций в выражениях.

Деление (/) Если хотя бы один из операндов операции вещественный, то и результат операции вещественный, иначе – тип результата целочисленный (дробная часть результата отбрасывается). Например, результатом вычисления выражения 5/2 будет 2, а результатом вычисления выражения 5.0/2 будет 2.5.

Остаток от целочисленного деления (%) Операнды этой операции могут быть только целого типа. Результат выражения 5%2 равен 1.

Пример программы вычисления суммы старшей и младшей цифр целого положительного трехзначного числа:

#include <iostream.h>

#include <conio.h>

void main()

{

int a, s; //вводимое число и сумма цифр старшей и младшей цифр

cout<< “a? “

cin>>a;

s=a/100+a%10;

cout<< “s=”<<s;

getch();

}

Инкремент и декремент (++, --) Эти унарные операции увеличивают (++) или уменьшают (--) операнд на 1.

Тип операнда может быть: целым, вещественным и указателем. Операнд может быть только переменной. Например, допустимо выражение х++, но выражение 3++ или (a+b)++ в программе С++ недопустимо.

При вычислении выражения с инкрементом или декрементом кроме приоритета операций учитывается форма операций инкремента и декремента. Операции могут быть записаны в одной из двух форм: постфиксной форме, когда знак операции записывается после операнда (х++), или в префиксной форме, когда знак операнда записывается перед операндом (++х). Если инкремент (декремент) записан в префиксной форме, то вначале операнд изменяется, а затем уже измененным участвует в выражении. Если инкремент (декремент) записан в постфиксной форме, то вначале операнд участвует в выражении, а затем уже изменяется.

Пример программы, демонстрирующей различие между префиксной и постфиксной формами операции инкремента:

#include <iostream.h>

#include <conio.h>

void main()

{

int a=2;

int b=2;

int x;

x=++a+4;

cout<<a<<' '<<x<< <<endl;

x=4+b++;

cout<<b<<' '<<x;

getch();

}

Результат работы программы:

3 7

3 6

 

2.2.2. Операции присваивания

Язык С++ содержит несколько операций присваивания:

· обычное присваивание =;

· операции составного присваивания Ɵ=, где Ɵ – это один из знаков бинарных операций: +, -, *, /, %, &, |, ^, >>, <<.

Выражение с операцией составного присваивания aƟ=b эквивалентно выражению a=a Ɵ b.

Примеры операций составного присваивания:

x+=2; //сложить и присвоить, эквивалентно х=х+2

x-=y; //вычесть и присвоить, эквивалентно х=х-y

x*=10; // умножить и присвоить, эквивалентно x=x*10

Операции составного присваивания позволяют сократить запись выражений. Кроме того, операции составного присваивания выполняются быстрее, чем эквивалентные выражения с обычным присваиванием.

Операция = может многократно встречаться в выражении, например, x=y=z=3;

2.2.3. Операции отношения

Операции отношения:

· <, > меньше и больше;

· <=, >= меньше или равно и больше или равно;

· ==, != равно и не равно.

Эти операции используются для задания простых условий.

Пример программы, определяющей попадает ли точка с координатами {x, y} в правую полуплоскость:

#include <iostream.h>

#include <conio.h>

void main()

{

float x, y;

cout<<”x, y? ”;

cin>>x>>y;

if (x>0)

cout<<”Yes”;

else

cout<<”No”;

getch();

}

 

2.2.4. Логические операции

 

Логические операции языка С++:

· && логическое И;

· || логическое ИЛИ;

· ! логическое отрицание.

Они используются для формирования сложных условий путем комбинации простых условий.

Пример программы, определяющей принадлежит ли вещественное число х диапазону [a, b]:

#include <iostream.h>

#include <conio.h>

void main()

{

float x, a, b;

cout<<”a, b? ”;

cin>>a>>b;

cout<<”x? ”;

cin>>x;

if (x>=a && x<=b)

cout<<”Yes”;

else

cout<<”No”;

getch();

}

 

2.2.5. Поразрядные операции

В языке С++ используются следующие поразрядные операции:

· ~ поразрядное отрицание;

· << >> сдвиг влево и сдвиг вправо;

· & поразрядное И;

· ^ поразрядное исключающее ИЛИ;

· | поразрядное ИЛИ.

Они работают с двоичным представлением целых чисел и обеспечивают доступ к отдельному разряду числа. Операнды операций – целые числа или символы.

Поразрядные операции применяются для:

· обработки массивов, каждое данное которых имеет одно из двух возможных значений;

· быстрого умножения и деления чисел на 2n;

· создания битовых масок.

Поразрядное отрицание изменяет значения всех разрядов двоичного представления числа на противоположные значения.

Пример:

unsigned short x, z;

x=2; //0000000000000010

z=~x;//1111111111111101

cout<<z;// 65533

Операция сдвиг влево сдвигает все разряды влево на заданное число, заполняя освободившиеся разряды значением 0.

Пример:

unsigned short x, z;

x=2; //0000000000000010

z=x<<3;//000000000010000 равносильно умножению на 23

cout<<z;//16

Операция сдвиг вправо cдвигает все разряды вправо на заданное число, заполняя освободившиеся разряды значением 0, если число беззнаковое, и значением 0 или значением знакового разряда (в зависимости от реализации С++).

Пример:

unsigned short x, z;

x=16; //0000000000010000

z=x>>3; //000000000000010 равносильно делению на 23

cout<<z; //2

Операция поразрядное И формирует результат, каждый разряд которого равен 1 только тогда, когда соответствующие разряды операндов равны 1.

Пример:

unsigned short x, y, z;

x=2; //0000000000000010

y=3; //0000000000000011

z=x&y;//000000000000010

cout<<z; //2

Операция поразрядное исключающее ИЛИ формирует результат, каждый разряд которого равен 1 только тогда, когда соответствующие разряды операндов различны.

Пример:

unsigned short x, y, z;

x=2; //0000000000000010

y=3; //0000000000000011

z= x^y; //0000000000000001

cout<<z; //1

Операция поразрядное ИЛИ формирует результат, каждый разряд которого равен 1 тогда, когда хотя бы у одного из операндов соответствующий разряд 1.

Пример:

unsigned short x, y, z;

x=2; //0000000000000010

y=3; //0000000000000011

z= x|y; //0000000000000011

cout<<z; //3

Пример программы получения значение i-разряда целого числа (разряды нумеруются справа налево и нумерация начинается с 0):

#include <iostream.h>

#include <conio.h>

void main()

{

int i; //номер разряда

int x, y; //вводимое число и значение i-разряда

cout<<”x? “; cin>>x;

cout<<”i? “; cin>>i;

y=x>>i & 1;

cout<<”y=”<<y;

getch();

}

Тест:

х=5 (0000000000000101), i=2 у: 1

 

2.2.6. Вычисление выражений

 

Выражение – это конструкция языка, вычисляющая значение. Выражения состоят из операндов и операций. Операции выполняются в определенном порядке в соответствии с их приоритетом, ассоциативностью (порядком выполнения операций одного приоритета) и формой (префиксная или постфиксная). Изменить порядок вычисления операций можно с помощью круглых скобок.

В языке С++ допускается в выражениях использовать операнды разных типов. Например, можно складывать два числа, одно из которых 16-разрядное, а другое 32-разрядное или одно целое, а другое вещественное. В этом случае перед вычислением выражения происходит автоматическое преобразование операндов к одному типу (неявное преобразование типов): более короткий тип преобразуется к более длинному, целый операнд преобразуется к вещественному. Преобразование очень естественно и выполняется таким образом, чтобы при вычислениях сохранить значимые разряды операндов и их точность. Исключением из этого правила являются операции присваивания, в которых всегда тип правого операнда преобразуется к типу левого операнда. При этом может происходить потеря точности и значимости (без выдачи сообщений). Полностью правила преобразования типов операндов приведены в [1, 2].

Примеры присваиваний:

int a=32768;

short b;

float c=1.2;

char z;

b=a; cout<<b<<endl; //-32768, потеря значимости

a=c; cout<<a<<endl; //1, потеря точности

c=a; cout<<c<<endl; //1

z=65; cout<<z<<endl; //А

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

· каноническая форма: (тип) операнд;

· функциональная форма: тип (операнд).

Пример программы, вычисляющей среднее арифметическое трех целых чисел:

#include <iostream.h>

#include <conio.h>

void main()

{

int a, b, c;

float avg; //среднее арифметическое

cout<<”a, b, c? “;

cin>>a>>b>>c;

avg= float(a+b+c)/3;

cout<<”avg=“<<avg;

getch();

}

Тест:

a=4, b=5, c=4 результат: 4.3333

 

3. Структурное программирование

 

3.1. Общая характеристика операторов

 

Оператор – элемент текста программы, выражающий законченное действие. Любой алгоритмический язык содержит операторы, поддерживающие три алгоритмические структуры: следование, развилка, повторение. Для удобства программирования в языках содержится несколько реализаций алгоритмических структур, например, три оператора цикла или условный оператор и оператор выбора для программирования ветвлений. Язык С++ не является исключением. Кроме операторов, поддерживающих базовые алгоритмические структуры, в С++ есть и другие операторы, использование которых в некоторых случаях делает программу более простой. К таким операторам относятся: goto, break, continue, пустой оператор.

Язык С++ содержит 12 операторов. Все операторы заканчиваются точкой с запятой. Любой оператор может быть помечен меткой. Метка имеет имя и отделяется от оператора двоеточием, например, Met1: x=2;

 

3.2. Оператор-выражение

Оператор-выражение используется для программирования алгоритмов линейной структуры. Он изменяет значение переменной.

Синтаксис оператора:

Выражение;

Примеры операторов-выражений: х=2; a++; d+=2;

 

3.3. Условный оператор

 

Условный оператор используется для программирования разветвляющихся алгоритмов.

Синтаксис оператора:

if (выражение)

оператор1

[else

оператор2]

Замечание: при описании синтаксиса опраторов в квадратных скобках будут указываться необязательные конструкции.

Выполнение оператора: если значение выражения истинно выполняется оператор1, иначе оператор2.

Пример оператора:

if (a>b)

y=sin(x);

else

y=cos(x);

Наличие точки с запятой перед служебным словом else обязательно, так как точка с запятой входит в запись предшествующего оператора. Сокращенная запись структуры развилки может быть реализована с помощью условной операции:

y=a>b ? sin(x) : cos(x);

Пример программы, определяющей принажлежит ли точка с координатами {x,y} первому квадранту:

#include <iostream.h>

#include <conio.h>

void main()

{

float x, y;

cout<<”x,y ? “; cin>>x>>y;

if (x>=0 && y>=0)

cout<<”Yes”;

else

cout<<”No”;

getch(); }

Программа может содержать несколько последовательных условных операторов. Условные операторы могут быть вложенными.

Пример программы, вычисляющей функцию знака

#include <iostream.h>

#include <conio.h>

void main()

{

float x, sign;

cout<<”x ? “; cin>>x;

if (x>=0)

sign=1;

else

if (x==0) //вложенный оператор if

sign=0;

else

sign=-1;

cout<<”sign=”<<sign;

getch();

}

 

3.4. Составной оператор

 

Составной оператор используется для объединения нескольких операторов в один оператор. Такое объединение требуется выполнять в тех случаях, когда по синтаксису в программе может быть записан только один оператор, (например, в ветке условного оператора), а по логике алгоритма надо выполнить несколько действий.

Синтаксис оператора:

{Операторы [и объявления]}

Пример составного оператора:

if (a>b)

{//переставить значения

int x; //объявление переменной

x=a; a=b; b=x;

}

 

3.5. Операторы для программирования циклов

 

В С++ для программирования циклических алгоритмов используются три оператора цикла:

· for

· while

· do while

и операторы передачи управления:

· break

· continue

 

3.5.1. Оператор цикла for

Синтаксис оператора:

for ([выражение1]; [выражение2]; [выражение3]) оператор

Пример оператора:

for (i=0; i<10; i++)

cout<<i<<’ ‘;

Выполнение оператора:

1) Вычисляется выражение1, если оно есть.

2) Вычисляется выражение2, если оно есть.

3) Если выражение2 истинно (<>0) или оно отсутствует
выполняется оператор тела цикла, иначе выход из цикла.

4) Вычисляется выражение3, если оно есть.

5) Переход на пункт 2.

Оператор for является оператором цикла с предусловием: перед каждой итерацией цикла, в том числе и перед первым выполнением, проверяется условие выполнения цикла.

Пример программы вычисления суммы

#include <conio.h>

#include <iostream.h>

void main()

{

float s; //сумма

int n; //количество слагаемых

int i; //номер слагаемого

cout<< “n? “; cin>>n;

s=0;

for (i=1; i<=n; i++)

s=s+1.0/i;

cout<<”s=”<<s;

getch();

}

 

3.5.2. Оператор цикла while

 

Синтаксис оператора:

while (выражение) оператор

Выполнение оператора: пока выражение истинно выполняется оператор.

Оператор while является оператором цикла с предусловием.

Пример программы вычисления количества цифр в целом числе:

#include <iostream.h>

#include <conio.h>

#include <math.h>

void main()

{

int x; //число

int y; //модуль числа

int k=1; //количество цифр в числе

cout<<"x? "; cin>>x;

y=abs(x);

while (y>=10)

{

k++;

y/=10; //целочисленное деление

}

cout<<"k="<<k;

getch();

}

Тесты:

х=123 результат=3

х=0 результат=1

х=-34567 результат=5

 

3.5.3. Оператор цикла do while

 

Синтаксис оператора:

do оператор while(выражение);

Выполнение оператора:

1) Выполняется оператор тела цикла.

2) Вычисляется выражение.

3) Если выражение истинно, то переход на пункт 1, иначе выход из цикла.

Оператор do while является оператором цикла с постусловием: вначале выполняется оператор тела цикла, а затем вычисляется выражение для принятия решения о выполнении очередной итерации.

Пример программы вычисления количества цифр в целом числе:

#include <iostream.h>

#include <conio.h>

#include <math.h>

void main()

{

int x; //число

int y; //модуль числа

int k=0;

cout<<"x? "; cin>>x;

y=abs(x);

do

{

k++; y/=10;

}

while (y>0);

cout<<"k="<<k;

getch();

}

 

3.5.4. Оператор break

 

Оператор break используется внутри операторов цикла и оператора switch для прерывания выполнения этих операторов и передачи управления на оператор программы, следующий за оператором цикла или оператором switch.

Синтаксис оператора:

break;

Пример программы суммирования вводимых с клавиатуры целых чисел (признаком конца ввода является ввод отрицательного числа):

#include <iostream.h>

#include <conio.h>

void main()

{

int х; //вводимое число

int s=0; //сумма чисел

while (true) //бесконечный цикл

{

cout<<"x?"; cin>>x;

if (x<0)

break; //выход из цикла

s+=x; //суммирование неотрицательных чисел

}

cout<<"s="<<s;

getch();

}

 

3.5.5. Оператор continue

 

Оператор continue используется внутри операторов цикла. Он пропускает все операторы, следующие за ним в теле цикла, и передает управление на начало следующей итерации цикла.

Синтаксис оператора:

continue;

Пример программы суммирования и подсчета отрицательных чисел вводимой с клавиатуры последовательности из n целых чисел:

#include <iostream.h>

#include <conio.h>

void main()

{

int х; //вводимое число

cout<<"n? ";

cin>>n;

int s=0; //сумма отрицательных чисел

int k=0; //количество отрицательных чисел

//Цикл ввода и обработки чисел

for (int i=1; i<=n; i++)

{

cout<<"x?";

cin>>x;

if (x>=0)

continue;

s+=x; //суммирование отрицательных чисел

k++; //подсчет количества отрицательных чисел

}

cout<<"s="<<s<<” k=”<<k;

getch();}

3.6. Оператор goto

 

Оператор goto передает управление на оператор с указанной в goto меткой.

Синтаксис оператора:

goto метка;

Оператор goto надо использовать в программах только в исключительных случаях, так как его использование приводит к усложнению структуры программы.

 

3.7. Пустой оператор

 

Пустой оператор используется совместно с оператором цикла for или с оператором goto. Оператор не выполняет никаких действий.

Синтаксис оператора:

;

Пример использования пустого оператора для вычисления суммы:

s=0;

for (int i=1; i<=n; s+=1.0/i, i++)

;

 

3.8. Оператор switch

 

Оператор switch используется для программирования разветвляющихся алгоритмов, в которых количество альтернатив больше двух.

Синтаксис оператора:

switch (выражение)

{

метка выбора: [операторы]

метка выбора: [операторы]

………………………………..

метка выбора: [операторы]

[default: операторы]

}

Метка выбора имеет вид:

case константа

Выражение и константы в метках выбора должны быть целого типа.

Выполнение оператора начинается с вычисления значения выражения. Далее управление передается на ветвь, константа которой равна значению выражения. Выполняются операторы этой ветви, а далее выполняются операторы всех ветвей, находящихся ниже. Если нет константы, равной значению выражения, то выполняется ветвь default, если она есть. Для выполнения только одной ветви оператора надо в ней предусмотреть оператор break.

Пример оператора, который выводит значение целого числа k, значение которого от 1 до 5, римскими цифрами:

switch (k)

{

case 1: cout<<”I”; break;

case 2: cout<<”II”;break;

case 3: cout<<”III”;break;

case 4: cout<<”VI”;break;

case 5: cout<<”V”;break;

default: cout<<”Error”;

}

Для выхода из ветви оператора switch могут использоваться также операторы goto и return. В операторе switch в каждой ветви может быть несколько меток выбора.

Пример программы, которая по номеру месяца выводит время года:

#include <iostream.h>

#include <conio.h>

void main()

{

int month; //месяц

cout<<"month? "; cin>> month;

switch (month)

{

case 12: case 1: case 2: cout<<”winter”;break;

case 3: case 4: case 5: cout<<”spring”;break;

case 6: case 7: case 8: cout<<”summer”; break;

case 9: case 10: case 11: cout<<”autumn”;break;

}

getch();

}

 

3.9. Оператор return

 

Оператор return завершает работу функции и передает управление в точку вызова функции. Может передавать в точку вызова функции вычисленное функцией значение.

Синтаксис оператора:

return [выражение];

Пример программы вычисления младшей цифры целой части вещественного числа, в которой алгоритм вычисления младшей цифры вещественного числа оформлен в виде функции:

#include <iostream.h>

#include <conio.h>

//Определение функции

int f(float x)

{

return (int)x%10;

}

void main()

{

float a;

cout<<"a? ";

cin>>a;

cout<<f(a)<<endl;

getch();

}

4. Массивы

Массив – это составной тип данных, используемый в программе для представления конечной последовательности данных одного типа. Под элементы массива выделяются смежные участки памяти. Доступ к элементу массива осуществляется по индексу.

 

4.1. Объявление массива

Синтаксис объявления массива:

Тип элементов имя массива [размер массива];

Пример объявления массивов:

int a[100]; //целочисленный массив из 100 элементов

float b[10]; //массив из 10 вещественных чисел

При объявлении массива можно указать начальные значения для его элементов:

int a[4]={10,20,30,40};

или

int a[]={10,20,30,40};

В последнем случае размер памяти под массив определяется автоматически по количеству констант. Можно проинициализировать только часть первых элементов массива:

int a[4]={10,20};

 

4.2. Обращение к элементам массива

К элементу массива обращаются с помощью индекса (номера) элемента.

Синтаксис обращения:

Имя_массива [индекс]

Индекс определяет положение элемента в массиве и задается выражением. Выражение должно быть целого типа.

Примеры обращения к элементам массива:

a[1]=2; a[i]=3;

a[i+2]=a[i];

Элементы массива в языке С++ нумеруются с 0. Поэтому в массиве, объявленном как массив из 100 элементов, первый элемент имеет индекс равный 0, а последний – 99. Контроль выхода индекса элемента массива за границы допустимых значений при выполнении программы в С++ не выполняется.

В языке С++ отсутствуют операции над массивом. Исключение составляет операция индексации []. Над элементами массива можно выполнять операции, которые допустимы для типа элементов массива.

Пример программы поиска значения максимального элемента целочисленного массива из n элементов (n<=100):

#include <iostream.h>

#include <conio.h>

void main ()

{

int a[100]; //массив

int n, i; //количество элементов и индекс элемента

int max; //значение максимального элемента

cout<<”n? “;

cin>>n;

cout<<”a? “;

//Ввод массива

for (i=0; i<n; i++)

cin>>a[I];

max=a[0];

for (i=1; i<n; i++) //цикл поиска максимального элемента

if (a[i]<max

max=a[I];

cout<<”max=”<<max;

getch();

}

Тесты:

n=5

a: 1, 8, -9, 3, 5 max=8

a: 1, 8, 2, 8, 6 max=8

a: 1, 1, 1, 1, 1 max=1

4.3. Типовые алгоритмы работы с массивами

Массив используется для хранения последовательности однотипных данных и выполнения над этой последовательностью операций. Типовые операции над массивами:

· поиск в массиве;

· вычисление суммы, количества и произведения определенных элементов массива;

· сортировка массива;

· удаление определенных элементов из массива;

· добавление элементов в массив;

· формирование массива.

Пример программы подсчета отрицательных чисел в массиве из n (n<=100) вещественных чисел:

#include <iostream.h>

#include <conio.h>

void main ()

{

float a[100]; //массив чисел

int n, i; //количество элементов в массиве и индекc элемента

int k; //количество отрицательных чисел в массиве

cout<<”n? “;

cin>>n;

cout<<”a? “;

for (i=0; i<n; i++) //цикл ввода массива

cin>>a[I];

k=0;

for (i=0; i<n; i++) //цикл поиска и подсчета отрицательных чисел

if (a[i]<0

k++;

cout<<”k=”<<k;

getch();

}

Пример программы сортировки массива из n вещественных чисел (n<=100) по возрастанию методом прямого обмена (пузырьковым методом):

#include <iostream.h>

#include <conio.h>

void main ()

{

float a[100]; //массив чисел

int n, i; //количество элементов в массиве и индекc элемента

int k; //номер прохода массива при сортировке

cout<<”n? “; cin>>n;

cout<<”a? “;

for (i=0; i<n; i++) //цикл ввода массива

cin>>a[i];

//Сортировка пузырьковым методом

for (k=1; k<n; k++)

for (i=0; i<k-1; i++)

if (a[i]>a[i+1])

{int t; t=a[i]; a[i]=a[i+1]; a[i+1]=t;} //перестановка элементов

cout<<”a:”<<endl;

for (i=0; i<n; i++) //цикл вывода массива на экран

cout<<a[i]<<’ ‘;

getch();

}

Пример программы удаления из массива, содержащего n целых чисел, последнего отрицательного элемента:

#include <iostream.h>

#include <conio.h>

void main ()

{

int a[100]; //массив чисел

int n, i ,j; //количество элементов массива, индекcы элементов

cout<<”n? “; cin>>n;

cout<<”a? “;

for (i=0; i<n; i++) //цикл ввода массива

cin>>a[i];

i=n-1; //начальное значение индекса для поиска с конца

while (i>=0 && a[i]>=0) //цикл поиска отрицательного числа

i--;

if (i>=0) //число найдено, номер числа i

{

for (j=i; j<n-1; j++) //удаление a[i], сжатие массива

a[j]=a[j+1];

n--; //количество элементов будет на 1 меньше

}

for (i=0; i<n; i++) //вывод массива

cout<<a[I]<<’ ‘;

getch();

}

Тесты:

n=5, a: 1 –2 –3 5 6 результат: a: 1 –2 5 6, n=4

n=5, a: -1 –2 –3 –4 -6 результат: a: -1 –2 –3 –4, n=4

n=5, a: 1 2 3 4 5 результат: a: 1 2 3 4 5, n=5

Пример программы формировния нового массива из отрицательных чисел целочисленного массива размера n (n<=100):

#include <iostream.h>

#include <conio.h>

void main ()

{

int a[100], b[100]; //исходный и формируемый массивы

int n, i, j; //количество элементов в массиве и индекcы элементов

cout<<”n? “; cin>>n;

cout<<”a? “;

for (i=0; i<n; i++) //цикл ввода массива

cin>>a[i];

j=0; //индекс первого элемента в формируемом массиве

for (i=0; i<n; i++) //цикл поиска a[i]<0 и запись их в массив

if (a[i]<0)

{ b[j]=a[I]; j++;}

if (j==0) //новый массив пуст

cout<<”b is empty”;

else //вывод сформированного массива

{

cout<<”b:”;

for (i=0; i<j; i++)

cout<<b[i]<<’ ‘;

}

getch();

}

Тесты:

n=5, a: 1 -2 3 -4 -5 результат b: -2 -3 -5

n=5, a: -1 -2 -3 -4 -5 результат b: -1 -2 -3 -4 -5

n=5, a: 1 2 3 4 5 результат : b is empty

 

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

Многомерный массив – это массив, компонентами которого являются массивы.

Пример объявления многомерного массива (двумерного массива) из двух элементов, каждый из которых является массивом из трех вещественных чисел:

float b[2][3];

Пример объявления трехмерного массива из четырех элементов, каждый из которых является массивом из 10 двумерных массивов целых чисел:

int a[4][10][15];

При обращении к элементу многомерного массива надо указывать индекс по каждому измерению. Каждый индекс заключается в квадратные скобки. Нумерация индексов по каждому измерению начинается с нуля, например, обращение к элементу, объявленного выше массива:

a[0][9][4]=25;

Многомерные массивы можно инициализировать. Примеры допустимых вариантов инициализации массива:

float b[2][3]={1.2, 1.3, 1.4, 1.6,1.7, 1.8};

float b[2][3]={{1.2, 1.3, 1.4},{1.6, 1.7, 1.8}};

float b[][]={{1.2, 1.3, 1.4},{1.6, 1.7, 1.8};

Многомерные массивы располагаются в памяти так, что быстрее всего меняется последний индекс. Так данные двумерного массива, объявленного как

float b[2][3];

располагаются в памяти в следующем порядке:

b[0][0], b[0][1], b[0][2], b[1][0], b[1][1], b[1][2]

Двумерный массив можно представить в виде таблицы (матрицы). Так двумерный массив, объявленный как

float b[2][3];

можно изобразить матрицей из двух строк и трех столбцов:

 

  0-столбец 1-столбец 2-столбец
0-строка b[0][0] b[0][1] b[0][2]
1-строка b[1][0] b[1][2] b[1][2]

Пример программы вычисления суммы чисел, расположенных выше главной диагонали матрицы целых чисел из n строк и n столбцов (n<=100):

#include <iostream.h>

#include <conio.h>

void main()

{

int a[100][100]; //матрица целых чисел

int s; //сумма элементов матрицы

int i, j; //номера строк и столбцов

int n; //размер матрицы

cout<<”n? “; cin>>n;

//Ввод матрицы

cout<<”a? “;

for(i=0; i<n; i++)

for(j=0; j<n; j++)

cin>>a[i][j];

//Вычисление суммы элементов выше главной диагонали

s=0;

for(i=0; i<n-1; i++)

for(j=i+1; j<n; j++)

s+=a[i][j];

cout<<”s=”<<s;

getch();

}

5. Строки

Строка в языках программирования – это последовательность символов, которая обрабатывается в программе как единый объект. Символами строки могут быть буквы (латинского алфавита и кириллицы, цифры, специальные знаки). В строке С++ после последнего значащего символа должен находиться символ с кодом 0 (нулевой символ). Символ с кодом 0 записывается в программе как ‘\0’.

 

5.1. Объявление строки

 

Синтаксис объявления строки-переменной:

char имя_строки[максимальный_размер_размер_строки+1];

Пример объявления строки, в которой может храниться не более 5 символов:

char s[6]; //выделено 6 байтов, из них 1 байт под 0-символ

Строку при объявлении можно инициализировать:

char s[6]=”ABC”; //выделено 6 байтов, заполнено 4 байта

char s[]=”ABC”; //выделено 4 байта, заполнено 4 байта

char s[6]={‘A’,’B’,’C’,’\0’}; //выделено 6 байтов заполнено 4

 

5.2. Посимвольная обработка строк

 

Над строками С++ не определены никакие операции, кроме операции индексации [] – обращения к отдельному символу строки.

Пример программы, посчитывающей количество цифр в строке:

# include <iostream.h>

#include <conio.h>

void main()

{

char s[81]; //строка

int i, k; //номер символа и счетчик цифр

cout<<”s ? ”;

cin>>s; //ввод строки

k=0; //обнуление счетчика

i=0;

//Цикл поиска цифр в строке

while (s[i]!=’\0’)

{

if (s[i]>=’0’ && s[i]<=’9’) // s[i]-цифра

k++;

i++;

}

cout<<”k=”<<k;

getch();

}

При сравнении символов строки сравниваются коды символов. Коды цифр упорядочены по возрастанию значений цифр, а коды латинских букв упорядочены по положению в алфавите. Коды прописных латинских букв меньше кодов соответствующих строчных букв на 32.

Пример программы, которая заменяет в строке все строчные латинские буквы на соответствующие прописные буквы:

# include <iostream.h>

#include <conio.h>

void main()

{

char s[21]; //строка

int i; //номер символа в строке

cout<<”s ? ”; cin>>s;

i=0;

while (s[i]!=’\0’)

{

if (s[i]>=’a’ && s[i]<=’z’) //строчная буква

s[i]=s[i]-32;//замена на прописную: вычитаются коды

i++;

}

cout<<”s: ”<<s;

getch(); }

5.3. Ввод строк

Cтроку, не содержащую пробельных символов, можно ввести, используя операцию >> (взять из потока). Например, оператор cin>>s; вводит в строку s символы с клавиатуры. Объект cin считывает в строку символы до первого пробельного символа.

Для ввода в строку текста, в котором встречаются пробелы, символы перехода на новую строку или табуляции в С++ используется функция getline объекта cin.

Синтаксис вызова функции getline:

cin.getline(строка, максимальный размер строки+1, символ-ограничитель строки);

Функция getline считывает из буфера ввода (области оперативной памяти, в которую попадают вводимые с клавиатуры данные до их записи в переменные) символы до символа-ограничителя. Количество считываемых символов не может быть более чем максимальный размер строки. Сам символ-ограничитель в строку не записывается, он удаляется из буфера ввода. В конец строки-переменной добавляется символ ’\0’.

Примеры ввода строки, содержащей пробельные символы:

char s[21];

cin.getline(s,21,’\n’); //вводимые символы ABC ABC ММ 123’\n’

cout<<s; //ABC ABC ММ 123

cin.getline(s,21,’#’); //вводимые символы ABC ABC ММ 123’#’’\n’

cout<<s; //ABC ABC ММ 123

Если в качестве ограничителя используется символ новой строки, то третий аргумент функции getline можно не указывать:

cin.getline(s,21);// вводимые символы ABC ABC ММ 123’\n’

Пример программы, которая подсчитывает количество слов в тексте-предложении, которое заканчивается точкой. В качестве разделителей слов в предложении используются символы пробел и символ новой строки. Максимальная длина текста 200 символов.

#include <iostream.h>

#include <conio.h>

void main( )

{

char s[201]; //строка с текстом

int k=0; //счетчик слов

int i=0; //номер символа

cin.getline(s, 201, '.'); //ввод текста с пробельными символами

//Подсчет символов разделителей слов

while(s[i]!='\0')

{

if(s[i]==' ' || s[i]=='\n')

k++;

i++;

}

if (s[0]!=’\0’) //строка не пустая

k++; //количество слов на 1 больше количества разделителей

cout<<"k="<<k;

getch();

}

Другой способ ввода строки с пробелами – использование функции gets библиотеки stdio языка Си. Функция вводит символы из буфера ввода до символа новой строки и в конец строки-переменной добавляет символ ’\0’. Сам символ новой строки в строку не записывается, он удаляется из буфера ввода.

Пример использования функции gets:

char s[21];

gets(s); //ABC ABC ММ 123’\n’

cout<<s; //ABC ABC ММ 123

 

5.4. Библиотечные функции для работы с текстом

 

В стандартных библиотеках языка С++ содержится много полезных функций для работы со строками. Их использование позволяет сократить код программы, увеличить ее надежность, уменьшить время разработки программы. Библиотечные функции приведены в [1, 2]. Все функции рассчитаны на то, что строки заканчиваются нулевым символом. Ниже рассматриваются наиболее востребованные при обработке текста функции.

Функция strlen(s)возвращает текущую длину строки s. Для использования этой функции надо подключить к программе файл string.h.

Пример программы, определяющей является ли введенное слово палиндромом:

#include <iostream.h>

#include <conio.h>

#include <string.h>

void main()

{

char s[21]; //слово

int l, r; //левый и правый символы слова

cin>>s;

cout<<s<<endl;

l=0; //начало слова

r=strlen(s)-1; //конец слова

while(l<r && s[l]==s[r])

{

l++; //индекс левого символа

r--; //индекс правого символа

}

if( l>=r)

cout<<"Yes";

else

cout<<"No" ;

getch();

}

Тесты:

Шалаш палиндром

Тот палиндром

Таня не является палиндромом

АННА палиндром

С палиндром

 

Функция strcpy(s1,s2) копирует второй аргумент-строку s2 в строку s1. Размер первой строки должен быть не меньше второй, чтобы в нее скопировался 0-символ. Для использования этой функции надо подключить к программе файл string.h.

Пример использования функции:

char s1[21], s2[21];

cout<<s1<<endl; //abc

strcpy(s2,”12345”);

cout<<s2; //12345

Функция strcat(s1,s2) присоединяет к концу первой строки s1 вторую строку s2и записывает результат в первую строку. Размер первой строки должен быть достаточен, чтобы в нее поместились две сцепленные строки и нулевой символ. Для использования этой функции надо подключить к программе файл string.h.

Пример использования функции:

char s1[10], s2[10];

cin>>s1; //abc

cin>>s2; //def

strcat(s1,s2);

cout<<s1<<endl; //abcdef

Функция strcmp(s1,s2)сравнивает две строки и возвращает число 0, если строки равны, отрицательное число, если строка s1 меньше s2 и положительное число, если строка s1 больше s2. Строки сравниваются лексиграфически (сравниваются коды соответствующих символов строк). Сравнение происходит до первого несовпадающего символа или до конца строк (если все символы строк совпадают). При лексиграфическом сравнении строка “Иванов” меньше строки “Петров”.

Пример программы сортировки по возрастанию массива из n слов (n<=20), максимальная длина слова 15 символов:

#include <iostream.h>

#include <conio.h>

#include <string.h>

void main()

{

char s[20][16]; //массив из 20 строк

char x[16]; //переменная для перестановки слов

int i, j, n; //номер слова и номер прохода

int n; //количество слов

cout<<"n? “;

cin>>n;

cout<<"s? "<<endl;

for (i=0; i<n; i++) //ввод входной строки из нескольких слов ...

cin>>s[i]; // ввод слова

for (j=1; j<n; j++) //сортировка пузырьковым методом

for (i=0; i<n-j; i++)

if(strcmp(s[i],s[i+1])>0) //сравнение слов

{//перестановка слов

strcpy(x,s[i]);

strcpy(s[i],s[i+1]);

strcpy(s[i+1],x);

}

for (i=0; i<n; i++)

cout<<s[i]<<' ';

getch();

}

Тест:

n=4, Иванов Андреев Сидоров Петров

Результат: Андреев Иванов Петров Сидоров

 

6. Указатели

 

Указатель – это тип данных, значениями которых являются адреса оперативной памяти. Переменная-указатель (или просто указатель) содержит адрес ячейки памяти, в которой находится значение другой переменной или код функции.

Указатели используются для:

· работы со строками и массивами;

· работы с динамическими структурами данных, такими как очереди, списки, деревья, сети, графы;

· передачи в функцию в качестве параметра адреса другой функции;

· обмена данными между функциями в стиле языка С.

6.1. Объявление указателей

Синтаксис объявления переменной-указателя:

тип *имя_указателя;

где тип – это тип данных, на которые может ссылаться указатель.

Примеры объявлений указателей:

int *p1; //указатель на целое

float *p2, *р22; //указатели на вещественные данные

char *p3; // указатель на символ

char *p[15]; //массив из 15 указателей на символы

char (*p)[15] ;//указатель на массив из 15 символов

float **r; //указатель на указатель

Указателю при его объявлении можно присвоить начальное значение. Таким значением может быть адрес другой переменной или целое число 0. Указатель с нулевым значением не на что не указывает.

char c=’a’;

char *p3=&c; //& - операция получения адреса переменной

int *p4=0; //инициализация указателя нулем

int * const p=&x; //константный указатель, не может изменяться

const int * p1=&x; //указатель на константное целое значение

6.2. Операции над указателями