КАТЕГОРИИ: Архитектура-(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
Например:
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
Класс ofstream: запись файлов. Класс ofstream предназначен для вывода данных в файлы. В табл. 4 перечислены основные методы класса:
Таблица 4
Бинарные файлы. Бинарные файлы представляют собой последовательность байтов, которая вводится или выводится без каких-либо преобразований. Для записи бинарных файлов или чтения из них используются методы 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
Режим открытия файла. По сравнению с флагами аргумента open_mode установки режима Mode в классе TFileStream заметно отличаются, что видно из табл. 6. Режим передается конструктору объекта файлового потока в качестве второго параметра следом за именем файла. Например, так следует открывать файл для чтения: TFileStream* fs = new TFileStream("Notebook.dat",fmOpenRead); а так – для модификации:
TFileStream* fs = new TFileStream("Notebook.dat", fmOpenReadWrite);
Таблица 6
Ниже приводится пример использования класса 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; Просмотров: 2191; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |