Практикум по информатике
Скачать 7.84 Mb.
|
§7. Внешние файлы В данном параграфе рассматриваются следующие вопро- сы: процедуры работы с файлами, создание главного меню, использование стандартных диалогов Теория Процедуры работы с файлами Файл ― это именованная структура данных, представляющая собой последовательность элементов данного типа, причем коли- чество элементов последовательности практически не ограниче- но. Файл должен быть объявлен в разделе описания переменных. В общем виде объявление файла: Имя: file of ТипЭлементов; Файл, компонентами которого являются данные символьного типа, называется символьным или текстовым. Описание тексто- вого файла в общем виде: Имя: TextFile; где Имя ― имя файловой переменной, TextFile ― обозначе- ние типа, показывающее, что Имя ― это файловая переменная, представляющая текстовый файл. Примеры описания файлов: Var Job: file of char; // файл символьного типа Test: file of real; // файл вещественного типа 402 Fz: file of integer; // файл целого типа My_File: TextFile; // файл текстового типа Для того чтобы программа могла записывать результаты сво- ей работы в файл или считывать исходные данные из файла, не- обходимо связать файловую переменную с конкретным файлом (задать имя файла). Процедура AssignFile устанавливает физическую связь меж- ду файловой переменной f и строковой переменной ИмяФайла: AssignFile (var f, ИмяФайла: string); Примеры вызова процедуры AssignFile: AssignFile(f, ‘d:\Мои документы\result.txt’); AssignFile(Fin, ‘test011.txt’); FileName:=’otchet1.txt’; AssignFile(Fot, FileName); . Прежде чем записывать информацию в файл необходимо его открыть. Возможны следующие режимы открытия файла для за- писи в него данных: ― перезапись (запись нового файла поверх существующего или создание нового файла); ― добавление в существующий файл. Открыть для чтения файл можно с помощью процедуры Reset(f) , где f — имя файловой переменной. Процедура Reset ищет файл, открывает его и устанавливает указатель на начало файла. Если файл не найден, выдается сообщение об ошибке вво- да/вывода и программа завершает свою работу. Открыть файл для записи позволяет процедура Rewrite(f), где f — имя файловой переменной. Процедура Rewrite(f) ищет файл, открывает его, стирает в нем старую информацию и устанавлива- ет указатель на начало файла. Если файл не найден, он создается заново. Для открытия файла с целью добавления в него информации служит процедура AppendFile(f), где f — имя файловой пере- менной. Процедура AppendFile открывает файл и устанавливает указатель на конец файла. Если файл не найден, выдается сооб- щение об ошибке ввода/вывода и программа завершает свою ра- боту. Для ввода (чтения) информации из файла предназначены про- цедуры: 403 Read(f,[список ввода]); Readln(f,[список ввода]); где f — имя файловой переменной, список ввода — переменные, элементы массивов. Процедура Readln имеет следующие особенности: — после ввода данных указатель переносится на начало сле- дующей строки; — процедура используется только для текстовых файлов. Для вывода (записи) данных в файл существует процедуры: Write(f,[список вывода]); Writeln(f,[список вывода]); где f — имя файловой переменной, список вывода — переменные, элементы массивов, константы. Отличительными особенностями процедуры Writeln также яв- ляется применимость ее только в случае текстовых файлов и пе- ренос указателя на новую строчку. После окончания всех действий с файлом он должен быть обя- зательно закрыт с помощью процедуры CloseFile(f), где f — имя файловой переменной. Часто в программах при работе с файлами оказываются полез- ными функции EOF(f) и EOLN(f). EOF(f) — логическая функция, принимает значение TRUE (ис- тина), если обнаружен конец файла. EOLN(f) — логическая функция, принимает значение TRUE (истина), если обнаружен конец строки. Главное меню Компонент находится на вкладке Standard. TMainMenu позволяет поместить главное меню в программу. При помещении MainMenu на форму это выглядит, как про- сто иконка. Иконки данного типа называют «невидимыми ком- понентами», поскольку они невидимы во время выполнения про- граммы. Создание меню включает три шага: (1) помещение MainMenu на форму, (2) вызов Дизайнера Меню через свойство Items в Инспекторе Объектов, (3) определение пунктов меню в Дизайнере Меню. Чтобы создать процедуру, обрабатывающую действия, связан- ные с выбранным пунктом меню, необходимо произвести два щелчка по пункту на форме, и в редакторе кода будет подготов- 404 лена заготовка процедуры, подобная этой: procedure TForm1.N1Click(Sender: TObject); begin end; Использование стандартных диалогов На странице Dialogs (диалоги) представлены компоненты для вызова стандартных диалогов Windows. Внешний вид диалогов зависит от используемой версии Windows. Объекты, представ- ленные на данной странице невидимы во время выполнения и вызов диалогов происходит программно. TOpenDialogs находится на странице Dialogs . Позволяет выбрать файл из списка файлера (подобно тому, как открывается файл в Word с помощью команды Открыть. ). Од- ним из главных свойств компонента OpenDialogs (кроме самого имени компонента) является свойство NameFile, которому при- сваивается имя выбранного из панели диалога файла. В програм- ме для проверки, выбран файл или еще нет, используется функ- ция Execute. Функция логическая. Принимает значение Истина, если файл выбран и Ложь в противном случае. Фрагмент про- граммы для выбора файла из панели диалога может выглядеть так: if not od1.Execute then Exit; NameFile := od1.FileName; В этом примере, стандартное имя компонента OpenDialogs1 в Инспекторе Объектов было заменено на od1, для краткости. Про- граммисты очень часто заменяют стандартные имена компонен- тов на свои (свойство Name). Компонент TSaveDialog (находится также на странице Dialogs) используется для выбора имени файла, в котором будет сохранена информация из диалоговой панели. Обычно такая диа- логовая панель вызывается командами File →Save (Сохранить) или File →Save As (Сохранить как). Если пользователь указал имя файла и нажал кнопку Ok, то оно сохраняется как значение свойства FileName. Использование данного компонента анало- гично использованию компонента OpenDialogs. Например, if not SaveDialog1.Execute then Exit; 405 NameFile:=SaveDialog1.FileName; Организация вывода на принтер Для вывода на принтер нужно воспользоваться рядом проце- дур, определенных в модуле Printers. То есть в разделе Uses мо- дуля программы нужно обязательно подключить модуль Printers: uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Grids, DateUtils, Printers; Далее в программном модуле нужно ассоциировать значение тес- товой переменной с принтером с помощью процедуры AssignPrn и открыть файл для записи. Например, Var TextToPrint: System.Text; ………………………. AssignPrn(TextToPrint); // ассоциировать с принтером Rewrite(TextToPrint); // открыть файл После этого вызов стандартных процедур Write и Writeln при- ведет к выводу текста на устройство печати. Например, вывод содержимого компонента Memo на принтер можно осуществить с помощью следующих инструкций: For Line:=0 to Memo1.Lines.Count-1 do Writeln(TextToPrint, Memo1.Lines[Line]); После того как вывод информации завершен, необходимо вызвать стандартную процедуру Close: System.Close(TextToPrint); Структура данных — запись На практике мы часто сталкиваемся с задачами, где исполь- зуются данные, состоящие из других данных. Например, инфор- мация о студентах может состоять не только из фамилии и ини- циалов, паспортных данных, номера группы, но и оценок, полу- ченных на экзаменах. Для работы с такой информацией в Delphi используется структура данных — запись (record). Запись — это структура данных, состоящая из полей. Поля — это именованные компоненты разного типа. Переменную-запись можно в общем виде описать в разделе описания переменных как: Имя-переменной: record Поле_1: Тип_1; 406 Поле_2: Тип_2; Поле_К: Тип_K; End; Например, Student: record f_name: string[20]; l_name: string[20]; day: integer; month: integer; year: integer; address: string[50]; end; Если в программе нужно использовать много переменных- записей одной структуры, то целесообразно в разделе Type объя- вить тип «запись»: Имя = record Поле_1: Тип_1; Поле_2 : Тип_2; Поле_K : Тип_К; End; Например, Type TDate = record Day: integer; Month: integer; Year: integer; End; В разделе описания переменных переменные-записи могут быть объявлены так: Var Birthday: TDate; Dat1, Dat2: TDate; Для работы с записями в языке Delphi предусмотрен оператор With. Он позволяет много раз не писать имя переменной-записи, а работать просто с полями. В общем виде оператор With выгля- дит так: With Имя do Begin 407 {операторы программы} End; где: Имя — имя переменной-записи; With — зарезервированное слово, означающее, что далее, до слова end, при обращении к полям записи «Имя», имя записи можно не указывать. Например, если в программе объявлена запись Student (см. выше) и данные о студенте вводятся в поля Edit1, Edit2 и Edit3 диалогового окна, то вместо операторов Student.f_name:=Edit1.Text; Student.l_name:=Edit2.Text; Student.address:=Edit3.Text; можно записать with student do begin f_name:=Edit1.Text; l_name:=Edit2.Text; address:=Edit3.Text; end; Практика Задача Дана следующая информация об индивидуальных домах в не- котором регионе: номер кадастрового дела, Фамилия И.О. собст- венника, адрес дома, общая площадь (кв.м), дата последней упла- ты налога на недвижимость. Составить программу, которая: 1) находит собственников, не уплативших налог за предыдущий год; 2) выводит информацию о домах площадью более 100 кв.м. Предусмотреть возможности ввода исходных данных с клавиату- ры и файла на диске. Вывод предусмотреть в двух вариантах: файл либо принтер. Для решения задачи предлагается создать три окна 408 Компоненты Имя Компонента Свойства компонента Значение Назначение Form1 Caption Учет индивиду- альных домов Заголовок глав- ной формы Label1 Caption Для перехода в Справочная ин- 409 Visible новую ячейку таблицы исполь- зовать клавишу «ENTER». При вводе данных в последнюю ячей- ку строки нажать «ENTER» и кла- вишу «СТРЕЛКА ВНИЗ» для пере- хода в другую строку False формация для пользователя программы Строка подсказки невидима Form1.StringGrid1 ColCount FixedCol FixedRow Options: goFixedVertLine goFixedHorzLine goVertLine goHorzLine goEditing goTabs 6 1 1 True True True True True True Количество столбцов по умолчанию Количество фик- сированных сле- ва столбцов Количество фик- сированных сверху строк Опции: Разметка зафик- сированных вер- тикальных линий Разметка зафик- сированных гори- зонтальных ли- ний Разметка верти- кальных линий внутри таблицы Разметка гори- зонтальных ли- ний внутри таб- лицы Признак допус- тимости редакти- рования содер- жимого ячеек таблицы.True ― редактирование разрешено. False ― запрещено Разрешает ис- пользование кла- 410 goAlwaysShowEdi- tor ScrollBars True ssBoth виши Tab для пе- ремещения в другую ячейку Признак нахож- дения компонен- та в режиме ре- дактирования Выводятся обе полосы прокрутки Form1.MainMenu N1 N2 N3 N4 N5 N6 N7 N8 N10 N1001 N11 N1003 N9 N1002 Ввод данных Клавиатура Файл Расчет Вывод результа- тов Файл Принтер Вывод Найти собствен- ников, не упла- тивших налог за предыдущие го- ды Вывести инфор- мацию о домах, площадь которых превышает 100 кв. м Список должни- ков Площадь больше 100 кв.м Список должни- ков Площадь больше 100 кв.м Названия пунктов меню OpenDialogs1 Name Od1 Имя компонента SaveDialog1 Name SaveDialog1 Имя компонента Form2 Caption Дома с площа- дью более 100 кв.м Заголовок формы Form2.StringGrid1 Свойства аналогичны свойствам Form1.StringGrid1 (см. выше) Label1 Caption Поле вывода ре- зультата Form2.Button1 Caption Закрыть Кнопка для за- крытия окна “ Дома с площа- дью более 100 411 кв.м ” Form3 Caption Должники Заголовок формы Form3.StringGrid1 Свойства аналогичны свойствам Form1.StringGrid1 (см. выше) Label1 Caption Список собствен- ников, не упла- тивших налог на недвижимость в предыдущие го- ды, включая прошлый Справочная ин- формация для пользователя программы Label2 Caption Поле для вывода результата Form3.Button1 Caption Закрыть Кнопка для за- крытия окна “Должники” Для наглядности приведем структуру создаваемого главного меню: 412 Переменные и массивы Обозначение в программе Содержание Тип L количество домов с площадью бо- лее 100 кв.м целый M количество должников целый Delo_N массив номеров кадастровых дел строковый длиной 4 Famil массив собственников индивидуальных домов строковый длиной 20 Adres массив адресов индивидуальных домов строковый длиной 30 S массив площадей индивидуальных домов вещественный D массив дат последней уплаты на- лога на недвижимость Объект типа дата n Счетчик объектов в файле или таб- лице целый F Файловая переменная текстовый NameFile Имя файла строковый длиной 20 DA День уплаты налога Целый беззнаковый M Месяц уплаты налога Целый беззнаковый Y Год уплаты налога Целый беззнаковый i Счетчик строк, управляющая пере- менная в цикле Целый TextToPrint Файловая переменная для вывода на принтер Системный текс Текст модуля unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Menus, Grids, DateUtils, StdCtrls,Unit2,Unit3, Printers; // подключаются модули, связанные с 2-ой и 3-ей формами, // библиотека функций и процедур работы с принтером type TForm1 = class(TForm) MainMenu1: TMainMenu; 413 N1: TMenuItem; N2: TMenuItem; N3: TMenuItem; N4: TMenuItem; N5: TMenuItem; N6: TMenuItem; N7: TMenuItem; N8: TMenuItem; N10: TMenuItem; N1001: TMenuItem; StringGrid1: TStringGrid; od1: TOpenDialog; SaveDialog1: TSaveDialog; N9: TMenuItem; N1002: TMenuItem; N11: TMenuItem; N1003: TMenuItem; Label1: TLabel; procedure N8Click(Sender: TObject); procedure N2Click(Sender: TObject); procedure N3Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure StringGrid1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure N10Click(Sender: TObject); procedure N1001Click(Sender: TObject); procedure N11Click(Sender: TObject); procedure N1003Click(Sender: TObject); procedure N9Click(Sender: TObject); procedure N1002Click(Sender: TObject); private { Private declarations } public { Public declarations } L:Integer;// количество домов с площадью более 100 кв.м M:Integer;// количество должников Delo_N:Array[1..1000] of String[4];// массив номеров кадастровых дел Famil :Array[1..1000] of String[20]; ];{ массив собственников индивидуальных домов} Adres :Array[1..1000] of String[30];{ массив адресов индивидуальных домов} S:Array[1..1000] of Real;// массив площадей индивидуальных домов 414 D:Array[1..1000] of TDate;{ массив дат последней уплаты налога на не- движимость} end; var Form1: TForm1; implementation {$R *.dfm} // процедура закрывает главное окно — ВЫХОД procedure TForm1.N8Click(Sender: TObject); begin Form1.Close; end; //активизация ввода с клавиатуры procedure TForm1.N2Click(Sender: TObject); begin N2.Checked := True;// ставится галочка напротив пункта Клавиатура Label1.Visible:=True;// поле с подсказкой становится видимым StringGrid1.SetFocus;// фокус переносится в таблицу StringGrid StringGrid1.Options := StringGrid1.Options + [goEditing]; // в StringGrid добавляется свойство, // разрешающее редактирование ячеек end; // процедура ввода исходных данных из файла на диске procedure TForm1.N3Click(Sender: TObject); Var n:integer;// счетчик объектов в файле F:TextFile;// файловая переменная текстового типа NameFile:String[20];// имя файла DA,M,Y:Word;{ день, месяц, год последней уплаты налога на недвижимость, в файле эти числа вводятся через пробел } begin N3.Checked:=True;// ставится галочка напротив пункта «Файл» if not od1.Execute then Exit;// если в открывшемся списке // не выбрано имя файла, то прекращается выполнение процедуры NameFile := od1.FileName;{ переменной имя_файла присваивается имя, выбранное из списка} AssignFile(F,NameFile);// процедура связывает файловую переменную // и конкретный файл Reset(F);// процедура открывает файл для чтения // счетчик объектов инициализируется единицей n:=1; {пока не достигнут конец файла, из файла читаются построчно: 415 номер кадастрового дела, фамилия собственника, адрес дома, площадь, дата в виде трех чисел на одной строке. Данные одновременно выводятся в таблицу в главном диалоговом окне} While Not(EoF(F)) Do // пока не достигнут конец файла, делать Begin Readln(F,Delo_N[n]); // из файла читается номер кадастрового дела StringGrid1.Cells[1,n]:=Delo_N[n]; { номер кадастрового дела выво- дится в таблицу на 1 форме} Readln(F,Famil[n]); // из файла читается фамилия собственника StringGrid1.Cells[2,n]:=Famil[n];// фамилия выводится в форму на экран Readln(F,Adres[n]); // читается адрес StringGrid1.Cells[3,n]:=Adres[n];// адрес выводится в форму на экран Readln(F,S[n]);// читается площадь StringGrid1.Cells[4,n]:=FloatToStr(S[n]); {площадь выводится в таб- лицу на экране} Readln(F,DA,M,Y);D[n]:=EncodeDate(Y,M,DA);{преобразование трех чисел в объект типа дата – массив дат} StringGrid1.Cells[5,n]:=DateToStr(D[n]);// дата выводится в таблицу n:=n+1;// счетчик объектов увеличивается на 1 {если количество строк в таблице на форме меньше n, то ему при- сваивается значение счетчика объектов } if StringGrid1.RowCount < n then StringGrid1.RowCount := n; End; {после того как достигнут конец файла, файл закрывается} CloseFile(F); end; {процедура выполняется при появлении диалогового окна (формы) на экране, связана с событием — создание формы} procedure TForm1.FormCreate(Sender: TObject); Var n:Integer; // счетчик объектов в таблице begin // заполнение шапки таблицы нулевой строки StringGrid1.Cells[0,0]:='Номер п/п'; StringGrid1.Cells[1,0]:='Номер кадастрового дела'; StringGrid1.Cells[2,0]:='Фамилия И.О. собственника'; StringGrid1.Cells[3,0]:='Адрес'; StringGrid1.Cells[4,0]:='Общая площадь (кв.м)'; StringGrid1.Cells[5,0]:='Дата последней уплаты налога на недвижимость'; // цикл нумерации строк таблицы For n:=1 to 1000 Do StringGrid1.Cells[0,n]:=IntToStr(n); 416 end; {Процедура, связанная с событием, нажатие клавиши в ячейке таблицы. Проверяется правильность нажатия клавиш при вводе — «ENTER» (для перехода в ячейку справа) и последовательно клавиш «ENTER» и «СТРЕЛКА ВНИЗ» (для перехода на следующую строку). Здесь же проис- ходит считывание данных из ячеек таблицы в массивы. Такая технология ввода позволила организовать ввод для заранее неизвестного количества данных.} procedure TForm1.StringGrid1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); Begin // если нажата клавиша «СТРЕЛКА ВНИЗ» if Key = VK_DOWN then begin // то если текущий номер строки таблицы меньше предыдущего // значения количества строк в таблице, тогда ВЫХОД if StringGrid1.Row < pred(StringGrid1.RowCount) then Exit; // количество строк в таблице увеличивается на единицу StringGrid1.RowCount := StringGrid1.RowCount + 1; StringGrid1.Col := 1; // переход в начало строки // если в первую ячейку текущей строки ничего не введено, // то добавленная строка убирается if (Length(StringGrid1.Cells[1,StringGrid1.Row]) = 0) then begin StringGrid1.RowCount:=pred(StringGrid1.RowCount);Exit; end; end; // если нажата клавиша «ENTER», то if (Key = VK_RETURN) then begin case StringGrid1.Col of // если номер столбца таблицы равен 1 и если ячейка не пуста, 1 : if (Length(StringGrid1.Cells[1,StringGrid1.Row]) > 0) // тогда содержимое ячейки с индексом равным номеру текущей строки // помещается в массив «Номер кадастрового дела» then Delo_N[StringGrid1.Row] := StringGrid1.Cells[1,StringGrid1.Row] // иначе количеству строк в таблице // присваивается предыдущее значение и выход, т.е. программа будет // ждать заполнения первой колонки в этой строке else begin StringGrid1.RowCount:=pred(StringGrid1.RowCount);Exit; end; // если текущий номер колонки таблице равен 2, то // в массив собственников под номером равным номеру текущей строки // таблицы, помещается содержимое ячейки, стоящей на пересечении 417 // второго столбца и текущей строки 2 : Famil[StringGrid1.Row] := StringGrid1.Cells[2,StringGrid1.Row]; // аналогично предыдущему вводится адрес 3 : Adres[StringGrid1.Row] := StringGrid1.Cells[3,StringGrid1.Row]; // если четвертая колонка не пуста, то строка символов преобразуется // в вещественное число и помещается в массив площадей домов 4 : if Length(StringGrid1.Cells[4,StringGrid1.Row]) > 0 then S[StringGrid1.Row]:=StrToFloat(StringGrid1.Cells[4,StringGrid1.Row]) // иначе в массив вводится число 0.00 else S[StringGrid1.Row] := 0.00; // если пятая колонка не пуста, то строка символов преобразуется в дату // и помещается в массив дат 5 : if Length(StringGrid1.Cells[5,StringGrid1.Row]) > 0 then D[StringGrid1.Row] := StrToDate(StringGrid1.Cells[5,StringGrid1.Row]) // иначе в массив дат помещается 0 else D[StringGrid1.Row] := 0; end; // если текущий номер колонки меньше 5, то он увеличивается на 1 if StringGrid1.Col < 5 then StringGrid1.Col := StringGrid1.Col +1 end; end; { процедура, связанная с пунктом меню «Найти собственников, не уп- лативших налог за предыдущие годы»} procedure TForm1.N10Click(Sender: TObject); Var i,n:integer; begin // ставится галочка напротив пункта меню // «Найти собственников, не уплативших налог за предыдущие годы» N10.Checked:=True; // подписывается шапка таблицы Form3.StringGrid1.Cells[0,0]:='Номер по п/п'; Form3.StringGrid1.Cells[1,0]:='Фамилия И.О. собственника'; Form3.StringGrid1.Cells[2,0]:='Дата последней уплаты налога на недвижимость'; i:=0;// — номер строки в таблице { В цикле последняя дата уплаты налога собственником дома сравнивается с текущей датой, установленной на компьютере. Если разница превышает 1 год, собственник является должником. Фамилии должников выводятся в 418 таблицу в третьей форме. Если дата неизвестна, то выводится сообщение: «нет сведений»} For n := 1 to pred(StringGrid1.RowCount) Do // функция YearsBetween(D1,D2) находит разницу между двумя датами IF YearsBetween(Date,d[n]) >= 1 then Begin Inc(i); // i:=i+1; Form3.StringGrid1.Cells[0,i]:=IntToStr(i); Form3.StringGrid1.Cells[1,i]:=Famil[n]; if D[n]=0 then Form3.StringGrid1.Cells[2,i]:='нет сведений' else Form3.StringGrid1.Cells[2,i]:=DateToStr(D[n]); Form3.StringGrid1.RowCount:=Form3.StringGrid1.RowCount+1 end; // вывод количества должников M:=i; Form3.Label2.Caption:='Всего: '+ IntToStr(M)+' должников'; //показать форму 3 Form3.Show; end; {процедура, связанная с пунктом меню «Вывести информацию о до- мах, площадь которых превышает 100 кв.м»} procedure TForm1.N1001Click(Sender: TObject); Var n,i:Integer; Begin // поставить галочку напротив выбранного пункта меню N1001.Checked:=True; Form2.StringGrid1.Cells[0,0]:='Номер по п/п'; Form2.StringGrid1.Cells[1,0]:='Номер кадастрового дела'; Form2.StringGrid1.Cells[2,0]:='Фамилия И.О. собственника'; Form2.StringGrid1.Cells[3,0]:='Адрес'; Form2.StringGrid1.Cells[4,0]:='Общая площадь (кв.м)'; Form2.StringGrid1.Cells[5,0]:='Дата последней уплаты налога на недвижимость'; i:=0; { В цикле производится сравнение площадей всех домов со 100 кв.м. Если площадь дома превышает 100 кв.м, то вся информация о нем выводится в таблицу на форме 2} For n:=1 to pred(Form1.StringGrid1.RowCount) Do IF S[n]>100 Then Begin Inc(i); // i:=i+1; Form2.StringGrid1.Cells[0,i]:=IntToStr(i); Form2.StringGrid1.Cells[1,i]:=Delo_N[n]; Form2.StringGrid1.Cells[2,i]:=Famil[n]; Form2.StringGrid1.Cells[3,i]:=Adres[n]; 419 Form2.StringGrid1.Cells[4,i]:=FloatToStrF(S[n],ffFixed,10,2)+' кв.м'; if D[n]=0 then Form2.StringGrid1.Cells[5,i]:='нет сведений' else Form2.StringGrid1.Cells[5,i]:=DateToStr(D[n]); Form2.StringGrid1.RowCount:=Form2.StringGrid1.RowCount+1 end; L:=i; Form2.Label1.Caption:='Всего домов площадью более 100 кв.м:'+IntToStr(L); Form2.Show; end; {процедура, связанная с пунктом меню «Вывод в файл» — список должников} procedure TForm1.N11Click(Sender: TObject); Var f:TextFile; NameFile:String; i:Integer; begin N11.Checked:=True; {Если из панели диалога не выбрано или не задано имя файла сохранения, то выход. Т.е. панель диалога будет находится на экране, пока пользова- тель не задаст имя файла.} if not SaveDialog1.Execute then Exit; // переменной ИмяФайла присваивается имя файла, // заданное в панели диалога NameFile:=SaveDialog1.FileName; // устанавливается физическая связь между файловой переменной // и конкретным файлом на внешнем носителе AssignFile(f,NameFile); // открыть файл для записи Rewrite(f); // в следующем фрагменте программы информация о должниках // из формы 3 записывается в файл Writeln (f,'список должников:'); Writeln (f,'Номер п/п ','Фамилия И.О. собственника', ' Дата последней уплаты налога на недвижимость'); For i:=1 To M do Writeln (f,Form3.StringGrid1.Cells[0,i]:4,Form3.StringGrid1.Cells[1,i]:30,' ', Form3.StringGrid1.Cells[2,i]:30); // закрытие файла CloseFile(f); end; 420 {процедура, связанная с пунктом меню «Вывод в файл» — список до- мов с площадью более 100 кв.м} procedure TForm1.N1003Click(Sender: TObject); Var f:TextFile; NameFile:String; i:Integer; begin N1003.Checked:=True; // если не задано имя файла в панели диалога, // панель диалога остается на экране if not SaveDialog1.Execute then Exit; // переменной ИмяФайла присваивается имя файла, // заданное в панели диалога NameFile:=SaveDialog1.FileName; // устанавливается физическая связь между файловой переменной // и конкретным файлом на внешнем носителе AssignFile(f,NameFile); // открыть файл для записи Rewrite(f); // в следующем фрагменте программы информация о домах с площадью // более 100 кв.м из формы 2 записывается в файл Writeln (f,'Дома с площадью более 100 кв. м:'); Writeln (f,'Номер п/п ','Номер кадастрового дела ', 'Фамилия И.О. собственника ', ' Адрес ', 'Общая площадь (кв.м) ', 'Дата последней уплаты налога на недвижимость'); For i:=1 To L do Writeln (f,Form2.StringGrid1.Cells[0,i]:4,Form2.StringGrid1.Cells[1,i]:20,' ', Form2.StringGrid1.Cells[2,i]:30,' ',Form2.StringGrid1.Cells[3,i]:30, Form2.StringGrid1.Cells[4,i]:16,' ',Form2.StringGrid1.Cells[5,i]:20 ); CloseFile(f); end; {процедура, связанная с пунктом меню «Вывод на принтер» — список должников} procedure TForm1.N9Click(Sender: TObject); Var TextToPrint:System.Text; i:integer; begin N9.Checked:=True; // устанавливается физическая связь с печатающим устройством AssignPrn(TextToPrint); // открытие для вывода Rewrite(TextToPrint); 421 // в следующем фрагменте осуществляется вывод списка должников // из формы 3 на принтер Writeln (TextToPrint,'список должников:'); Writeln (TextToPrint,'Номер п/п ','Фамилия И.О.', ' Дата последней уплаты '); Writeln (TextToPrint,' ','собсвенника', ' налога на недвижимость '); For i:=1 To M do Writeln (TextToPrint,Form3.StringGrid1.Cells[0,i]:4, Form3.StringGrid1.Cells[1,i]:30,' ',Form3.StringGrid1.Cells[2,i]:30); System.Close(TextToPrint); end; {процедура, связанная с пунктом меню «Вывод на принтер» — список домов с площадью более 100 кв.м} procedure TForm1.N1002Click(Sender: TObject); Var TextToPrint:System.Text; i:integer; begin N1002.Checked:=True; // ассоциация с принтером AssignPrn(TextToPrint); // открытие для вывода Rewrite(TextToPrint); // в следующем фрагменте осуществляется вывод списка // домов с площадью более 100 кв.м из формы 2 на принтер Writeln (TextToPrint,'Дома с площадью более 100 кв. м:'); Writeln (TextToPrint,'N п/п','Номер кад. дела ', 'Фамилия И.О.собств.',' Адрес ', 'Общ. площ.(кв.м)','Дата посл. Уплаты налога на недвижимость'); For i:=1 To L do begin Writeln (TextToPrint,Form2.StringGrid1.Cells[0,i]:4, Form2.StringGrid1.Cells[1,i]:20,' ',Form2.StringGrid1.Cells[2,i]:20,' ', Form2.StringGrid1.Cells[3,i]:40,Form2.StringGrid1.Cells[4,i]:16,' ', Form2.StringGrid1.Cells[5,i]:20 ); end; System.Close(TextToPrint); end; end. {модуль Unit2 связан с формой Form2, куда выводится список домов с площадью превышающей 100 кв.м} 422 unit Unit2; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Grids, StdCtrls; type TForm2 = class(TForm) StringGrid1: TStringGrid; Button1: TButton; Label1: TLabel; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form2: TForm2; implementation {$R *.dfm} procedure TForm2.Button1Click(Sender: TObject); begin Form2.Close end; end. {модуль Unit3 связан с формой Form3, куда выводится список должни- ков по уплате налога на недвижимость} unit Unit3; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Grids; type TForm3 = class(TForm) Label1: TLabel; StringGrid1: TStringGrid; Button1: TButton; Label2: TLabel; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } 423 end; var Form3: TForm3; implementation {$R *.dfm} procedure TForm3.Button1Click(Sender: TObject); begin Form3.Close end; end. Вид некоторых диалоговых окон во время работы программы 424 425 Файл с исходной информацией удобнее подготовить с помо- щью стандартной программы «Блокнот». Каждое поле записи на- бирается на отдельной строке. Десятичный разделитель — точка. Дата уплаты налога в файле набирается в виде трех чисел на од- ной строке через пробел. Для приведенного выше примера файл с исходными данными выглядит так: 426 Задача Составить программу, которая записывает в файл введенные пользователем данные о результатах экзаменов, формируя таким образом простую базу данных. Исходные данные вводятся в поля диалогового окна и сохраняются в файле, компонентами которого являются записи типа TOzenka. unit apprec_; ………………………. // тип оценки 427 TKind = (NeUd, Ud, Hor,Otl); // запись файла TOzenka=record Facultet: string[20]; // факультет Predmet: string[20]; // предмет person: string[40]; // студент Oz: TKind; // оценка end; var Form1: TForm1; f: file of TOzenka; // файл записей – база данных implementation {$R *.DFM} // активизация формы procedure TForm1.FormActivate(Sender: TObject); var resp : word; // ответ пользователя begin AssignFile(f, 'D:\Ozenki.db'); {$I-} Reset(f); // открыть файл Seek( f, FileSize(f)); // указатель записи в конец файла {$I+} if IOResult = 0 then button1.enabled:=TRUE // теперь кнопка «Добавить» доступна else begin resp:=MessageDlg('Файл базы данных не найден.'+ ' создать новую БД?',mtInformation,[mbYes,mbNo],0); if resp = mrYes then begin {$I-} rewrite(f); 428 {$I+} if IOResult = 0 then button1.enabled:=TRUE else ShowMessage('Ошибка создания БД.'); end; end; end; // щелчок на кнопке «Добавить» procedure TForm1.Button1Click(Sender: TObject); var Ozenka: TOzenka; oz :TKind; begin with Ozenka do begin Facultet := ComboBox1.Text; Predmet:= ComboBox2.Text; person := Edit1.Text; case RadioGroup1.ItemIndex of 0: oz := NeUd; 1: oz:= Ud; 2: oz := Hor; 3: oz := Otl; end; end; write(f,Ozenka ); // записать содержимое полей записи в файл end; // завершение работы программы procedure TForm1.FormClose(Sender: TObject; var Action: TClo- seAction); begin CloseFile( f ); // закрыть файл end; procedure TForm1.Button2Click(Sender: TObject); begin 429 Form1.Close end; end. Так выглядит форма в процессе выполнения программы: Задача Составить программу, которая читает и обрабатывает данные, записанные в файл программой Добавление записи в файл, и, в зависимости от того, какой из переключателей — все или — выбрать выбран, выводит список оценок, полученных студента- ми всех факультетов или факультета, название которого введено в поле «Факультет». unit rdrec_; 430 ……………. var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); type // тип оценки TKind = (NeUd,Ud,Hor,Otl); // запись файла TOzenka = record Facultet:string[20]; Predmet:string[20]; person:string[40]; kind:TKind; end; var f: file of TOzenka; // файл записей rec: TOzenka; // запись, прочитанная из файла n: integer; // количество записей, удовлетворяющих запросу st: string[80]; begin AssignFile(f,'D:\ozenki.db'); {$I-} Reset(f); //открыть файл для чтения {$I-} if IOResult <> 0 then begin ShowMessage('Ошибка открытия файла БД.'); Exit; end; Memo1.Clear; // очистить список поля Memo 431 // обработка БД if RadioButton2.Checked then Memo1.Lines.Add('*** ' + ComboBox1.Text + ' ***'); n := 0; while not EOF(f) do begin read(f, rec); // прочитать запись if RadioButton1.Checked or (rec.facultet = ComboBox1.Text) then begin n := n + 1; st := rec.person+ ', ' + rec.predmet; if RadioButton1.Checked then st := st + ', '+ rec.facultet; case rec.kind of NeUd: st := st+ ', неудовлетворительно '; Ud: st := st+ ', удовлетворительно'; Hor: st := st+ ', хорошо'; Otl: st := st+ ', отлично'; end; Memo1.Lines.Add(st); end; end; CloseFile(f); if n = 0 then ShowMessage('В БД нет запрашиваемой информации.'); end; // переключатель «Выбрать» procedure TForm1.RadioButton2Click(Sender: TObject); begin Label1.Enabled := True; ComboBox1.Enabled := True; // теперь поля Факультет доступно ComboBox1.SetFocus; // курсор в поле «Факультет» end; 432 // переключатель «Все» procedure TForm1.RadioButton1Click(Sender: TObject); begin Label1.Enabled := False; ComboBox1.Enabled := False; // теперь поле «Факультет» не доступно end; procedure TForm1.Button2Click(Sender: TObject); begin Form1.Close end; end. Возможный вариант решения: Задачи для самостоятельного решения Группа А № 7.1. Подсчитать значение Q, вычисляемой по формуле 433 N ΣYi i=1 Q = ⎯⎯ , N! где Yi — элементы массива Y с размерностью N. Массив Y вве- сти из файла на диске. Вывод обеспечить в трех вариантах: 1) на экран; 2) на печатающее устройство; 3) в файл на диске. № 7.2. Дан массив X, содержащий вещественные числа. Найти и записать на место X(1) — наибольший элемент массива X, а на место X(N) — наименьший элемент массива (X1,X2,...,XN). Ввод исходного массива X осуществить из файла на диске. Вывод обеспечить в трех вариантах:1) на экран; 2) на печатающее уст- ройство; 3) в файл на диске. № 7.3 Дан массив Q(N), состоящий из отрицательных и положи- тельных чисел. Составить из Q два массива: A, содержащий только положительные числа; B, содержащий только отрицатель- ные. Массив Q вводится из файла на диске. Вывести исходный массив и массивы, полученные в процессе преобразования. Вы- вод обеспечить в трех вариантах:1) на экран; 2) на печатающее устройство; 3) в файл на диске. № 7.4. Даны натуральное число N, действительные числа X1,X2,..., Xn. Получить (1+r)/(1+s),где r — сумма всех тех членов последовательности X1, X2,..., Xn, которые не превосходят 1, a s — сумма членов, больших 1. Вывести сначала массив X. Затем r, s. Ввод исходных данных осуществить из файла на диске. Вывод — по желанию пользователя программы либо на экран, либо на печать или в файл на диске. № 7.5. Дана последовательность из N различных чисел. Найти сумму чисел этой последовательности, расположенных между максимальным и минимальным числами (в сумму включить и оба этих числа). Последовательность ввести из файла на диске. Вы- вести исходную последовательность в виде таблицы с указанием порядкового номера числа в последовательности и самого числа и сумму чисел. Вывод предусмотреть в трех вариантах:1) в файл на диске; 2) на экран; 3) на печатающее устройство. 434 № 7.6. Даны: n — целое число (n>=2),последовательности дейст- вительных чисел : a1, a2,..., an. Получить: min(a1+a2,a2+a3,...,an-1+an); max(a1,a1a2,a1a2a3,...,a1...an-1an). Ввод исходных данных осуществить из файла на диске. Вывод — по желанию пользователя программы либо на экран, либо на пе- чать, либо в файл на диске. № 7.7. Дан файл f1, который содержит номера телефонов сотруд- ников учреждения: указывается фамилия сотрудника, его ини- циалы и номер телефона. Найти телефон сотрудника по его фа- милии и инициалам. Вывод по желанию пользователя либо на эк- ран, либо в файл на диске, либо на печать. № 7.8. Дан файл f, содержащий сведения о кубиках: размер каж- дого кубика (длина ребра в см), его цвет (красный, желтый, зеле- ный или синий) и материал (деревянный, металлический, картон- ный). Найти: а) количество кубиков каждого из перечисленных цветов и их суммарный объем; б) количество деревянных кубиков с ребром 3 см и количество металлических кубиков с ребром, большим 5 см. Вывод по жела- нию пользователя либо на экран, либо в файл на диске, либо на печать. № 7.9. Сведения об автомобиле состоят из его марки, номера и фамилии владельца. Дан файл f, содержащий сведения о несколь- ких автомобилях. Найти: а) фамилии владельцев и номера авто- мобилей данной марки; б) количество автомобилей каждой мар- ки. Вывод по желанию пользователя либо на экран, либо в файл на диске, либо на печать. № 7.10. Дан файл f, содержащий сведения о книгах. Сведения о каждой из книг — это фамилия автора, название и год издания. а) Найти названия книг данного автора, изданных до 2002 года. б) Определить, имеется ли книга с названием «Информатика». Если да, то сообщить фамилию автора и год издания. Если таких книг несколько, то сообщить имеющиеся сведения обо всех этих книгах. Вывод по желанию пользователя либо на экран, либо в файл на диске, либо на печать. Группа Б 435 № 7.11. В память компьютера вводятся по очереди координаты N точек. Определить , сколько из них попадает в кольцо с внутрен- ним радиусом R1 и внешним R2. Обе окружности имеют общий центр с координатами X0 и Y0. Результаты обработки выдать ли- бо на напечать, либо на экран. Записать на дискету координаты точек, попавших в кольцо. № 7.12. Имеется таблица со среднесуточными температурами за период с 1.06.XX по 31.08.XX с точностью до 0,1 градуса. Необ- ходимо определить и вывести на экран, а по просьбе пользовате- ля и на печать, максимальную и минимальную среднесуточные температуры за указанный период, а также дни, в которые сред- несуточная температура отличалась от максимальной или мини- мальной не более чем на 0,5 градуса. Исходные данные вводить с магнитного диска. Форма представления исходных данных на магнитном диске: Июнь 1…...температура 2……– —…...– —…...– 30…...– Июль, август — аналогично. Форма вывода исходных данных и результатов на экран и печать. Среднесуточные температуры: Июнь. Дата температура Дата температура и т.д. 1….…–……...6……– всего 6 пар столбцов 2…….–……..7……– 3…….–……..8……– 4…….–……..9……– 5…….–…….10…...– Июль, август — аналогично. Максимальная температура XX градусов была: в июне: число, число, и т.д. в июле: число, число, и т.д. в августе: число, число, и т.д. Минимальная температура ХХ градусов была: в июне: число, число, и т.д. 436 в июле: число, число, и т.д. в августе: число, число, и т.д. Ввод исходных данных осуществить из файла на диске. Вывод предусмотреть в трех вариантах: 1) в файл на диске; 2) на экран дисплея; 3) на печать. № 7.13. Дан файл f, содержащий сведения о веществах: указыва- ется название вещества, его удельный вес и проводимость (про- водник, полупроводник, изолятор). а) Найти удельные веса и названия всех полупроводников. б) Выбрать данные о проводниках и упорядочить их по убыва- нию удельных весов. Составить программу. Вывод по желанию пользователя либо на экран, либо в файл на диске, либо на печать. № 7.14. Даны два файла f1 и f2. Файл f1 — это инвентарный файл, содержащий сведения о том, сколько изделий разных видов продукции хранится на складе (вид продукции задается его по- рядковым номером). Файл f2 — это вспомогательный файл, со- держащий сведения о том, на сколько уменьшилось или увеличи- лось количество изделий по некоторым видам продукции. Вспо- могательный файл может содержать несколько сообщений по продукции одного вида или не содержать ни одного такого сооб- щения. Обновить инвентарный файл на основе вспомогательного, образовав новый файл g. № 7.15. Составить программу назначения студентов на стипен- дию по результатам экзаменационной сессии: 1) если сессия сдана на все «5»,то стипендия повышенная; 2) если на «4» и «5», то стипендия обыкновенная; 3) если есть хотя бы одна «3»,то стипендия не назначается. Исходные данные ввести из файла на диске. Вывод обеспечить в трех вариантах:1) на экран дисплея; 2) на печатающее устройст- во; 3) в файл на диске. № 7.16. Даны координаты n точек на плоскости:X1,Y1,..., Xn, Yn (n=20). Найти номера двух точек, расстояние между которыми наибольшее (считать, что такая пара точек единственная). Коор- динаты точек вводятся из файла на диске. Вывести координаты точек в виде таблицы, номера двух точек, расстояние между ко- торыми наибольшее и само расстояние между ними. Вывод пре- 437 дусмотреть в трех вариантах: 1) в файл на диске; 2) на печатаю- щее устройство; 3) на экран дисплея. № 7.17. Дан файл f, содержащий сведения об учениках школы . Сведения об ученике состоят из его имени и фамилии и названия класса (года обучения буквы), в котором он учиться и среднего балла по результатам в последней четверти. а) Выяснить, сколько учеников школы не имеют отметок ниже четырех. б) Собрать в файле g сведения о лучших учениках школы, т.е. об учениках не имеющих средний балл ниже 4,5. Составить программу. Вывод по желанию пользователя либо на экран, либо в файл на диске, либо на печать. № 7.18. Информация о температуре воздуха за месяц задана в ви- де массива. Определить: а) сколько раз температура опускалась ниже 0 градусов по Цель- сию; б) температура скольких дней была ниже среднемесячной. Результаты выдать на печать. Исходные данные должны быть подготовлены на дискете. № 7.19. По результатам экзаменационной сессии подготовить на- печатанный протокол, который должен содержать данные о не- успевающих студентах (пофамильно), среднюю оценку каждого студента, средний балл по группе. В заголовке протокола указать название факультета и номер группы. Файл с исходными данны- ми подготовить на дискете. № 7.20. Подготовить на диске файл с фамилиями и оценками, по- лученными студентами группы во время сессии. Определить чис- ло неуспевающих студентов, фамилии студентов сдавших экза- мены на отлично и средний балл по группе. Протокол обработки данных выдать на печать, либо вывести на экран. |