Ситкин. Информатика. Программирование в DELPHI
.pdfIMPLEMENTATION
{$R *.dfm}
var x:array of array of real; //объявлен как глобальный динамич. массив
procedure TForm1.Button1Click(Sender: TObject); var f:textfile; i, j, m, n:byte; z:real;
BEGIN
If OpenDialog1.Execute Then //если файл выбран пользователем в окне
Begin
AssignFile(f, OpenDialog1.FileName); //связать его с переменной f
{$I-} Reset(f); {$I+} //открыть файл, связанный с f для чтения
if IOResult <>0 then begin ShowMessage('Файл не найден'); Exit; end;
End
Else Begin ShowMessage('Файл не выбран'); Exit; End;
if eof(f) then begin ShowMessage('Файл пустой'); CloseFile(f); Exit; end;
m:=0; n:=0; //начальные значения счётчиков строк и столбцов repeat //цикл подсчёта числа строк
Readln(f); //перевод указателя чтения в файле f на следующую строку m:=m+1; //увеличение значения счётчика строк на единицу
until eof(f); //выход из цикла, если достигнут конец файла Reset(f);//повторн. откр-е файла для возврата указателя чтения в начало файла repeat //цикл подсчёта числа элементов первой строки (числа столбцов)
{$I-} Read(f, z); {$I+}//без z не будет перевода указателя чтения к след-щей //позиции, поэтому контролируем, допустимое ли число записывается в z
if IOResult <>0 then //если ошибка синтаксиса элемента в 1-ой строке
begin ShowMessage('Ошибка в 1-ой строке'); CloseFile(f); Exit; end;
n:=n+1; //увеличение значения счётчика столбцов на единицу until eoln(f); //выход из цикла, если достигнут конец строки
Reset(f);//повторн. откр-е файла для возврата указателя чтения в начало файла SetLength(x, m, n); //выделение памяти под двумерный массив (матрицу)
for i:=0 to m 1 do //внешний цикл (в нём один оператор – вложенный for) for j:=0 to n 1 do Begin //начало тела вложенного цикла
{$I-} Read(f, x[i,j]); {$I+} //ввод xij элемента из файла if IOResult <>0 then //если ошибка синтаксиса эл-нта
begin
ShowMessage('Ошибка синтаксиса эл-нта в файле');
CloseFile(f); SetLength(x, 0, 0); Exit; end;
End; //конец тела вложенного цикла CloseFile(f); //закрытие файла чтения
END; //конец процедуры
131
Пример 10.3
Разработаем проект для считывания с файла элементов двумер-
ного массива с неизвестным заранее числом строк и переменным чис-
лом элементов в каждой из них и записи их квадратов в другой файл.
Как и в предыдущем проекте, предусмотрим загрузку окна от-
крытия файла и контроль выбора файла, его доступности и наличия данных в нём (рис. 10.3). В случае успешного его прохождения, ис-
пользуя конструкцию вложенных циклов, поэтапно будем выделять память. В теле внешнего цикла на каждой итерации – под двумерный массив x сначала по первому измерению для одной строки и под один элемент одномерного массива y, в который потом запишем длину
(число элементов) этой строки. В теле вложенного цикла на первой итерации выделяется, а со второй – добавляется память по второму измерению под один элемент текущей строки двумерного массива. В
эту ячейку памяти записывается текущий элемент из файла, если нет ошибки синтаксиса, и т.д. для всех элементов строки. По окончании строки происходит выход из вложенного цикла, в одномерный массив y записывается длина только что пройденной строки (число итераций внутреннего цикла на данной строке), указатель чтения переходит к следующей строке, и всё повторяется, пока файл не закончится.
После выхода из внешнего цикла имеем введённый в память ис-
комый двумерный массив и массив, содержащий число элементов каждой из строк, её номер соответствует номеру элемента, а в пере-
менную m записано число строк. Используя эти данные, после про-
верки выбора и доступности файла записи, во вложенных циклах осуществляется вывод квадратов элементов во второй файл, для вы-
бора которого предусмотрим загрузку окна сохранения файла.
132
начало |
|
|
|
файл |
|
нет |
файл чтения |
выбран |
|
|
не выбран |
|
|
|
|
да |
|
|
|
открыть |
|
|
|
файл чтения |
|
|
|
|
|
|
|
ошибка |
|
да |
файл чтения |
открытия |
|
|
не найден |
|
|
|
|
нет |
|
|
|
конец |
|
да |
файл чтения |
файла |
|
|
пустой |
|
|
|
|
нет |
|
|
|
номер строки |
|
|
|
i = 0 |
|
|
|
|
|
|
|
|
|
|
|
не конец |
нет |
закрыть файл |
|
чтения. число |
|||
файла |
|
|
строк m = i |
да |
|
|
|
|
|
|
|
выд-ть память |
|
|
|
под i-ую стр. |
|
|
|
|
|
|
|
выделить память под yi
номер столбца j = 0
не конец |
нет |
||
строки |
|
|
|
да |
|
|
|
выд-ть память |
|
длина i-ой |
|
под j-ый эл-т |
|
|
|
|
|
строки yi = j |
|
i-ой строки |
|
|
|
ввод xij |
|
|
|
|
|
i = i + 1 |
|
из файла |
|
|
|
|
|
|
|
ошибка |
|
|
|
да |
1 |
||
ввода xij |
|
|
|
|
|
|
|
нет |
|
|
|
перевод j = j + 1 строки чтения
|
1 |
|
|
|
ошибка |
|
|
синтаксиса |
|
|
|
|
|
закрыть |
|
|
файл чтения |
|
|
|
|
|
|
закрыть |
|
высвободить |
файл чтения |
|
всю память |
|
|
|
файл |
нет файл записи |
выбран |
не выбран |
|
|
да |
|
открыть файл записи
ошибка |
да файл записи |
доступа |
недоступен |
нет |
|
номер строки i = 0
нет закрыть файл i m 1 записи. высвть всю память
да
номер столб- |
|
|
|
ца j = 0 |
|
конец |
|
|
|
||
|
|
|
|
j yi 1 |
нет |
||
|
|
|
|
да |
|
|
|
запись x2ij |
|
i = i + 1 |
|
в файл |
|
|
|
|
|
|
|
|
|
|
|
перевод j = j + 1 строки записи
Рис. 10.3
133
var f1,f2:textfile; i, j, m:byte; x:array of array of real; y:array of byte;
BEGIN
If OpenDialog1.Execute Then //если файл выбран в окне открытия файла
Begin
AssignFile(f1, OpenDialog1.FileName); //связать его с переменной f1
{$I-} Reset(f1); {$I+} //открыть файл, связанный с f1 для чтения
if IOresult <>0 then begin ShowMessage('Файл не найден'); Exit; end;
End
Else Begin ShowMessage('файл для чтения не выбран'); Exit; End;
if eof(f1) then begin ShowMessage(' файл пуст'); Closefile(f1); Exit; end;
i:=0; //начальное значение номера строки
while not eof(f1) do //пока не достигнут конец файла Begin //начало тела внешнего цикла
SetLength(x, i+1); //выделение (добавл.) памяти под одну строку массива x SetLength(y, i+1); //выделение (добавл.) памяти под один элемент массива y j:=0; //начальное значение номера столбца (номера элемента в строке)
while not eoln(f1) do //пока не достигнут конец строки begin //начало тела вложенного цикла
SetLength(x[i], j+1); //выделение памяти под один эл-нт в i-ой строке {$I-} Read(f1, x[i,j]); {$I+} //чтение (ввод) xij элемента из файла
if IOResult <>0 then begin
ShowMessage('Ошибка син-са'); CloseFile(f1); SetLength(x, 0, 0); SetLength(y, 0); Exit;
end;
j:=j+1; //переход к следующему столбцу в i-ой строке end; //конец тела вложенного цикла
y[i]:=j; //запись в массив y длины i-ой строки i:=i+1; //переход к следующей строке
Readln(f1); //перевод строки чтения в файле чтения End; //конец тела внешнего цикла
CloseFile(f1); //закрытие файла чтения
m:=i; //число строк получает значение числа итераций внешнего цикла If SaveDialog1.Execute Then //если файл выбран в окне сохранения
Begin
AssignFile(f2,SaveDialog1.FileName); //связать его с переменной f2
{$I-} Rewrite(f2); {$I+} //открыть файл, связанный с f2 для записи
if IOResult <>0 then begin ShowMessage('Ошибка доступа'); Exit; end;
End
Else Begin ShowMessage('Файл записи не выбран'); Exit; End;
i:=0; //начальное значение номера строки
134
while i<=m-1 do //пока не исчерпаны все строки Begin //начало тела внешнего цикла
j:=0; //начальное значение номера столбца (номера элемента в строке) while j <= y[i]-1 do //пока не исчерпаны все элементы i-ой строки begin //начало тела вложенного цикла
Write(f2, sqr(x[i, j]):5:2,' '); //запись в файл квадрата элемента в формате
j:=j+1; //переход к следующему столбцу |
5:2 с пробелом |
end; //конец тела вложенного цикла |
|
i:=i+1; //переход к следующей строке вывода |
|
Writeln(f2); //перевод строки записи в файле |
|
End; //конец тела внешнего цикла |
|
CloseFile(f2); //закрытие файла записи |
|
SetLength(x, 0, 0); //высвоб. памяти из-под двумерного массива элементов SetLength(y, 0); //высвоб. памяти из-под одномерного массива длин строк
END; //конец процедуры
На рис. 10.4 представлен результат работы приложения.
Рис. 10.4
Представлен способ выделения динамической памяти под дву-
мерный массив переменной длины строк и неизвестного их числа, за-
полнения значениями из внешнего файла и записи элементов такого массива во внешний файл. Но для решения поставленной задачи па-
мять под массив можно было не выделять. Достаточно объявить от-
дельную переменную, в которую будет считываться в конструкции вложенных циклов одно значение текущего элемента из файла. Если ошибки синтаксиса нет, то в этом же цикле следующим оператором можно записать квадрат этой переменной во второй файл и перейти к считыванию следующего элемента. Предыдущее значение перемен-
ной (предыдущего элемента) «затрётся» новым, но квадрат старого значения уже записан во второй файл и интереса не представляет.
135
Задание
Разработать проект для считывания элементов прямоугольной матрицы с внешнего файла с представлением на форме и её обработ-
ки в соответствии с вариантом задания предыдущей работы. Резуль-
таты обработки записать или добавить (на усмотрение пользователя)
в другой внешний файл. Предусмотреть возможность выбора пользо-
вателем файлов чтения/записи данных, а также обработку исключи-
тельных ситуаций приложением.
Содержание отчёта
цель работы и полная формулировка задания;
блок-схема алгоритма обработки файлов и массива;
текст модуля проекта;
пример содержимого файлов чтения/записи данных;
выводы по работе.
Контрольные вопросы
1. В каких случаях следует использовать внешние файлы при разра-
ботке приложений? Что такое физический и логический файл?
2. Какова классификация логических файлов? В чём состоит разница при их объявлении и обработке?
3. Перечислите стандартные подпрограммы, используемые для орга-
низации обмена данными приложений с внешними файлами.
4.Каковы назначение и свойства компонентов OpenDialog и SaveDialog?
5.Какие исключительные ситуации (ошибки) могут возникнуть при работе с внешними файлами? Как их правильно обработать?
6.Как перевести указатель чтения (записи) в файле на строку ниже?
7.Как обозначается конец строки и файла в разных типах файлов?
136
|
|
|
|
Приложение 1. Элементы блок-схем алгоритмов |
Элемент блок-схемы |
Описание |
|||
|
|
|
R 0,25a |
|
0,5a |
начало |
|
|
|
|
|
|||
|
2a |
|
|
Начало и конец схемы |
|
конец |
|
2a |
a |
Действие (процесс) или группа действий |
|
|
|
|
|
|
a |
Ввод или вывод данных |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0,25a |
|
|
|
|
|
|
|
|
|
|
2a |
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
нет a |
Условие. Определение направления движения |
|
да |
|
|
|
|
|
потока в зависимости от условия |
|
|
2a |
|
|
|
||
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
a |
Предварительно описанный процесс. Ссылка |
|
|
|
|
|
|
||
|
|
|
|
|
|
0,15a |
на действия, описанные в другом алгоритме |
|
|
|
|
|
|
(подпрограмму). |
|
|
2a |
|
|
|
|
||
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
a |
|
|
|
|
a |
Подготовка. Границы изменения счётчика в |
|
|
|
|
|
|
счётном операторе цикла |
|
|
|
|
|
|
|
|
|
|
2a |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0,5a |
|
|
Соединитель. Связывает разделённые части |
|||
|
|
|
|
|
|
|
схемы, находящиеся на одной странице. |
|
|
|
|
|
|
|
Внутри указывают номер соединения |
|
|
|
|
|
|
|
Межстраничный соединитель. Связывает раз- |
|
|
0,6a |
|
|
делённые части схемы, находящиеся на раз- |
||
0,5a |
|
|
|
|
|
ных страницах. Внутри указывают номер со- |
|
|
0,2a |
|
|
единения и страницу продолжения схемы |
|||
|
|
|
|
|
|
|
Линии потока |
|
|
|
|
|
|
a |
Комментарий. Пояснение к блоку или запись |
|
5 мм |
|
|
|
|
действий, не поместившихся внутри блока |
|
|
|
|
|
|
|
||
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
137
Приложение 2. Титульный лист
Санкт-Петербургский государственный политехнический университет
Кафедра информационных машиностроительных технологий
ОТЧЁТ
о лабораторной работе
Дисциплина: «Информатика» Тема: «Обработка многомерных массивов»
Студент гр. 1041/1 |
А. В. Савченко |
Преподаватель |
Д. С. Ситкин |
|
«__»_________2009 г. |
Санкт-Петербург
2009 г.
138
Ситкин Дмитрий Сергеевич
ИНФОРМАТИКА.
ПРОГРАММИРОВАНИЕ В DELPHI
Лабораторный практикум
139