Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

6 Структурированные типы данных 2012

.pdf
Скачиваний:
50
Добавлен:
29.02.2016
Размер:
529.73 Кб
Скачать

 

 

21

 

 

 

Ymiddle2=Ymiddle2/N;

// Расчет

среднеквадратичного

значения Y

Xmiddle=Xmiddle/N;

 

// Расчет

среднего

значения X

 

Xmiddle2=Xmiddle2/N;

// Расчет

среднеквадратичного

значения X

cout << "Число точек=" << N << endl;

 

 

 

cout << "Максимум

Y =" << Ymax <<

"при

X="

<< Xmax <<

endl;

cout << "Минимум

Y =" << Ymin <<

"при

X="

<< Xmin <<

endl;

cout << "Среднее значение

Y

=" << Ymiddle << endl;

cout << "Среднеквадратичное значение Y

=" << Ymiddle2

<< endl;

cout << "Сумма значений1 аргумента X

="

<< Xsum <<

endl;

cout << "Сумма значений1 функции Y

 

="

<< Ysum <<

endl;

cout << "Среднее значение

X

=" << Xmiddle << endl;

cout << "Среднеквадратичное значение X

=" << Xmiddle2

<< endl;

getch();

// Приостановка

закрытия

консоли

 

return 0;

// Возврат кода

успешного завершения;

}// -------------------------------------- Конец программы

6.8.7 Перемещения по файлу в С++

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

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

1)seekg(номер_байта,ios:: смещение) – перемещение текущей позиции чтения данных (позиция "get");

2)seekp(номер_байта,ios:: смещение) – перемещение текущей позиции записи

данных (позиция "put");

3)tellg() – возвращает значение текущей позиции внутри файла для ввода данных (позиция “get”);

4)tellp() - возвращает значение текущей позиции внутри файла для вывода

данных (позиция “put”);

5) eof() – возвращает true если достигнут конец файла.

В seekp и seekg искомые позиции в относительных смещениях задаются как:

-ios::beg - перемещение от начала файла;

-ios::cur - перемещение вперед от текущей позиции;

-ios::end - перемещение от конца файла.

Пример возможности позиционирования потока ввода информации:

#include < iostream.h > #include < fstream.h >

void main(int argc, char* argv[])

{int size = 0; if (argc > 1)

{const char *FileName = argv[1]; ofstream of;

of.open( FileName, ios::binary );

for(int i = 0; i<100; i++) of.put ((char)(i+27)); of.close();

ifstream file;

file.open(FileName, ios::in | ios::binary); if (file){file.seekg(0, ios::end);

size = file.tellg(); if (size < 0)

{cerr << FileName << " не найден."; return;

}

cout << FileName << " size = " << size<

}

}

else cout << "Вы не задали имя файла.";

} // -------------------- конец программы -------------------------------

22

6.8.9 Буферизированный ввод-вывод с файлами в языке С++

В С++ имеется возможность использовать два способа буферезированного ввода-вывода:

1)с помощью строкового (текстового) буфера потоков ifstream и ofstream;

2)с помощью нетипизированного буфера модулей filebuf и stdiobuf.

Если использовать файловый ввод данных через текстовый буфер модуля fstream.h, то чтение информации из файла осуществляется встроенной функцией read() потока istream, которая имеет следующие прототипы:

Фаловый_поток_типа_istream.read(строковый_буфер,число_символов_буфера); Запись данных через строковый буфер осуществляет функция-член write() для

класса потока ofstrem: Фаловый_поток_типа_ostream.read(строковый_буфер,число_символов_буфера); Эта функция получает n символов из буфера, адрес которого задан параметром

s, и вставляет их в поток вывода. Пример: #include< iostream.h >

#include< fstream.h > void main()

{int x = 255;

char str[80] = "Тестирование двоичного ввода-вывода."; // Открываем файл для вывода в двоичном режиме ofstream ofs("Test.dat");

if (!ofs) { cout << "Файл не открыт!"; return -1; } ofs.write((char*)&x, sizeof(int)); ofs.write((char*)&str, sizeof(str));

ofs.close();

ifstream ifs("Test.dat");// Открывается файл для вывода if (!ifs) { cout << "Файл не открыт.\n"; return -10; } ifs.read((char*)&x, sizeof(int));

ifs.read((char*) str, sizeof(str));

cout << x << '\n' << str << '\n';

}

Класс streambuf используется для потокового буферизованного ввода/вывода. Ниже описываются два элемента типа filebuf, после этого открываются текстовые

файлы,

Затем каждый элемент filebuf связывается с соответствующим объектом.

Далее выполняется печать из входного потока в выходной.

#include <fstream.h>

 

#include <fcntl.h>

 

void main()

 

{ char

ch;

 

long

linecount=0;

 

filebuf inbuf,outbuf;

//объявление буферов

inbuf.open(“infile.dat”,_O_RDONLY | _O_TEXT); //открытие входного файла if(inbuf.is_open()==0)

{ cerr<<”cant open input file”; return -1;

}

istream is(&inbuf); //объявление входного потока outbuf.open(“outfile.dat”,_O_WDONLY | _O_TEXT); //открытие выходного файла if(outbuf.is_open()==0)

{ cerr<<”cant open output file”; return -1;

}

ostream os(&outbuf); //объявление выходного потока while(is)

{is.get(ch); //чтение из потока os.put(ch); //запись в поток if(ch==’\n’) linecount++;

}

inbuf.close(); //закрытие файлов outbuf.close();

cout<<”\nYou had: “<<linecount<<” lines”;

23

}

Допустимо использовать следующие методы класса filebuf: attach(), close(), fd(), is_open(), open(), overflow(), seekoff(), setbuf(), sync(), underflow().

6.8.10 Поиск файлов во внешней памяти

В составе модуля dir имеются две функции, которые позволяют выполнять поиск файлов по заданной строке шаблона имени файлов (маске) используя ресурсы операционной системы MS-DOS:

1)findfirst производит поиск первого файла в текущем каталоге диска (или по указанному в маске пути);

2)findnext – продолжает поиск по заданным в findfirst критериям следующего файла.

Формат finfirst:

int findfirst(char* pathname, struct ffblk *ffblk, int attrib);

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

ffblk - структура с информацией о файле и каталоге, его содержащем; attrib – атрибуты фавйла.

Структура ffblk содержит следующее описание: struct ffblk

{char ff_reserved[21]; /* зарезервировано DOS */

char

ff_attrib;

/* атрибуты */

int

ff_ftime;

/* время

*/

int

ff_fdate;

/* дата

*/

long

ff_fsize;

/*

размер */

char

ff_fname[13];

/*

имя файла */

};

Параметр attrib может быть задан с помощью констант, определенных в файле dos.h:

-FA_RDONLY - АТРИБУТ "только чтение";

-FA_HIDDEN - скрытый файл;

-FA_SYSTEM - системный файл;

- FA_LABEL

- метка тома;

-

FA_DIREC

-

каталог;

-

FA_ARCH

-

архив.

При успешном завершении, то есть при успешном значение поиске файла, соответствующего параметру pathname, функция findfirst возвращает значение 0. Если подходящих файлов больше не существует, или в имени файла допущена ошибка, функция возвращают значение -1 и глобальная переменная errno получает одно из следующих значений:

1)ENOENT - маршрут доступа или имя файла не найдены;

2)ENMFILE - нет больше файлов.

//--------------

Пример поиска файлов -------------------------------------

#include

<fstream.h>

 

#include

<iostream.h>

 

#include

<iomanip.h>

 

#include

<conio.h>

 

#include

<dir.h>

 

#pragma hdrstop

 

//---------------------------------------------------------------------------

 

 

#pragma argsused

 

int main(int argc, char* argv[])

{ char Mask[100];

// Маска поиска

int iAttributes = 0;

// Атрибуты файла

int count=0; // счетчик найденных файлов

struct

ffblk ffblk;

// Структура с данными о файле

int Done;

// Код завершения поиска

cout << " \n The Mask : ";

// Вывод запроса на

ввод маски

cin >> Mask;

//

Ввод маски

поиска с клавиатуры

cout << endl;

//

Перевод на

новую

строку

Done=findfirst(Mask, &ffblk, iAttributes);

 

// Поиск первого файла

 

 

24

 

 

while(!Done)

 

// Цикл поиска файлов

{ count++;

// Инкрементация счетчика файлов

 

cout.width(25);

 

 

 

 

cout<< ffblk.ff_name<<" - "<<ffblk.ff_fsize<<"b"<<endl;

// Вывод

результата

 

 

 

 

Done=findnext(&ffblk);

 

// Поиск следующего файла

}

// конец тела цикла

 

 

 

cout << "\n Number files - " << count;

// Вывод числа найденных файлов

cout << "\nKEY PRESSED !!!" ;

 

// Сообщение о завершении работы

getch();

 

// Приостановка закрытия окна

return 0;

 

// Возврат кода успешного завершения

} //

---------------------------------------------------------------------------

 

 

 

6.9 Тип перечисления

Этот тип в языках С и С++ описывает перечисления – набор именованных целочисленных констант. Объявляется перечисление с помощью зарезервированного слова enum в следующем формате

enum имя_перчисления {нумеератор1, нумеератор2, } имя_переменной;

Например enum Tdays {sun, mon, tues, wed, thur, fri, sat} anyday;

устанавливает тип Tdays, переменную anyday этого типа и набор нумераторов (sun, mon, ...), которым соответствуют целочисленные константы.

Данные типа enum всегда int, но при использовании их в выражениях

выполняется этих данных преобразования

к типу int. Идентификаторы, используемые

в списке нумераторов, неявно получают

тип unsigned char или int, в зависимости

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

В C переменной

типа

enum

может

быть

присвоено любое

значение типа

int. В

С++ переменной

перечислимого типа может присваиваться только значение одного из

ее нумераторов. Таким образом,

 

 

 

 

 

anyday =

mon;

// так

можно

 

 

 

 

anyday =

1;

// так

нельзя, даже хотя mon == 1

 

 

Идентификатор

days

является

тегом

перечислимого

типа, который

можно

использовать в последующих объявлениях переменных перечислимого типа enum days: enum days payday, holiday; // объявление двух переменных

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

enum { sun, mon, tues, wed, thur, fri, sat } anyday; // анонимный тип enum

Нумераторы, перечисленные внутри фигурных скобок, называются перечислимыми константами. Каждой из них назначается фиксированное целочисленное значение. При отсутствии явно заданных инициализаторов первый нумератор (sun) устанавливается в ноль, а каждый последующий нумератор имеет значение на единицу больше, чем предыдущий (mon = 1, tue = 2 и т.д.).

Можно установить нумераторы в конкретные значения. Любые последующие имена без инициализаторов будут получать приращение в единицу. Например, в следующем объявлении:

enum coins { penny=1, tuppence, nickel=penny+4, dime=10, quarter=nickel*nickel } smallchange;

tuppence примет значение 2, nickel - значение 5, а quarter - значение 25. Инициализатор может быть любым выражением, дающим целочисленное значение.

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

enum

может

участвовать во всех конструкциях, допускающих использование

типов int.

 

 

enum days {

sun,

mon, tues, wed, thur, fri, sat } anyday;

enum

days payday;

typedef

enum

days DAYS;

DAYS

*daysptr;

int

i

= tues;

anyday

= mon;

// так можно

25

*daysptr = anyday; // так можно

mon = tues; // неверно: mon - это константа

Пример программы с перечислением для обозначения типа компьютера: #include <iostream.h> // Подключение потоков консоли

#include <conio.h>

// Подключение функции getch

enum PCtype {

server, desktop, notebook, netbook, handbook} pc;

int main()

 

// Начало главной функция программы

{ int code;

 

// Переменная кода ввода типа ПК

cout <<

"Выберите тип компьютера : " << endl; // Вывод меню

cout <<

"0

-

сервер "

<< endl;

cout <<

"1

-

настольный

ПК " << endl;

cout <<

"2

-

ноутбук "

<< endl;

cout <<

"3

-

нетбук

"

<< endl;

cout <<

"4

-

КПК "

<< endl;

cin >> code;

// Чтение кода типа ПК с клавиатуры

pc=code;

 

 

// Присваивание перечислению значения

switch(pc)

 

 

 

// Переключатель вывода типа ПК

{ case server : cout << "тип компьютера-сервер" << endl;

 

 

 

break;

 

case desktop : cout<<"тип компьютера-настольный ПК"<<endl; break;

case notebook : cout << "тип компьютера-ноутбук" << endl; break;

case netbook : cout << "тип компьютера - нетбук" << endl; break;

case handbook : cout << "тип компьютера - КПК" << endl; break;

} // Конец блока оператора switсh

getch(); // Приостановка закрытия консоли return 0; // Возврат кода успешного завершения

}//-----------------------------------------------------------

6.10 Совместимость и преобразование типов данных

6.10.1 Основные понятия совместимости типов

Различают следующие понятия при сравнении различных типов данных:

1)тождественность типов данных двух переменных означает, что две переменные используют один идентификатор типа данных;

2)совместимость двух типов данных означает, что вместо переменной одного

типа данных можно использовать переменную второго типа данных без потери

информации;

 

 

 

 

 

 

3) совместимость

по

присваиванию

(A=B)

двух

типов

данных

(typeА A и typeB B) означает, что при операции присваивания переменной A можно передать значение переменной B без потери или искажения данных.

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

struct s1 { int a; }; // Первый тип структура struct s2 { int a; }; // Второй тип структура

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

s1

x;

 

 

s2

y = x;

// Ошибка несоответствия типов

int i

= x;

// Ошибка несоответствия типов.

26

6.10.2 Определение нового имени типа с помощью typedef

Имеется возможность выполнить описание нового имени для существующего типа с использованием префикса typedef, которое при этом не приводит к созданию нового типа. Формат описания нового имени типа:

typedef имя_типа новое_имя_типа;

Пример:

typedef int length;

Это описание делает имя length синонимом стандартного типа int. «Тип» length может быть использован в описаниях, преобразованиях типов и т.д. аналогично применению типа int. Примеры:

length

len, maxlen;

//

Объявление переменных типа int

length

*lengths[];

//

Формирование указателя на вектор

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

typedef *char string;

Это делает string синонимом для *char, то есть для указателя на символы, что затем можно использовать в описаниях вида

string p, lineptr[lines], alloc();

6.10.3 Преобразование типов данных в языке С++

Для придания программе гибкости и универсальности используется преобразование одного типа данных в другой. В языках С и С++ это можно выполнить тремя способами:

1)с помощью операций неявного преобразования типов в выражениях;

2)с помощью явного приведения типа;

3) с помощью переменных, хранящих

данные

в

одной области памяти

(например, объединений или указателей).

 

 

 

Неявные преобразования используются,

если

в

выражениях встречаются

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

1)типы char и int могут свободно смешиваться в арифметических выражениях: переменная типа char автоматически преобразуется в int;

2)выражения отношения и логические выражения, связанные операциями && и

||, по определению имеют значение 1, если они истинны, и 0, если они ложны; 3) к арифметической операции применяется следующая последовательность

правил преобразования:

типы char и short преобразуются в int, а float в double;

если один из операндов имеет тип double, то другой преобразуется в double и результат имеет тип double;

если

один из операндов имеет тип long, то другой преобразуется в

long

и результат имеет тип long;

если один из операндов имеет тип unsigned, то другой преобразуется в unsigned и результат имеет тип unsigned;

4)все переменные типа float в выражениях преобразуются в double − вся вещественная арифметика выполняется с двойной точностью.

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

без него. При обратном преобразовании типа int в char лишние биты высокого порядка отбрасываются.

Если тип float присваивается типу int, то преобразование float в int выполняется отбрасыванием дробной части. Тип double преобразуется во float округлением. Длинные целые преобразуются в более короткие целые и в переменные типа char посредством отбрасывания лишних битов высокого порядка.

27

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

Внутри выражения может осуществляться явное преобразование типа с помощью конструкции, называемой переводом (CAST), имеющей следующий формат:

(имя_типа)выражение

Смысл этой операции в том, что выражение условно присваивается некоторой переменной указанного типа, используемой вместо всей конструкции. Это может быть необходимо, например, для функции извлечения корня sqrt, которая ожидает аргумента типа double. Если N - целое, то можно выполнить выражение

int N=3; // Объявление целочисленной переменной cout << sqrt((double) N); // Вывод значения корня от 3

В примере N преобразует к типу double до передачи аргумента функции sqrt. Явное приведение типов также используется при преобразовании указателей.

При этом используется следующий формат:

(имя_базового_типа*) указатель;

Так обозначение (базовый_тип*) преобразует указатель в тип «указатель на базовый тип данных». Ниже показан пример преобразования указателей на базовые типы char и int.

char

*str;

// Указатель

символьного типа

int *ip;

// Указатель

целочисленного типа

str = (char*) ip;

//

Приведение

второго

указателя

ip =

(int*) str;

//

Приведение

первого

указателя

6.10.4 Определение размера типа

Специальная операция sizeof(тип-операнд) позволяет определить размер в байтах стандартного или определяемого пользователем типа данных. Возможны два способа использования операции sizeof:

1)унарное sizeof выражение;

2)sizeof (имя_типа).

Впервом случае тип выражения операнда определяется без расчета выражения (без побочных эффектов). Если операнд имеет тип char (signed или unsigned), то операция sizeof дает в результате 1. Если операнд не является параметром и имеет тип массива, то результат представляет собой общее количество байтов в массиве (имя массива не преобразовывается к типу указателя). Число элементов массива можно определить как

Число_элементов = sizeof (массив) / sizeof (массив[0]);

Если операнд sizeof является массивом или функцией, то sizeof дает размер указателя. Применительно к структурам и объединениям sizeof дает общее число байтов, включающее любые символы-заполнители.

В языке С++ для объектно-ориентированных программ операция

sizeof(тип_производного_класса_от_базового)

возвращает размер базового класса.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]