Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КЛ_ТехнолПрогр2010_090103.doc
Скачиваний:
22
Добавлен:
27.04.2019
Размер:
1.35 Mб
Скачать

2.3. Типы данных

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

Базовые типы данных

Базовые типы бывают целые, вещественные, символьные, используют стандартные идентификаторы типов:

Короткое целое short int -32768÷32767

Целое int -32768÷32767

Неотрицательное целое unsigned int 0÷65535

Длинное целое long -2*109÷2109

Неотрицат. длинное целое unsigned long 0÷4*109

Веществ.одинарной точности float 3.4*10-38÷3.4*1038

Веществ. двойной точности double 1.7*10-308÷1.7*10308

Веществ. высокой точности long double 3.4*10-4932÷3.4*104932

Символ (один байт) char -128÷127

Беззнаковый символ unsigned char 0÷255

Константы – это лексемы, представляющие собой фиксированные значения.

Целые константы – любые числа без дробной части, не начинающиеся с нуля. Восьмеричные целые константы начинаются с нуля. Шестнадцатиричные констнты начинаются с 0x. Для констант с плавающей точкой можно опустить либо десятичную точку, либо Е, но не то и другое. Символьная константа – это один символ, заключенный в одинарные кавычки (апострофы). Они имеют числовые значения, равные кодам ASCII соответствующих символов. Примеры:

29, -3, +4569 //целые константы

01, 023, 0407 //восьмеричные

0x1a, 0x10, 0x2F //шестнадцатиричные

3.14, 2e3, 3.4E-5, 10., .9 //вещественные

‘a’, ‘9’, ‘-‘ //символьные

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

Одинарная кавычка ' '\''

Ноль (пустой символ) NUL '\0'

Звуковой сигнал(звонок) BEL '\a'

Возврат на шаг(забой) BS '\b'

Перевод страницы FF '\f'

Новая строка(перевод строки) LF '\n'

Возврат каретки CR '\r'

Горизонтальная табуляция HT '\t'

Вертикальная табуляция VT '\v'

Обратная косая черта \ '\\'

Двойная кавычка " '\"'

Байтовое значение в восьмеричной системе '\ddd'

Байтовое значение в шестнадцатиричной системе '\xdd'

Строковая константа - это ноль и более символов, заключенных в двойные кавычки, имеет тип массив символов (char), содержит в конце добавляемый автоматически символ ноль '\0'. Нулевая (пустая строка) записывается в виде "" и хранится в виде одного символа '\0'. Константы могут быть записаны в нескольких строках. Последний символ переносимой строки-это \ ,он и символ новой строки отбрасываются при выводе данных. Соседние строковые константы, разделенные пробелами, конкатенируются (соединяются).

Преобразование и переименование типов

Язык С++ допускает преобразование (приведение) типов и переименование типов. Желательное правило: в выражениях и операторах лучше использовать переменные и константы одинакового типа. Если типы разные, то выполняется преобразование(приведение) типов. Возможны неявные(стандартные) и явные преобразования типов.

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

в выражениях операнды преобразуются к одинаковому типу по схеме: char->short int->unsigned int->long->unsigned long->

float->double->long double;

в операторах присваивания правая часть преобразуется к типу левой части.

Явное преобразование типов выполняется специальной операцией приведения типа, имеющей 2 формы записи:

(tip) vyr; -используется в С и С++;

tip(vyr); - функциональная форма,введена в С++.

Формы почти равноценны, и их выбор -это дело вкуса.

Переименование типа проводится объявлением нового идентификатора типа данных, синонима существующего типа с целью использования более удобного или сокращённого названия. Синтаксис:

typedef tip ident;

,где tip -существующий тип данных;

ident -идентификатор-синоним.

Пример: typedef unsigned int t;

unsigned int x;//Длинное t x;//Короткое название

unsignet int y;//название t y;

Операции

Над базовыми типами выполняются следующие операции:

-арифметические операции: сложение (+), вычитание (-), умножение (*), деление (/), остаток от деления (% ,для целых и символов), унарные операции (+ и -);

-логические операции: НЕ (!),ИЛИ (||),И (&&);

-операции отношения: равно (==), не равно (!=), меньше (<), меньше или равно (<=), больше (>), больше или равно (>=);

-операции инкремента и декремента (для целых и символов): постфиксный инкремент (vyr++) - увеличение vyr на единицу, результатом всего выражения является значение vyr до увеличения;

пример: m=1;

n=m++; //m=2,n=1

префиксный инкремент (++vyr) - увеличение vyr на единицу, результатом всего выражения является значение vyr после увеличения;

пример: m=1;

n=++m; //m=2,n=2

постфиксный декремент (vyr--) - уменьшение vyr на единицу, результатом всего выражения является значение vyr до уменьшения;

пример: m=2;

n=m--; //m=1,n=2

префиксный декремент (--vyr) - уменьшение vyr на единицу, результатом всего выражения является vyr поле уменьшения;

пример: m=2;

n=--m; //m=1,n=1

-побитовые операции(для целых и символов): дополнение до единицы (~), побитовое ИЛИ (|), побитовое И (&), побитовое исключающее ИЛИ (^), сдвиг вправо (>>), сдвиг влево (<<);

-операции присваивания: присвоить (=), сочетание с арифметическими и битовыми логическими операциями (+=, -=, *=, /=, %=, |=, &=, ^=; >>=, <<=);

примеры: m+=n; //Сокращенная запись m=m+n;

x=y=z;//Множественное присваивание x=(y=(z=0));

-условная операция,арифметическое если (?:): vyr1?vyr2:vyr3)- если vyr1 истинно,то вычисляется vyr2, и результатом является vyr2; иначе вычисляется vyr3, и результатом является vyr3;

пример: y=(x<=0)?-x:x;//y - абсолютное значение x

-операция последовательного выполнения, операция запятая (,): vyr1,vyr2 -сначала вычисляется vyr1,затем vyr2, результат операции - vyr2; операция обычно используется для выполнения нескольких выражений в ситуациях, где по синтаксису может быть лишь одно.

Приоритет операций в порядке убывания следующий:

1) () -вызов функции;

2) !, ~, +, -, ++, --, () -логическое НЕ, дополнение до единицы, унарные операции, инкремент, декремент, операция приведения типа;

3) *, /, % -мультипликативные операции;

4) +, - -сложение, вычитание;

5) <<, >> -сдвиг;

6) <, >, <=, >= -операции отношения;

7) ==, != -операции отношения;

8) & -побитовое И;

9) ^ -побитовое исключающее ИЛИ;

10) | -побитовое ИЛИ;

11) && -логическое И;

12) || -логическое ИЛИ;

13) ?: -условная операция;

14) =,+=,-=,*=,/=,%=,>=,<=,&=,^=,|= -операции присваивания;

15) , -операция запятая.

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

math.h - математические функции;

string.h - функции обработки строк;

ctype.h - функции для проверки и обработки символов;

stdlib.h - преобразование символов и строк в числа и обратно;

conio.h - библиотека видеофункций;

iostream.h - базовая библиотека ввода/вывода потоком С++.

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

Массивы

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

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

Доступ к элементам массива осуществляется с помощью индексированной переменной:

per[index];

,где index -целое положительное число от 0 до количества элементов минус 1.

Пример:

int kol[5];//первый элемент-kol[0],...,пятый элемент-kol[4]

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

Указатели

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

Указатель - это переменная, содержащая адрес другой переменной или функции. Использование указателей позволяет упростить алгоритм и повысить его эффективность за счет простого доступа к большим объемам данных с помощью указателя.

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

Для доступа к переменной через указатель используется операция разадресации (разыменования, или обращения по адресу,или косвенной адресации)- *. Выражение *ident означает, что нужно извлечь значение по адресу, равному значению указателя ident.

Пример:

//Доступ через указатель

int tabn1,tabn2,*p=&tabn1;

tabn1=1000;

tabn2=*tabn1;//tabn2=1000

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

Пример:

int tabn,*p=&tabn;

tabn=1000;

*p=2000;// Значение tabn изменится на 2000

Пример указателей на массивы:

char* naim="Картотека служащих";//Объявление и инициализ.

//указателя адресом строки символов

int tabn[5];

int *p=tabn;//Объявление и инициализация указателя адресом

//первого байта массива,операция & не нужна.

Доступ к элементам массива может осуществляться помимо имени массива (tabn[i]), с помощью указателя(p[i]).

p[i]==*(p+i)

,где p+i -адрес i-го элемента массива tabn,

* -операция разадресации.

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

struct tip_rab //Объявление типа структура

{

int tabn;

char fio[20];

float zarp;

};

tip_rab rab; //Объявление переменной типа структура tip_rab

tip_rab *p; //Объявление указателя p на тип tip_rab

p=&rab; //Инициализация указателя p адресом rab

или

tip_rab *p=&rab;//Объявление и инициализация указателя

Доступ к полям структуры осуществляется помимо операции (.)-операции прямого выбора поля структуры (rab.tabn), с помощью операции (->) -операции косвенного выбора поля структуры или операции указателя поля (p->tabn). p->tabn==(*p).tabn.

Определение адреса поля структуры выполняется с помощью операции адресации: &prab->tabn, где операция -> имеет более высокий приоритет.

Над указателями можно выполнять следующие операции:

- операции адресации(&) и разадресации(*);

- операция присваивания(=);

- арифметические операции(+,-,++,--);

- операции сравнения.

Общее правило операций следующее: считается, что указатель указывает на начало совокупности переменных объявленного типа; прибавление к указателю tip*p целого числа n увеличивает содержащийся в нем адрес на число, равное произведению прибавляемого числа на размер переменной в байтах, т.е. на n*sizeof(tip), таким образом,указатель перемещается на n значений или на n*sizeof(tip) байтов.

Размеры типов в байтах для малой модели следующие: char-1, int-2, long-4, float-4, double-8.

Указатели- это удобный способ обработки больших объемов данных: массивов, структур, объединений.

Использование модификатора const определяет, что указатель и/ или указываемая переменная не должны изменяться. Если необходимо, чтобы указываемая переменная не изменялась, нужно записать const перед типом указателя.

Пример:

const int *p=&tabn1;//Указатель на константу типа int

*p=1000;// недопустимо

p=&tabn2;// допустимо

const char *fkart="kartotek.dat";

Если необходимо, чтобы сам указатель не изменялся, нужно записать const после обозначения типа указателя.

Пример:

int * const p=&tabn1;//Постоянный указатель на int

*p=1000;// допустимо

p=&tabn2;// недопустимо

Адрес именной константы не может быть присвоен указателю без const, т.к. такое присваивание могло бы изменить именную константу через указатель.

Пример:

const int kol=25;

const int *p=&kol;// допустимо

int *p=&kol;// недопустимо

Указатели могут агрегироваться в массивы. Массивы указателей обязательно должны быть инициализированы.

Преимущества указателей следующие:

- экономия памяти, более компактное размещение данных;

- эффективное выполнение программы при использовании указателей в качестве параметров функции при передаче агрегированных данных за счет того, что в стек копируется не весь объем данных, а только одно число -адрес первого байта данных;

- возможность изменения значений переменных вызывающей функции при изменении значений параметров вызываемой функции, т.е. возможность возврата значений помимо оператора return;

Ссылки

Альтернативой указателям являются ссылки.

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

Пример: ссылка указатель

int tabn=1000; int tabn=1000;

int &r=tabn; int *p=&tabn;

cout<<r<<'\n';//r=1000 cout<<*p<<'\n';//*p=1000

tabn=2000; tabn=2000;

cout<<r<<'\n';//r=2000 cout<<*p<<'\n';//*p=2000

r=3000; *p=3000;

cout<<tabn<<'\n';//tabn=3000 cout<<tabn<<'\n';//tabn=3000

Результаты примеров с ссылкой и указателем одинаковы. Но использование ссылки по сравнению с указателем более удобно, так как ссылка пишется как обычная переменная и не требует операций адресации(&) и разадресации(*). Ссылка r определяет местоположение в памяти переменной tabn. При изменении значения tabn (tabn=2000;) ссылка r получает это новое значение. При изменении значения ссылки (r=3000) переменная tabn получает это новое значение. Более точнее можно сказать следующее об операциях над ссылкой. Операция присваивания ссылке r значения 3000 не изменяет ссылку, т.е. ссылка r всегда ссылается на int tabn, а операция присваивания применяется к переменной tabn.

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

Ссылки используются в качестве формальных параметров функций при передаче агрегированных данных (структур, объединений). При вызове функции автоматически вычисляется адрес фактического параметра (переменной вызывающей функции) и помещается в стек, затем копия адреса присваивается формальному параметру (ссылке). Аналогично выполняется возврат значения функции по ссылке. Возвращать ссылку, как и указатель, на локальную переменную нельзя.

Преимущества ссылок заключаются в следующем:

- эффективное выполнение программы при использовании ссылок в качестве параметров функций при передаче агрегированных данных (как и указатели);

- возможность изменения значений переменных вызывающей функции при изменении значений параметров вызываемой функции, т.е. возможность использования ссылок для возврата значений помимо оператора return (как и указатели);

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

Типы данных, определяемые пользователем:

структуры, объединения, перечисления

Структура - это поименованная совокупность данных, состоящая из фиксированного числа компонентов разных типов. Компоненты структуры называются полями.

Пример:

struct tip_rab //Объявление типа структура tip_rab

{

int tabn;

char fio[20];

float zarp;

};

tip_rab rab1,rab2,brigada[10];//Объявление переменных типа

//структура tip_rab

Типы полей структуры - это любые типы, включая тип структура. Таким образом, возможно создание иерархической структуры данных.

Доступ к полям структуры осуществляется с помощью составного идентификатора:

per.pole

,где pole – идентификатор (имя) поля структуры;

символ (.) - операция выбора поля структуры.

Пример:

rab1.tabn=1200;

Над целыми структурами, имеющими один и тот же идентификатор типа, возможна операция присваивания.

Пример:

rab1=rab2;

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

Пример:

//Вызываемая функция //Вызывающая функция

void vyvod(tip_rab &x) tip_rab rez;

{ //rez имеет значение

cout<<x.tabn<<'\n' ...

<<x.fio<<'\n' vyvod(rez);

<<x.zarp<<'\n';

}

Если необходимо заблокировать изменение переменной rez от функции vyvod, то необходим модификатор const: const tip_rab &x.

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

Пример:

union tip_rab //Объявление типа объединение

{

int tabn; //Размер 2 байта

char fio[20]; //размер 20 байт

float zarp; //размер 4 байта

};

...

tip_rab rab1,rab2;//Объявление переменных типа tip_rab

Размер объединения равен максимальному размеру всех его полей, в нашем примере - 20 байт. Одновременно в памяти может находиться значение только одного поля. Переменная rab1 может одновременно хранить в 20 байтах либо значение int, либо массив char, либо значение float.

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

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

Упорядоченность идентификаторов пользователя определяется возрастающей последовательностью целочисленных значений идентификаторов. По умолчанию идентификаторы инициализируются значениями 0,1 и т.д.

Примеры:

enum selector {vyhod,sozd,prosm,ud,zam};//vyhod=0,sozd=1,...

enum dni {pn,vt,sr,cht,pt,sb,vs};//pn=0,vt=1,...

selector sel1;//Объявление переменной типа selector

dni d; //объявление переменной типа dni

При объявлении перечисления можно явно инициализировать идентификаторы пользователя целыми значениями.

Пример:

enum dni {pn=1,vt,sr,cht=pn+7,pt,sb,vs};//pn=1,vt=2,sr=3,

//cht=8,pt=9,sb=10,vs=11

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

enum {false,true}; //символические константы false=0,true=1

Над переменной перечисляемого типа возможны операции:

- операция присваивания, например, sel1=sozd; d=vs;

- операции отношения, например, if (sel1==sozd) ...;

- любые операции, выполняемые над типом int.

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