Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Пример. void __fastcall TForm1::Button1Click(TObject *Sender)




void __fastcall TForm1::Button1Click(TObject *Sender)

{

TStringList *MyList=new TStringList;

ListBoxl->Clear(); // очистить список

ListBox1->Items->Add("Первый элемент");

// Свойство Items содержит метод Add() и другие методы

MyList->Add(ListBox1->Items[ListBox1->ItemIndex+1].GetText());

MyList->Add("Последняя строка");

ListBox1->Items->AddStrings(MyList);

}

 

Контейнерные списочные классы TStringList и TList решают проблему динамического распределения памяти. Хотя списочные классы TStringList и TList не являются прямыми потомками одного предка, однако они имеют много общих методов: Add() – добавить элемент в конец списка; Clear() – очистить список; Delete() – удалить элемент с указанным номером; Exchange() – поменять два элемента местами; Insert() – вставить элемент в указанную позицию; Move() – переместить элемент из одной позиции в другую; Sort() – отсортировать список. Важным дополнением к перечисленным методам является свойство Count, содержащее текущее число элементов в списке.

Класс TStringList является потомком класса ТStrings, наследующим свойства и методы родителя. Однако TStrings это абстрактный базовый класс, который не способен производить объекты.

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

 

void _fastcall TForml::TForml(TComponent* Owner): TForm(Owner)

{ TStringList * MyList;

MyList = new TStringList; // создать объект

MyList->Add("Раз");

MyList->Add("Два");

MyList->Add("Три");

MyList->Duplicates = dupIgnore; // игнорировать дубликаты

MyList->Sorted = true; // сортировка списка

ListBox1->Items->AddStrings(MyList); // отображение списка

}

 

Метод Add() добавляет в конец списка строку вместе с указателем на сопровождающий объект. Метод AddStrings() добавляет в конец списка группу строк, взятых из другого списочного объекта. Метод Find() выдает номер строки в отсортированном списке и возвращает значение false, если такой строки нет в списке. Метод IndexOf() возвращает номер строки, под которым она впервые встретилась в списке (как отсортированном, так и нет). Метод LoadFromFile() загружает строки списка из текстового файла. Метод SaveToFile() сохраняет список в текстовом файле

Для хранение объектов используется другой списочный класс TList. Ниже приводится пример использования класса TList для хранения различных объектов (модуль Unit2.cpp). Конструктор главной формы создает список MyList, а затем заносит в него названия файлов, содержащих значки выполняемых программ, и сами значки.

 

TList* MyList; // объявление в файле Unit2.h

// Инициализация списка конструктором главной формы

__fastcall TForm2::TForm2(TComponent* Owner): TForm(Owner)

{

MyList = new TStringList; // создать объект MyList

// Загрузить файл имен и отобразить их в компоненте ListBox2

ListBox2->Items->LoadFromFile("Names.txt");

// Перебрать имена программ и сформировать список MyList

for (int i=0; i<ListBox2->Items->Count; i++)

{

String str = ListBox2->Items->Strings[i];

int pos=str.LastDelimiter(“.”); // найти символ ‘.’

str.Delete(pos,4); // стереть расширение файла.exe

str.Insert(“.ico”,pos); // заменить расширение файла на.ico

TIcon* icon = new TIcon; // создать новый объект icon

icon->LoadFromFile(str); // загрузить объект icon

MyList->AddObject(str, icon); // добавить str, icon в список

}

}

 

Элементы списка нумеруются, начиная с 0, и адресуются посредством индексируемого свойства Strings[i]. Например, заголовку формы можно присвоить название, взятое из второй строки списка следующим образом:

 

Form1->Caption = MyList->Strings[2];

В ряде случаев удобно интерпретировать строчный список как единую строку текста. Свойство Text содержит все строки списка:

Form1->Caption = MyList->Text;

Далее приводится реакция на событие выбора строки из списка ListBox2:

void__fastcall TForm2::ListBox2Click(TObject *Sender)

int i = ListBox2->ItemIndex; // номер строки

//Сдвинуть изображение и вывести пиктограмму

Label2->Top=8+i*16; // сдвинуть изображение стрелки

Image2->Top = i*16; // сдвинуть изображение значка

Image2->Picture->Icon =

dynamic_cast<TIcon*> (MyList->Objects [i]);

// Свойство CommaText содержит все строки списка,

// разделенные запятыми:

Form1->Caption = MyList->CommaText;

}

 

Свойство CommaText преобразует список к формату SDF (System Data Format), обеспечивая возможность импорта данных из внешней программы непосредственно в контейнерный объект VCL. При этом любая строка, содержащая пробелы или запятые, заключается в двойные кавычки.

Листинг кодового модуля Unit2.cpp, приведенный выше, иллюстрирует применение метода AddObject() на примере списка, в котором имена выполняемых программ файла Names.txt ассоциируются с их пиктограммами (объектами класса TIcon). Конструктор главной формы создает список MyList, объявленный в интерфейсном модуле Unit2.h, а затем заносит в него названия и изображения пиктограмм. Упомянутое ранее индексируемое свойство Objects содержит типизированный указатель TObject*, поэтому при выборе пиктограммы оператор dynamic_cast преобразует ее тип обратно к TIcon*.

Наиболее характерное свойство списка TList это Capacity, которое содержит максимальную текущую емкость контейнера. Это значение не является пределом, список всегда можно при необходимости расширять и далее. Преимущества этого свойства появляются, когда списки становятся слишком объемными. Дело в том, что алгоритм перераспределения памяти под списочные классы VCL начинает работать медленно при больших размерах контейнера. Если значение свойства Capacity определить заранее, сразу же после создания списка, перед добавлением в него новых элементов, то этот алгоритм вообще не включается до тех пор, пока заданная емкость контейнера не будет исчерпана. Если предполагается хранить большое количество объектов в списке, то его емкость следует определить сразу же после создания:

 

TList* MyList = new TList;

MyList->Capacity = 1000;

MyList->Add(new TMyObject); // добавить объект

 

Рассмотрим, как можно извлекать объекты из списка. Для динамического преобразования указателя типа void* обратно к типу TMyObject* (в нашем примере) можно использовать оператор

dynamic_cast<TMyObject*> (MyList->Items [i]);

или применить статическое преобразование типа в стиле языка С:

(TMyObject*)MyList->Items[i];

Класс TList предназначен для хранения данных любого типа. Адресный указатель void* на объект любого типа передается как параметр таким методам, как Add() и Insert(). Класс TList инкапсулирует ряд специализированных методов: First() – возвращает первый указатель списка (элемент индексируемого свойства Items[0]); Last() – возвращает последний указатель списка (элемент индексируемого свойства Items[Count]); Expand() – увеличивает размер списка, когда его текущая емкость Count достигла значения свойства Capacity

3.2. Файлы и потоки

C++Builder предоставляет разработчикам несколько способов организации ввода-вывода файлов:

• в стиле языка С;

• поточные классы стандартного C++;

• класс TFileStream из библиотеки VCL.

Поточные классы и потоки C++. Классы ifstream и оfstream, используемые для чтения и записи в потоки, являются производными от базового класса ios. Класс fstream способен одновременно читать и писать информацию в поток. Под потоками понимают объекты поточных классов. Для использования классов необходимо включить в заголовок модуля файл fstream.h.

Открытие файла. Потоки открываются с помощью конструктора или с помощью метода open().

Режим открытия файлов задают флаги-члены данных перечисляемого типа класса ios:

enum open_mode { арр, binary, in, out, trunc, ate };

В табл. 2 приведены возможные значения флагов.

Таблица 2

Режим Назначение
in Открыть для ввода (по умолчанию для ifstream)
out Открыть для вывода (по умолчанию для ofstream)
binary Открыть файл в бинарном режиме
app Присоединять данные; запись в конец файла
ate Установить указатель позиционирования на конец файла
trunc Уничтожить содержимое, если файл существует (выбирается по умолчанию, если флаг out указан, а флаги ate и арр – нет)

 

Например:

 

ifstream file;

file.open("test.dat", ios::in | ios::binary);

ofstream file;

file.open("test.txt", ios:out | ios::app);

Операторы включения и извлечения. Оператор поточного включения (<<) записывает данные в поток. Например:

ofstream file("temp.txt");

char buff[] = "Текстовый массив ";

int v = 100;

file << buff << endl << v << endl;

file.close();

В результате образуются две строки в текстовом файле temp. txt:

Текстовый массив

100

Оператор поточного извлечения (>>) производит обратные действия. Из-за ограниченности оператора извлечения для ввода могут быть использованы другие методы, например getline().

Класс ifstream: чтение файлов. Класс ifstream предназначен для ввода из файлового потока. В табл. 3 перечислены основные методы класса.

Таблица 3

Метод Описание
open Открывает файл для чтения
get Читает один или более символов из файла
getline Читает символьную строку из текстового файла или данные из бинарного файла до определенного ограничителя
read Считывает заданное число байтов из файла в память
eof Возвращает ненулевое значение (true), когда указатель потока достигает конца файла
peek Выдает очередной символ потока, но не выбирает его
seekg Перемещает указатель позиционирования файла в указанное положение
tеllg Возвращает текущее значение указателя позиционирования
close Закрывает файл

Класс ofstream: запись файлов. Класс ofstream предназначен для вывода данных в файлы. В табл. 4 перечислены основные методы класса:

 

Таблица 4

Метод Описание
open Открывает файл для записи
put Записывает одиночный символ в файл
write Записывает заданное число байтов из памяти в файл
seekp Перемещает указатель позиционирования в заданное положение
tеllp Возвращает текущее значение указателя файла
close Закрывает файл

Бинарные файлы. Бинарные файлы представляют собой последовательность байтов, которая вводится или выводится без каких-либо преобразований.

Для записи бинарных файлов или чтения из них используются методы write() и read(). Первым параметром методов является адрес блока записи/чтения, который должен иметь тип символьного указателя char*. Второй параметр указывает размер блока.

Приведем пример приложения для создания и отображения данных записной книжки. Записи файла считываются и отображаются в строках объекта Memo1.

 

#include <fstream.h>

struct Notes // структура данных записной книжки

{ char Name[60]; // Ф.И.О.

char Phone[16]; // телефон

int Age; }; // возраст

// Обработчик события, возникающего при нажатии кнопки

void __fastcall TForm1::Button1Click(TObject *Sender)

{Notes Notel =

{"Иванов Иван Васильевич", "не установлен", 60};

Notes Note2 =

{"Балаганов Шура ", "095-111-2233 ", 30};

ofstream ofile("Notebook.dat", ios::binary);

ofile.write((char*)&Notel, sizeof(Notes)); // 1-й блок

ofile.write((char*)&Note2, sizeof(Notes)); // 2-й блок

ofile.close (); // закрыть записанный файл

ifstream ifile("Notebook.dat", ios::binary);

Notes Note; // структурированная переменная

char str[80]; // статический буфер строки

Memo1->Clear (); // очистить объект Memo2

//Считывать и отображать строки в цикле, пока не достигнут

// конец файла

while (!ifile.read((char*)&Note, sizeof(Notes)).eof())

{ sprintf(str, "Имя %s Тел: %s\t Boзpacт: %d",

Note.Name, Note.Phone, Note.Age);

Memo1->Lines->Add(str); }

ifile.close (); // закрыть прочитанный файл

}

 

В результате выполнения этого кода образуется бинарный файл

 

Notebook. dat из блоков размером 80 байтов каждый:

Иванов Иван Васильевич Тел: не установлен Возраст: 60

Балаганов Шура Тел: 095-111-2233 Возраст: 30

 

Класс ввода и вывода fstream: произвольный доступ к файлу. Предположим, что мы хотим считать пятидесятую запись из книжки. Очевидное решение – установить указатель файла роs прямо на нужную запись и считать ее:

 

ifstream ifile ("Notebook.dat", ios::binary);

int pos = 49 * sizeof(Notes);

ifile.seekg(pos); // поиск 50-й записи

Notes Note;

ifile.read((char*)&Note, sizeof(Notes));

Чтобы заменить содержимое произвольной записи, надо открыть поток вывода в режиме модификации:

ofstream ofile("Notebook.dat", ios::binary | ios::ate);

int pos = 2 * sizeof(Notes);

ofile.seekp(pos); // поиск 3-й записи

Notes Note=

{"Иванов Иван Николаевич", "095-222-3322", 64};

ofile.write((char*)&Note, sizeof(Notes)); // замена

 

Если не указать флаг ios::ate (или ios::арр), то при открытии бинарного файла Notebook.dat его предыдущее содержимое будет стерто. Можно открыть файл по одновременному чтению/записи, указав флаги ios::in | ios::out.

TFileStream: поточный класс VCL. Основные принципы потоков ввода-вывода С++ используются и в классе TFileStream. В табл. 5 перечислены основные свойства и методы класса TFileStream.

Конструктор предназначен для открытия файла. Методы Read() и Write() идентичны методам read() и write(). Свойство Position реализует те же действия, что и методы tellg() и seekg(), делая процедуру поиска простой. Класс TFileStream лишен метода, аналогичного getline(). В результате оказывается, что класс TFileStream плохо приспособлен к построчному чтению текстовых файлов. Некоторым оправданием этого недостатка являются методы загрузки LoadFromFile() и сохранения SaveToFile() файла, применимые ко многим компонентам библиотеки VCL (TMemo, TListBox, ТСоmboBox, TTreeView и др.).

Таблица 5

Свойство Описание
Position Текущее значение указателя позиционирования файла
Size Размер данных файла; свойство доступно только для чтения
Метод Описание
Конструктор TfileStream Открывает файл в указанном режиме (по созданию, чтению, записи или по чтению/записи одновременно)
CopyFrom Копирует заданное число байтов из некоторого потока в данный
Read Считывает заданное число байтов из файла в память
Write Записывает заданное число байтов из памяти в файл
Seek Перемещает указатель позиционирования в указанное положение относительно начала, конца или текущего положения файла

Режим открытия файла. По сравнению с флагами аргумента open_mode установки режима Mode в классе TFileStream заметно отличаются, что видно из табл. 6.

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

TFileStream* fs = new TFileStream("Notebook.dat",fmOpenRead);

а так – для модификации:

 

TFileStream* fs = new TFileStream("Notebook.dat",

fmOpenReadWrite);

 

Таблица 6

Режим Описание
fmCreate Создать новый файл. Если файл с указанным именем существует, то открыть его для записи
fmOpenRead Открыть файл только для чтения
fmOpenWrite Открыть файл только для записи с полной заменой текущего содержания
fmOpenReadWrite Открыть файл для чтения/записи (модификации)
fmShareExclusive Другие приложения не могут открыть этот файл (исключительное пользование)
fmShareDenyNone He делается никаких попыток предотвратить чтение/запись этого файла из других приложений (полное разделение)
fmShareDenyWrite Другие приложения могут открыть и читать этот файл параллельно с вашим заданием (разделение только по чтению)
fmShareDenyRead Другие приложения могут открыть и записывать в этот файл параллельно с вашим заданием (разделение только по записи)

 

 

Ниже приводится пример использования класса TFileStream для работы с файлом, содержащим записную книжку (выше данная задача решалась с использованием потоков С++):

 

TForm4 *Form4;

struct Notes // структура данных записной книжки

{ char Name[60]; // Ф.И.О.

char Phone[16]; // телефон

int Age;}; // возраст

// Обработчик события, возникающего при нажатии кнопки

void __fastcall TForm4::Button4Click(TObject *Sender)

{ Notes Notel, Note3;

// Конструктор TFileStream открывает файл для чтения/записи

TFileStream* fs = new TFileStream("Notebook.dat ",

fmOpenReadWrite);

fs->Position = 2*sizeof(Notes);

fs->Read(&Note3, sizeof(Notes)); // найти и считать Note3

fs->Position = 0;

fs->Read(&Notel, sizeof(Notes)); // найти и считать Notel

fs->Position = 0;

fs->Write(&Note3, sizeof(Notes));

// Note3 переносится на место Notel

fs->Position = 2*sizeof(Notes);

fs->Write(&Notel, sizeof(Notes));

// Note1 переносится на место Note3

char str[80]; // статический буфер строки

Memo4->Clear(); // очистить объект Memo4

// Считывать и отображать все записи в объекте Мето4

fs->Position = 0; // вернуться к началу файла

for (unsigned i=0; i<fs->Size/sizeof(Notes); i++)

{ fs->Read(&Notel, sizeof(Notes));

sprintf(str, "%s\tTeл: %s\tBo3pacT: %d", Notel.Name, Note1.Phone,

Note1.Age);

Memo4->Lines->Add(str);

}

delete fs; // вызов деструктора

}

 

Свойство Size поточного объекта fs позволяет вычислить число записей в файле Notebook. dat.

Пример. Создание простейшего текстового редактора с возможностью открытия и сохранения текстовых файлов.

Используются компоненты: TMainMemu. TOpenDialog, TSaveDialog. На рис. 16 и 17 показана форма в процессе проектирования приложения.

 
 

 

Рис. 16. Создание меню

 
 

Рис. 17. Форма в процессе проектирования

 

void __fastcall TForm1::Exit1Click(TObject *Sender)

{ exit(0); }

void __fastcall TForm1::Open1Click(TObject *Sender)

{ OpenDialog1->Options.Clear();

OpenDialog1->Options << ofFileMustExist;

OpenDialog1->Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";

OpenDialog1->FilterIndex = 2;

if (OpenDialog1->Execute())

Memo1->Lines->LoadFromFile(OpenDialog1->FileName);

}

void __fastcall TForm1::Save1Click(TObject *Sender)

{ SaveDialog1->Options.Clear();

SaveDialog1->Options << ofFileMustExist;

SaveDialog1->Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";

SaveDialog1->FilterIndex = 2;

if (SaveDialog1->Execute())

Memo1->Lines->SaveToFile(SaveDialog1->FileName);

}

 

Вопросы

 

1. Какие типы строк можно использовать в C++Builder?

2. Какие функции используются для преобразования чисел в строки типа AnsiString и обратно?

3. Что означает следующий код:

 

AnsiString a = "Hello World";

char *b = a.c_str();

 

4. Какая из строк преобразования является правильной?

 

AnsiString a = "Hello World";

int i = a.ToInt();

 

или

 

int ni = StrToInt(a);

 

5. Что означает следующий код?

 

AnsiString a = "12.5";

float d;

d=a.ToDouble();

 

6. Что означает следующий код?

 

char Arr[240]= "Hello World";

AnsiString Str;

Str=(AnsiString)Arr;

 

7. Какие средства можно использовать в C++Builder для работы с файлами?

8. Охарактеризуйте возможности и основные методы класса TFileStream.

9. Чем отличаются текстовый и двоичный режимы работы с файлами?

10. Каково назначение компонента MaskEdit? Вместо какого компонента он используется?

11. Как работают методы Add и Insert в многострочных текстовых компонентах?

12. С помощью каких методов можно выполнить сохранение строк списка в текстовом файле на диске и последующее чтение списка строк из файла?

13. Назовите отличительные особенности компонента RichEdit.

14. Как извлекать строки из компонента Memo и организовать поток ввода из строк для этих строк?

15. Как выполнить фильтрацию файлов при использовании компонентов OpenDialog и SaveDialog?

16. Чем комбинированный список отличается от простого списка?

17. Что означает следующий код?

 

#include <clipbrd.hpp>

void __fastcall TForm1::Button1Click(TObject *Sender)

{

AnsiString s = "Hello, World!";

Clipboard()->AsText = s;

if (Clipboard()->HasFormat(CF_TEXT))

Edit1->Text = Clipboard()->AsText;

else

application->MessageBox("The clipboard does not contain text.", NULL, MB_OK);

}

 

18. Что означает следующий код?

 

void __fastcall TForm1::Button1Click(TObject *Sender)

{

for(int i = 0; i < ListBox1->Items->Count; i++)

if(ListBox1->Selected[i])

ShowMessage(ListBox1->Items->Strings[i]);

}




Поделиться с друзьями:


Дата добавления: 2014-12-27; Просмотров: 2142; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.17 сек.