Скачать презентацию Типы данных определяемые пользователем Язык С позволяет Скачать презентацию Типы данных определяемые пользователем Язык С позволяет

Типы данных пользователя.ppt

  • Количество слайдов: 71

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

Язык С++ позволяет программисту определять свои типы данных и правила работы с ними (типы Язык С++ позволяет программисту определять свои типы данных и правила работы с ними (типы данных, определяемые пользователем). К ним относятся: • переименования типов (typedef), • структуры (struct), • перечисления (enum), • объединения (union).

Переименование типов (typedef) Для того чтобы сделать программу более ясной, можно задать типу новое Переименование типов (typedef) Для того чтобы сделать программу более ясной, можно задать типу новое имя с помощью ключевого слова typedef: typedef тип новое_имя[размерность]; Например : typedef unsigned int typedef char Msg[100]; UINT;

Введенное таким образом имя можно использовать таким же образом, как и имена стандартных типов: Введенное таким образом имя можно использовать таким же образом, как и имена стандартных типов: UINT i, j; //две переменных типа unsigned int Msg str[10]; // массив из 10 строк по 100 символов

Перечисления (enum) При необходимости определить несколько именованных констант, имеющих различные значения, используют перечисления. Формат: Перечисления (enum) При необходимости определить несколько именованных констант, имеющих различные значения, используют перечисления. Формат: enum [имя_типа] {список_констант}; Константы должны быть целочисленными и могут инициализироваться. При отсутствии инициализатора первая константа обнуляется, следующая – на единицу больше и т. д.

enum Err {ER_READ, ER_WRITE, ER_CONVERT}; Err error; . . . switch (error) { case enum Err {ER_READ, ER_WRITE, ER_CONVERT}; Err error; . . . switch (error) { case ER_READ: . . break; case ER_WRITE: . . . break; case ER_CONVERT: . . break; } Константам ER_READ, ER_WRITE, ER_CONVERT присваиваются значения 0, 1 и 2 соответственно.

Структуры В отличии от массива структура может содержать элементы разных типов (поля структуры). Определение Структуры В отличии от массива структура может содержать элементы разных типов (поля структуры). Определение структуры состоит из двух шагов: 1. объявление шаблона структуры; 2. определение переменных типа объявленного шаблона.

Описание шаблона структуры: struct [имя типа] { тип 1 элемент1; Тип 2 элемент2; . Описание шаблона структуры: struct [имя типа] { тип 1 элемент1; Тип 2 элемент2; . . Тип. N элемент. N; } [список_описателей]; Если отсутствует имя типа, то должен быть список описателей – список переменных, указателей или массивов.

Например, объявление шаблона: struct sotr { char fam[15]; char dolg[20]; int oklad; }; Например, объявление шаблона: struct sotr { char fam[15]; char dolg[20]; int oklad; };

Новый тип sotr можно использовать в дальнейшем, например: sotr odin; // переменная odin типа Новый тип sotr можно использовать в дальнейшем, например: sotr odin; // переменная odin типа sotr msotr[10]; // массив msotr из 10 сотрудников

Доступ к полям структуры выполняется с помощью оператора выбора: 1. . (точка) при обращении Доступ к полям структуры выполняется с помощью оператора выбора: 1. . (точка) при обращении через имя структуры : odin. oklad msotr[6]. fam 2. -> при обращении через указатель : student->rating sphere->radius

Пример1 Список 5 -и сотрудников кафедры содержит фамилии, должности и оклады. Вывести на экран Пример1 Список 5 -и сотрудников кафедры содержит фамилии, должности и оклады. Вывести на экран фамилии сотрудников, имеющих максимальный оклад и его размер. #include #include #include const int n = 5; struct sotr { char fam[15]; char dolg[20]; long int oklad; };

// Инициализация массива структур sotr msotr[n]= { // Инициализация массива структур sotr msotr[n]= { "Петров", "Зав. кафедрой", 40000, "Иванов", "Профессор", 40000, "Шубина", "Преподаватель", 10000, "Семенов", "Лаборант", 5000, "Ильина", "Ассистент", 6000 }; void main() { long int max; int i;

max=0; for(i=0; i<n; i++) if(msotr[i]. oklad>max) max= msotr[i]. oklad; printf( max=0; for(i=0; imax) max= msotr[i]. oklad; printf("Макс. оклад%ld руб. имеют: n", max); //cout<<"Макс. окл "<

Пример 2 // Объявляем новый тип данных TStudent struct TStudent { char FIO[56]; // Пример 2 // Объявляем новый тип данных TStudent struct TStudent { char FIO[56]; // ФИО char Group[10]; //название группы int Year; // курс float Rating; // рейтинг }; //Объявляем указ-ль на структ. данных struct TStudent *Student;

// Создаём студента struct TStudent Zuev = {“Зуев А. А. ”, “И-12 -10”, 1, // Создаём студента struct TStudent Zuev = {“Зуев А. А. ”, “И-12 -10”, 1, 20. 6}; Student = &Zuev; Student->Rating = 25. 1; // или (*Student). Rating= 25. 1;

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

Например: struct Options { bool center: 1; unsigned int shadow: 2; unsigned int palette: Например: struct Options { bool center: 1; unsigned int shadow: 2; unsigned int palette: 4; }

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

#include <stdio. h> void main() { enum paytype {CARD, CHECK}; paytype pt; union payment #include void main() { enum paytype {CARD, CHECK}; paytype pt; union payment { char card[25]; long check; } info; …// присваивание значений info и pt

switch (pt) { case CARD: printf(“Оплата по карте %s”, info. card); break; case CHECK: switch (pt) { case CARD: printf(“Оплата по карте %s”, info. card); break; case CHECK: printf(“Оплата чеком %ld”, info. check); break; } }

Директивы препроцессора Директивы препроцессора

Препроцессор – первая фаза компилятора. Инструкции препроцессора называются директивами. Директивы начинаются с символа #. Препроцессор – первая фаза компилятора. Инструкции препроцессора называются директивами. Директивы начинаются с символа #.

Директива #include <файл> Вставляет содержимое указанного файла в ту точку исходного файла, где она Директива #include <файл> Вставляет содержимое указанного файла в ту точку исходного файла, где она записана. < > - поиск ведётся в стандартном каталоге включаемых файлов; “ “ - поиск ведётся в каталоге с исходным файлом, а затем в стандартном каталоге.

Заголовочные файлы обычно имеют расширение. h и могут содержать: • Определения типов, констант, шаблонов, Заголовочные файлы обычно имеют расширение. h и могут содержать: • Определения типов, констант, шаблонов, перечислений; • Объявления функций, данных, шаблонов; • Пространства имён; • Директивы препроцессора; • Комментарии.

В заголовочном файле не должно быть определений функций и данных. В заголовочном файле не должно быть определений функций и данных.

Директива #define Определяет подстановку в тексте программы. Она используется для определения: • Символических констант: Директива #define Определяет подстановку в тексте программы. Она используется для определения: • Символических констант: #define имя текст_подстановки • Макросов (выглядят как функции, но реализуются подстановкой их текста в текст программы): #define имя(параметры)текст_подст.

 • Символов, управляющих условной компиляцией (используется вместе с #ifdef и #ifndef): #define имя • Символов, управляющих условной компиляцией (используется вместе с #ifdef и #ifndef): #define имя Примеры: #define Version 1 #define Vasya “Василий Иванович” #define Мах(x, y) ((x)>(y))? (x): (y) #define MUX Имена рекомендуется записывать прописными буквами.

В С++ вместо символических констант предпочтительнее использовать const и enum , вместо макросов – В С++ вместо символических констант предпочтительнее использовать const и enum , вместо макросов – функции или шаблоны.

Директивы условной компиляции #if, #ifdef, #ifndef применяются, чтобы исключить компиляцию отдельных частей программы. Это Директивы условной компиляции #if, #ifdef, #ifndef применяются, чтобы исключить компиляцию отдельных частей программы. Это полезно при отладке или при поддержки нескольких версий программы для различных платформ.

#if константное_выражение. . . [ #elif константное_выражение. . . ] [ #else. . . #if константное_выражение. . . [ #elif константное_выражение. . . ] [ #else. . . ] #endif

#if VERSION == 1 #define INCFILE “vers 1. h” #elif VERSION == 2 #define #if VERSION == 1 #define INCFILE “vers 1. h” #elif VERSION == 2 #define INCFILE “vers 2. h” #else #define INCFILE “vers 3. h” #endif #include INCFILE

Директивы #ifdef и #ifndef позволяют управлять компиляцией в зависимости от того, определён ли с Директивы #ifdef и #ifndef позволяют управлять компиляцией в зависимости от того, определён ли с помощью #define указанный в них символ или нет. #ifdef символ // код компилируется, если символ определён #ifndef символ // код компил-ся, если символ не определён

Действие этих директив распростаняется до первого #elif, #else или #endif. Пример: #ifndef FILE_INCLUDED #define Действие этих директив распростаняется до первого #elif, #else или #endif. Пример: #ifndef FILE_INCLUDED #define FILE_INCLUDED “myheader. h” #endif. . . #include FILE_INCLUDED

Ввод и вывод. Работа с файлами Ввод и вывод. Работа с файлами

Имеется 2 основных типа функций вводавывода: • Потоковые – данные при вводе/выводе рассматриваются как Имеется 2 основных типа функций вводавывода: • Потоковые – данные при вводе/выводе рассматриваются как поток байтов. Обеспечивается буферизованный (форматированный или неформатированный) ввод/вывод. • Низкоуровневые – непосредственно обращаются к средствам ввода-вывода операционной системы. Не выполняют буферизации и форматирования (open, close, read, write).

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

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

Использование буфера повышает скорость передачи данных, так как пересылки осуществляются только тогда, когда буфер Использование буфера повышает скорость передачи данных, так как пересылки осуществляются только тогда, когда буфер уже заполнен (при выводе) или пуст (при вводе). В зависимости от устройства ввода/вывода потоки делятся на: • Стандартные (клавиатура и дисплей), • Строковые (символы потока образуют строку в основной памяти), • Файловые.

Потоковый ввод/вывод в С++ реализуется либо с помощью функций, унаследованных от С (<stdio. h>), Потоковый ввод/вывод в С++ реализуется либо с помощью функций, унаследованных от С (), либо с помощью потоков С++ (, ).

Потоковый в/в в С Заголовочный файл - <stdio. h> Существует 5 потоков, открывающихся в Потоковый в/в в С Заголовочный файл - Существует 5 потоков, открывающихся в начале работы программы: stdin – стандартный ввод, stdout – стандартный вывод, stderr – стандартный вывод сообщений об ошибках, stdaux – стандартный дополнительный поток, stdprn – стандартная печать.

Операции в/в начинаются с текущей позиции потока, определяемой положением указателя потока. Основные функции в/в Операции в/в начинаются с текущей позиции потока, определяемой положением указателя потока. Основные функции в/в потока: • Чтение и запись потока байтов fread, fwrite; • Чтение символа из потока getc, fgetc, из стандартного потока stdin-getchar; • Запись символа в поток putc, fputc, в стандартный поток stdout- putchar; • Чтение строки из потока fgets, из стандартного потока stdin - gets;

 • Запись строки в поток fputs, в стандартный поток stdout- puts; • Форматированный • Запись строки в поток fputs, в стандартный поток stdout- puts; • Форматированный ввод из потока – fscanf, из стандартного потока stdinscanf, из строки - sscanf; • Форматированный вывод в поток – fprintf, в стандартный поток stdoutprintf, в строку - sprintf;

Работа с потоком на примере работы с файлом: 1) Открытие потока. Поток можно открыть Работа с потоком на примере работы с файлом: 1) Открытие потока. Поток можно открыть для чтения и записи в двоичном или текстовом режиме. Формат: FILE* fopen(const char* filename, const char* mode); первый параметр – имя файла, второй – режим открытия файла:

“r” – для чтения, “w” – пустой файл для записи (существующий файл стирается), “a”- “r” – для чтения, “w” – пустой файл для записи (существующий файл стирается), “a”- для добавления информации в конец файла, “r+” – существующий файл для чтения и записи, “w+” – пустой файл для чтения и записи (существующий файл стирается), “a+” – для чтения и добавления информации в конец.

В режиме открытия могут быть символы t (текстовый режим) и b (двоичный режим) - В режиме открытия могут быть символы t (текстовый режим) и b (двоичный режим) - по умолчанию текстовый режим. При успешном открытии функция возвращает указатель на структуру типа FILE (указатель на файл), в противном случае – NULL. Пример: FILE* f=fopen(“d: \cpp\data”, ”rb”);

2) Ввод/вывод в поток – в виде последовательности байтов, в виде символов и строк 2) Ввод/вывод в поток – в виде последовательности байтов, в виде символов и строк или с использованием форматирования (см. список потоковых функций)

3) Закрытие потока Поток закрывается при завершении программы либо с помощью функции fclose: int 3) Закрытие потока Поток закрывается при завершении программы либо с помощью функции fclose: int fclose(FILE*);

#include <stdio. h> int main() { int a; FILE *f; if(!(f=fopen(“test. txt”, ”w+t”))) {printf(“Невозможно #include int main() { int a; FILE *f; if(!(f=fopen(“test. txt”, ”w+t”))) {printf(“Невозможно открытьn”); return 0; } for(a=0; a<1000; a+=3) fprintf(f, ”%d, ”, a); fclose(f); return 1; }

Для перемещения по файлу можно использовать функции: 1. int fseek(FILE *f, long bt, int Для перемещения по файлу можно использовать функции: 1. int fseek(FILE *f, long bt, int where); Установка указателя на заданную позицию: Bt – на сколько байтов сместить, Where =0 – смещать от начала файла, =1 – от текущей позиции указателя, =2 – от конца файла

2. long ftell(FILE *f); Возвращает значение указателя на текущую позицию файла (в байтах от 2. long ftell(FILE *f); Возвращает значение указателя на текущую позицию файла (в байтах от начала файла). В случае ошибки возвращает -1. 3. void rewind(FILE *f); Возвращает указатель на начало файла.

Потоковый ввод/вывод в стиле С++ Потоки cin, cout, cerr (<iostream. h>) являются аналогами потоков Потоковый ввод/вывод в стиле С++ Потоки cin, cout, cerr () являются аналогами потоков stdin, stdout, stderr. Они открываются автоматически при запуске программы. Они являются объектами класса «поток» . Для ввода/вывода с помощью этих потоков используются операции << (занести в поток) и >>(извлечь из потока): cin>>X>>Y; cout<<“Y=“<

Список функций для работы с файловыми потоками хранится в заголовочном файле fstream. h ( Список функций для работы с файловыми потоками хранится в заголовочном файле fstream. h ( #include )

1. Создание потоков ifstream in_stream; /*создаётся файловый поток ввода с именем in_stream (in_stream-объект класса 1. Создание потоков ifstream in_stream; /*создаётся файловый поток ввода с именем in_stream (in_stream-объект класса ifstream)*/ ofstream out_stream; //создаётся файловый поток вывода с именем out_stream 2. Подключение и отключение потоков После создания потока его можно подключить к файлу с помощью метода open.

in_stream. open( in_stream. open("Lecture_4. txt"); /* подключили поток “in_stream” к началу файла Lecture_4. txt */

out_stream. open( out_stream. open("Lecture_4. txt"); /* подключили поток "out_stream" к файлу "Lecture_4. txt", прежнее содержимое файла будет удалено */

Для отключения потока Для отключения потока "in_stream" от файла (для закрытия файла) вызывают метод close(): in_stream. close();

Аналогично для потока вывода: out_stream. close(); - добавляет в конец файла служебный символ EOF Аналогично для потока вывода: out_stream. close(); - добавляет в конец файла служебный символ EOF (end-of-file). Если данные не записывались, то создаётся пустой файл:

3. Проверка ошибок файловых операций Простейший способ проверки - вызов метода fail(): in_stream. fail(); 3. Проверка ошибок файловых операций Простейший способ проверки - вызов метода fail(): in_stream. fail(); - возвращает True, если последняя операция привела к ошибке (например, была попытка открытия несуществующего файла). После ошибки поток может быть поврежден, поэтому лучше не продолжать работу с ним.

#include <iostream. h> #include <fstream. h> #include <stdlib. h> // exit() int main() { #include #include #include // exit() int main() { ifstream in_stream; in_stream. open("Lecture_4. txt"); if (in_stream. fail()) { cout << “Открыть файл не удалось!n"; exit(1); // завершить выполнение программы }. . .

4. Символьный ввод/вывод 4. 1. Функция ввода get (чтение символа из файла) in_stream. get(ch); 4. Символьный ввод/вывод 4. 1. Функция ввода get (чтение символа из файла) in_stream. get(ch);

4. 2. Функция вывода put (запись символа в файл): out_stream. put('Л'); 4. 2. Функция вывода put (запись символа в файл): out_stream. put('Л');

5. Проверка конца файла (функция eof()) В класс 5. Проверка конца файла (функция eof()) В класс "поток ввода" встроен флаг EOF (конец файла) и метод eof() для чтения этого флага. Ниже приведена программа для копирования текстового файла "Lecture_4. txt" одновременно и на экран, и в другой файл "Copy_of_4. txt".

#include <iostream. h> #include <fstream. h> int main() { character; ifstream in_stream; ofstream out_stream; #include #include int main() { character; ifstream in_stream; ofstream out_stream; in_stream. open( "Lecture_4. txt" ); out_stream. open( "Copy_of_4. txt" ); in_stream. get( character );

while ( !in_stream. eof() ) { cout << character; out_stream. put(character); in_stream. get(character); } while ( !in_stream. eof() ) { cout << character; out_stream. put(character); in_stream. get(character); } out_stream. close(); in_stream. close(); return 0; }

>" и "<<" Объекты классов ofstream and ifstream всегда работают с" src="https://present5.com/presentation/3/134168901_132542173.pdf-img/134168901_132542173.pdf-66.jpg" alt="7. Операторы ввода/вывода ">>" и "<<" Объекты классов ofstream and ifstream всегда работают с" /> 7. Операторы ввода/вывода ">>" и "<<" Объекты классов ofstream and ifstream всегда работают с файлами как с последовательностями символов. Данные других типов ("int", "double" и др. ) для записи в файл должны быть преобразованы в последовательность символов. При чтении из файла эти последовательности должны быть преобразованы обратно.

>" и "<<". out_stream << 437 <<" src="https://present5.com/presentation/3/134168901_132542173.pdf-img/134168901_132542173.pdf-67.jpg" alt="Некоторые преобразования типов данных автоматически выполняются операторами ">>" и "<<". out_stream << 437 <<" /> Некоторые преобразования типов данных автоматически выполняются операторами ">>" и "<<". out_stream << 437 << ' '; in_stream >> n; При использовании операторов ">>" и "<<" надо после каждого записанного значения записывать еще как минимум один пробел или 'n' (маркер конца строки). Тогда данные будут отделены в файле друг от друга, и их можно будет извлекать оттуда с помощью оператора ">>".

Пример Сначала программа создает файл Пример Сначала программа создает файл "Integers. txt", записывает в него целые числа 51, 52, 53, 54 и 55, а затем считывает эти числа из файла. #include #include int main() { character; int number = 51; int count = 0; ofstream out_stream; // Поток для подсчета целых чисел. ifstream in_stream 1; // Поток для подсчета символов. ifstream in_stream 2;

// Создание файла out_stream. open( // Создание файла out_stream. open("Integers. txt"); for(count=1; count<=5; count++ ) out_stream << number++ << ' '; out_stream. close(); // Подсчет количества целых чисел в файле in_stream 1. open("Integers. txt"); count=0; in_stream 1 >> number; while ( !in_stream 1. eof()) { count++; in_stream 1 >> number; }

in_stream 1. close(); cout<< in_stream 1. close(); cout<<"В файле "<> character; while ( !in_stream 2. eof() ) { count++; in_stream 2 >> character; } in_stream 2. close(); cout<<"представленных с помощью "<

В отличие от функции get(), оператор >> игнорирует в файле разделители (пробелы). В отличие от функции get(), оператор >> игнорирует в файле разделители (пробелы).