Главная страница
Навигация по странице:

  • Класс ifstream: чтение файлов.

  • Класс ofstream: запись файлов.

  • Класс ввода и вывода fstream: произвольный доступ к файлу.

  • TFileStream: поточный класс VCL.

  • 4. ПОДДЕРЖКА ГРАФИКИ И ГРАФИЧЕСКИЕ КОМПОНЕНТЫ

  • • Рисунок (

  • БГУ Пособие - Программирование в C++ Builder. Учебное пособие по курсу методы программирования для студентов специальностей


    Скачать 1.24 Mb.
    НазваниеУчебное пособие по курсу методы программирования для студентов специальностей
    АнкорБГУ Пособие - Программирование в C++ Builder.pdf
    Дата26.05.2018
    Размер1.24 Mb.
    Формат файлаpdf
    Имя файлаБГУ Пособие - Программирование в C++ Builder.pdf
    ТипУчебное пособие
    #19699
    страница6 из 12
    1   2   3   4   5   6   7   8   9   ...   12
    Операторы включения и извлечения. Оператор поточного включе- ния (<<) записывает данные в поток. Например: ofstream file("temp.txt"); char buff[] = "Текстовый массив "; int v = 100; file << buff << endl << v << endl; file.close();
    В результате образуются две строки в текстовом файле temp. txt:
    Текстовый массив
    100
    Оператор поточного извлечения (>>) производит обратные действия.
    Из-за ограниченности оператора извлечения для ввода могут быть ис- пользованы другие методы, например getline().
    Класс ifstream: чтение файлов. Класс ifstream предназначен для ввода из файлового потока. В табл. 3 перечислены основные методы класса.

    58
    Таблица 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 struct Notes // структура данных записной книжки
    { char Name[60]; // Ф.И.О. char Phone[16]; // телефон int Age; }; // возраст

    59
    // Обработчик события, возникающего при нажатии кнопки 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 его предыдущее содержимое будет стерто. Можно

    60
    открыть файл по одновременному чтению/записи, указав флаги 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);

    61
    Таблица 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

    62
    fs->Position = 0; // вернуться к началу файла for (unsigned i=0; iSize/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())

    63
    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 в многострочных текстовых компонентах?

    64 12. С помощью каких методов можно выполнить сохранение строк списка в текстовом файле на диске и последующее чтение списка строк из файла?
    13. Назовите отличительные особенности компонента RichEdit.
    14. Как извлекать строки из компонента Memo и организовать поток ввода из строк для этих строк?
    15. Как выполнить фильтрацию файлов при использовании компонен- тов OpenDialog и SaveDialog?
    16. Чем комбинированный список отличается от простого списка?
    17. Что означает следующий код?
    #include 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]);
    }
    Упражнения
    1. В заданном тексте выполнить замену заданного слова (если слово встречается несколько раз, то замену выполнить каждый раз) другим словом, также заданным.
    2. Удалить в тексте строки, содержащие заданное слово.
    3. Текст представляет собой сведения об успеваемости студентов.
    Строка содержит фамилию студента и результаты сдачи экзаменов. Упо- рядочить строки в соответствии с убыванием среднего балла.
    5. Файл содержит последовательность чисел. Переставить числа в об- ратном порядке.
    6. Файл содержит последовательность чисел. Упорядочить последо- вательность чисел в файле, считывая в память не более двух чисел.

    65
    4. ПОДДЕРЖКА ГРАФИКИ И ГРАФИЧЕСКИЕ
    КОМПОНЕНТЫ
    Система Windows предоставляет средства рисования GDI (Graphics
    Device Interface) для построения графических изображений на графиче- ском контексте независимо от типа устройства вывода. При прямом вы- зове функций GDI им необходимо передавать дескриптор контекста
    устройства (HDC – device context handle), который задает инструменты рисования. Графический контекст представляет модель графического устройства. После завершения работы c изображениями, необходимо восстановить контекст устройства в исходное состояние и освободить его. C++Builder берет на себя работу GDI, связанную с поиском дескрип- торов изображений и ресурсов памяти. Разрешается прямое обращение приложений к функциям Windows GDI. Рассмотрим пример: void __fastcall TForm1::Button1Click(TObject *Sender)
    { HDC hdc =Canvas->Handle;
    LineTo(hdc,100,100);
    MessageBox(Form1->Handle,"Вызов Windows API","",MB_OK);
    }
    C++Builder предоставляет простой интерфейс посредством свойства
    Canvas графических компонентов. Это свойство инициализирует и осво- бодждает контекст устройства. Свойство Canvas представляет собой класс, инкапсулирующий свойства и методы для работы с графикой.
    В среде C++Builder три способа для работы с графикой:
    • Канва предоставляет битовую карту поверхности для рисования на форме, графическом компоненте, или на другом битовом образе. Кроме формы, для рисования используются объекты классов TImage и TPaint-
    Box. Canvas является свойством этих классов. Рассмотрим пример рисо- вания на форме: void __fastcall TForm1::FormPaint(TObject *Sender) {
    Canvas->Pen->Color = clBlue; // выбрать цвет контура
    Canvas->Brush->Color = clYellow; // выбрать цвет заливки
    Canvas->Ellipse(10, 20, 50, 50); // нарисовать эллипс
    }
    Метод FormPaint здесь вызывается событием OnPaint формы при ее рисовании. Отметим, что при рисовании непосредственно на форме воз- никает ряд проблем, связанных с ее перерисовкой. В следующем приме- ре рассматриваются различные способы задания цвета формы и цвета линий для рисования на компоненте TImage. void __fastcall TForm1::Button1Click(TObject *Sender)
    {

    66
    if (ColorDialog1->Execute())
    { Form1->Color = ColorDialog1->Color;
    }
    } void __fastcall TForm1::Button2Click(TObject *Sender)
    { Image1->Canvas->Pen->Width=2; randomize();
    Image1->Canvas->Pen->Color =(Graphics::TColor)random(256) ;
    Image1->Canvas->LineTo(100,200);
    }
    При нажатии на первую кнопку выбирается цвет формы, при нажатии на вторую кнопку рисуются линии случайно выбранным цветом.
    • Графика (TGraphic) представляет абстрактный базовый класс для работы с графикой. C++Builder определяет графические классы TBitmap,
    TClipBoard, TImage, TIcon и TMetafile, производные от базового класса
    TGraphic. Объекты этих классов используют методы рисования на канве и имеют собственные методы. Широко используются методы класса
    TGraphic LoadFromClipboardFormat(), LoadFromFile(), LoadFromStream(),
    SaveToClipboardFormat(), SaveToFile(), SaveToStream().
    • Рисунок (TPicture) представляет собой контейнер для графических объектов и может содержать любые графические объекты. Свойствами этого класса являются: Bitmap, Graphic, Icon, Metafile, PictureAdapter.
    Контейнерный класс TPicture может содержать битовый образ, пикто- грамму, метафайл или некоторый другой графический тип, а приложение будет обращаться ко всем объектам контейнера посредством объекта класса TPicture. Если необходимо указать доступ к конкретному графи- ческому объекту, задайте его в свойстве Graphic данного рисунка. Мето- ды этого класса: LoadFromClipboardFormat(), LoadFromFile(), LoadFrom-
    Stream(), SaveToClipboardFormat(), SaveToFile(), SaveToStream().
    Использование канвы. Класс Canvas инкапсулирует графические функции Windows на различных уровнях, начиная с функций высокого уровня для рисования линий, фигур и текста. Далее идут свойства и ме- тоды среднего уровня для манипуляций с канвой. В табл. 7 приводятся характеристики основных методов и свойств канвы.

    67
    Таблица 7
    Ур
    овень
    Действие
    Методы
    Свойства
    Определяет текущую позицию пера MoveTo
    PenPos
    Рисует прямую до заданной точки LineTo
    PenPos
    Рисует прямоугольник заданного размера Rectangle
    Рисует эллипс заданного размера Ellipse
    Выводит текстовую строку TextOut
    Задает высоту текстовой строки TextHeight
    Задает ширину текстовой строки TextWidth
    Вывод текста внутри прямоугольника TextRect
    Заливка указанного прямоугольника цветом и текстурой текущей кисти
    FillRect
    Высокий
    Заливка области канвы (произвольной формы) заданным цветом
    FloodFill
    Используется для установки цвета, стиля, ши- рины и режима пера
    Pen
    Используется для установки цвета и текстуры при заливке графических фигур и фона канвы.
    Brush
    Используется для установки шрифта заданного цвета, размера и стиля
    Font
    Используется для чтение и записи цвета задан- ного пикселя канвы
    Pixels
    Копирует прямоугольную область канвы в ре- жиме CopyMode
    CopyRect CopyMode
    Копирует прямоугольную область канвы с за- меной цвета
    BrushCopy
    Рисует битовый образ, пиктограмму, метафайл в заданном месте канвы
    Draw
    Рисует битовый образ, пиктограмму или мета- файл так, чтобы целиком заполнить заданный прямоугольник
    StretchDraw
    Средний
    Используется как параметр при вызове функ- ций Windows GDI
    Handle
    Объекты класса Canvas являются свойствами формы и всех графиче- ских объектов, например TForm, TImage, TBitmap. Рассмотрим пример: void __fastcall TForm1::FormActivate(TObject *Sender){
    WindowState = wsMaximized;
    Timer1->Interval = 50; randomize();
    }
    //----------------------------------------------------------- void __fastcall TForm1::Timer1Timer(TObject *Sender)
    { int x, y;

    68
    x = random(Screen->Width - 10); y = random(Screen->Height - 10);
    Canvas->Pen->Color = clYellow;
    Canvas->Brush->Color = (Graphics::TColor) random(256); switch (random(5))
    { case 0: Canvas->Pen->Style = psSolid; break; // стиль линии case 1: Canvas->Pen->Style = psDash; break; case 2: Canvas->Pen->Style = psDot; break; case 3: Canvas->Pen->Style = psDashDot; break; case 4: Canvas->Pen->Style = psDashDotDot; break;
    }
    Canvas->Rectangle(x, y, x + random(400), y + random(400)); }
    Здесь в методе FormActivate() формы задается интервал времени, че- рез который происходит событие OnTimer компонента TTimer, которое осуществляет перерисовку прямоугольника на форме.
    В качестве примера рассмотрим рисование графика функции y=f(x).
    Пусть x принимает значения из промежутка [x
    1
    , x
    2
    ], а y изменяется в промежутке [y
    1
    , y
    2
    ]. График функции будем рисовать в прямоугольнике на экране с координатами верхнего левого угла (Х
    1
    , Y
    1
    ) и нижнего пра- вого угла – (X
    2
    , Y
    2
    ). Таким образом, необходимо выполнить масштаби- рование: преобразование координат точек функции (x,f(x)) в соответст- вующие координаты точек (пикселей) заданного прямоугольника на эк- ране. В процессе преобразования будем учитывать, что ось Oy на экране имеет направление сверху вниз. Поэтому изменим направления оси Oy в заданном прямоугольнике на экране на привычное для нас направление снизу вверх. Для преобразования координат точки функции (x, y) в коор- динаты соответствующего пикселя (X, Y) на экране можно использовать следующие формулы:
    X=X
    1
    +[(X
    2
    -X
    1
    )/(x
    2
    -x
    1
    )](x-x
    1
    );
    Y=Y
    2
    -[(Y
    2
    -Y
    1
    )/(y
    2
    -y
    1
    )](y-y
    1
    ).
    Ниже приводится фрагмент программы для рисования графика функ- ции y=cos x, где x изменяется в промежутке [0, 2π]. График будем рисо- вать на всей поверхности компонента Image1, т. е. x

    [0,Image1->Width], а y

    [0,Image1->Height]. Получим следующий код:
    #define pi 3.14159 double X,Y; // координаты точек функции int PX,PY; // координаты пикселей на экране
    Y=cos(0);
    PY=Image1->Height-Image1->Height/2*(Y+1);
    Image1->Canvas->MoveTo(0,PY); // перемещаем перо в начальную
    // точку рисования графика for(X=0.05;X<=2*pi;X+=0.05){

    69
    Y=cos(X);
    PX=Image1->Width/(2*pi)*X;
    PY=Image1->Height-Image1->Height/2*(Y+1);
    Image1->Canvas->LineTo(PX,PY);
    }
    1   2   3   4   5   6   7   8   9   ...   12


    написать администратору сайта