- •Оглавление
- •2.6. Модульное программирование
- •2.8. Численные методы анализа
- •2.1. Элементы языка
- •Мантисса e порядок
- •2.2. Операторы языка
- •Input [приглашение ;/,] список_вводимых_переменных
- •Операторы управления
- •If логическое_условие then оператор
- •If логическое_условие goto метка_оператора
- •If логическое_условие then оператор else оператор
- •I f логическое_условие then
- •2.3. Организация ветвлений
- •Input “Укажите х”, X
- •15 ? “Неверно”
- •2.4. Организация циклов
- •Программа к задаче 9
- •Input "Введите числа X и y", X, y
- •2.5. Работа с массивами
- •Input "Введите число вкладчиков и процент ",n,p
- •2.6. Модульное программирование
- •2.7. ОбРаботка Символьных данных
- •Пример. ?instr(”Саша”,”а”),instr(3,”Саша”,”а”) Результат: 2,4
- •2.8. Численные методы анализа
- •Input “Введите левую и правую границы a и в ”, a, b,
- •Input “Введите допустимую погрешность e ”, e
- •2.9. Выявление нажатия клавиш
- •2.10. Работа с графикой
- •2.11. Работа с дисковыми файлами
- •Тесты по курсу
- •Литература
2.11. Работа с дисковыми файлами
В случаях, когда на компьютере обрабатываются большие наборы данных, или данные должны быть сохранены после завершения программы, следует сохранять их в дисковых файлах. Для описания структуры файла введем следующие термины. Каждый файл состоит из одной или нескольких записей. Каждая запись, в свою очередь содержит поля данных. Обычно, файл организуется так, что все его записи имеют одинаковую структуру. Если сравнить файл с таблицей, то строка таблицы соответствует записи, а отдельная клетка – полю. Например, пусть это файл о кадровом составе подразделения, где для каждого сотрудника хранятся данные: фамилия, табельный номер, год рождения, зарплата (в тыс. руб.).
поле 1 Фамилия |
поле 2 Табель |
поле 3 Год рождения |
поле 4 Зарплата |
|
Петров А.В. |
870 |
1946 |
800 |
запись 1 |
Кулик С.П. |
45 |
1970 |
1200 |
запись 2 |
. . . |
|
|
|
|
Яшин А.А. |
24 |
1972 |
950 |
запись N |
И конечно, файл должен иметь имя, которое дается по известным правилам для образования имен файлов. Пусть именем нашего файла будет KADR.DAT.
Различают файлы с последовательным и прямым (произвольным) доступом. Простейшим является последовательный доступ. В этом случае программа обрабатывает файл целиком даже если нужно изменить только один единственный символ. Такой файл может быть одновременно использован только для одной из целей – запись или считывание информации. Структура данных в файле может быть нерегулярной – длины одноименных полей могут отличаться друг от друга в разных записях. В файлах с произвольным доступом программа может обращаться к любой записи по номеру для ее обработки. Последовательность доступа к записям может быть любой, например, можно перемещаться и в обратном порядке. Структуры всех записей в файле должны быть строго идентичны.
Хотя файлы имеют имена, обращение к ним в программе происходит не непосредственно по имени, а по, закрепленному за ним в программе, номеру.
Любому действию с файлом должно предшествовать его открытие следующим оператором
OPEN имя_файла [FOR тип] AS#номер_файла LEN длина
Здесь файлу с указанным именем файла присваивается произвольный номер файла. Далее при обработке файла обращение к нему происходит только по номеру.
Остальные параметры имеют следующий смысл:
тип – может иметь одно из значений, определяющих тип доступа:
OUTPUT – последовательный ввод данных в файл,
INPUT – последовательный вывод данных из файла.
APPEND – последовательный ввод с добавлением данных в конец файла.
RANDOM – прямой ввод-вывод данных. Если параметр тип не задан, подразумевается файл с прямым доступом (RANDOM).
длина – длина записи. По умолчанию равна 128 байт для файлов прямого доступа и 512 байт для файлов прямого доступа.
Примеры организации доступа к файлу KADR.DAT:
OPEN "kadr.dat" FOR OUTPUT AS#1 – запись в начало нового файла
(номер 1) с последовательным доступом
OPEN "kadr.dat" FOR APPEND AS#2 – запись (добавление) в конец
существующего файла с последовательным доступом
OPEN "kadr.dat" FOR INPUT AS#3 – чтение с начала существующего
файла с последовательным доступом
OPEN "kadr.dat" FOR RANDOM AS#4 – запись или чтение файла с
произвольным доступом
Функция
LOC (номер_файла)
возвращает текущую позицию в открытом файле. Для файлов прямого доступа, возвращается номер записи, к которой было последнее обращение. Для файлов последовательного доступа – текущую байтовую позицию, деленную на 128.
Функция
EOF (номер_файла)
возвращает значение “истина”, если указатель в файле дошел до его конца. Функция позволяет контролировать положение указателя и не допускать ошибочных обращений за пределы файла.
Функция
LOF (номер_файла)
возвращает размер открытого файла в байтах.
Оператор
SEEK #номер_файла, позиция_в_файле
устанавливает указатель записей в заданную позицию. Для файлов прямого доступа – на запись с заданным номером. Для файлов с последовательным доступом – на байт с заданным номером от начала файла. В таких файлах оператор удобно использовать для перехода в его начало (например, SEEK #4,1 – переход в начало файла #4).
Оператор
CLOSE [[#номер_файла [,[#номер_файла]..]
закрывает файлы с перечисленными номерами. Если параметры отсутствуют, закрываются все файлы.
ФАЙЛЫ ПОСЛЕДОВАТЕЛЬНОГО ДОСТУПА. Работа с такими файлами осуществляется с помощью следующих операторов и функций.
Оператор
INPUT #номер_файла, переменные
читает данные из файла последовательного доступа в перечисленные переменные. Типы данных в файле и типы переменных должны соответствовать друг другу.
Оператор
WRITE #номер_файла [,список_выражений]
посылает данные из списка выражений в файл последовательного доступа.
Выводимые значения разделяются запятыми. Символьные строки заключаются в кавычки.
Оператор
PRINT #номер_файла, [USING формат;] список_выражений[,/;]
посылает данные из списка выражений в файл последовательного доступа. Никакие разделители между полями не вставляются.
Пример. Ввести в файл KADR.DAT данные о сотрудниках учреждения (фамилия, номер отдела, зарплата), первоначально хранимых в массивах fam$(n), ot(n), zar(n). Затем вывести из файла список сотрудников отдела 123, а также суммарную и среднюю зарплату его работников.
Программа подсчета суммарной и средней заработной платы отдела
n=6 'размерность исходных массивов данных (до 6 сотрудников)
'исходные массивы - фамилии, отделы, зарплаты
DIM fam$(n), ot(n), zar(n)
DATA "Иванов",123,800, "Петров",564,780, "Сидоров",123,950
DATA "Ильин",123,700, "Семина",564,600, "Коваль",123,900
READ fam$(1), ot(1), zar(1), fam$(2), ot(2), zar(2), fam$(3), ot(3), zar(3)
READ fam$(4), ot(4), zar(4), fam$(5), ot(5), zar(5), fam$(6), ot(6), zar(6)
'открытие файла KADR.DAT для ввода данных
OPEN "kadr.dat" FOR OUTPUT AS 1
PRINT " Список сотрудников"
PRINT "ФИО Отдел Зарплата"
FOR i=1 TO n 'запись данных в файл из массивов
WRITE #1, fam$(i), ot(i), zar(i)
PRINT fam$(i), ot(i), zar(i)
NEXT
CLOSE #1 'закрытие файла
OPEN "kadr.dat" FOR INPUT AS 1 'открытие файла для просмотра
sum = 0: k = 0 'переменные для суммы и числа работников в отделе
DO WHILE NOT EOF(1)
INPUT #1, f$, o, z 'считывание данных из файла
IF o=123 THEN 'для отдела 123
sum=sum+z 'суммируется зарплата
k=k+1 'число работников
PRINT f$,o,z 'вывод сведений о сотрудниках отдела
END IF
LOOP
CLOSE #1
'вывод суммарной зарплаты отдела
PRINT "Фонд зарплаты отдела="; sum
PRINT "Средняя зарплата="; sum/k
Результат работы программы:
Список сотрудников
ФИО Отдел Зарплата
Иванов 123 800
Петров 564 780
Сидоров 123 950
Ильин 123 700
Семина 564 600
Коваль 123 900
Иванов 123 800
Сидоров 123 950
Ильин 123 700
Коваль 123 900
Фонд зарплаты отдела= 3350
Средняя зарплата= 837.5
Пример. Данные из файла KADR.DAT отсортировать по номерам отделов и занести в файл OTDEL.DAT.
Программа сортировки данных из файла KADR.DAT
DIM no(20) 'массив для хранения номеров всех найденных отделов
'открытие файла KADR.DAT c номером 1 для просмотра
OPEN "kadr.dat" FOR INPUT AS 1
nn=0 'переменная для подсчета числа существующих отделов
DO WHILE NOT EOF(1) 'просмотр файла 1
INPUT #1, f$, o, z 'считывание данных
FOR i = 1 TO nn 'просмотр номеров уже найденных в файле отделов
'если такой отдел уже попадался, переход к следующей записи
IF no(i) = o THEN GOTO m:
NEXT
'если такой отдел в массиве не найден, он заносится в элемент no(nn)
nn=nn+1: no(nn)=o
m: LOOP
'сортировка номеров отделов по возрастанию
FOR i=1 TO nn-1: FOR j=i+1 TO nn
IF no(j)<no(i) THEN SWAP no(i),no(j)
NEXT j, i
KILL "otdel.dat"
'открытие файл OTDEL.DAT для добавления
OPEN "otdel.dat" FOR APPEND AS 2
FOR i = 1 TO nn 'просмотр номеров отделов в массиве NN
SEEK #1, 1 'переход в начало исходного файла KADR
DO WHILE NOT EOF(1) 'просмотр записей в файле KADR
INPUT #1,f$,o,z 'считывание данных из него
'если номера отделов в массиве и файле KADR совпадают,
'данные из файла KADR записываются в OTDEL
IF no(i)=o THEN WRITE #2, f$,o,z
LOOP
NEXT
CLOSE #2 'закрытие файла OTDEL.DAT
OPEN "otdel.dat" FOR INPUT AS 2 'открытие его для вывода
ot 'переменная для фиксации изменения номера отдела
DO WHILE NOT EOF(2) 'просмотр записей в файле
INPUT #2, f$,o,z 'считывание списка сотрудников
'Если это новый отдел, запоминается (в OT) и выводится его номер
IF ot<>o THEN PRINT " Отдел "; o: ot=o
PRINT f$,o,z 'вывод на экран списка сотрудников
LOOP
CLOSE 'закрытие всех файлов
Результат работы программы:
Отдел 123
Иванов 123 800
Сидоров 123 950
Ильин 123 700
Коваль 123 900
Отдел 564
Петров 564 780
Семина 564 600
ФАЙЛЫ ПРЯМОГО ДОСТУПА. Ввод/вывод данных в файл/из файла здесь осуществляется с помощью следующих операторов.
PUT номер_файла [,[номер_записи][,переменная]]
GET номер_файла [,[номер_записи][,переменная]]
Если опущен параметр номер записи, будет читаться следующая запись после последнего оператора PUT/GET или запись, указанная последним оператором SEEK.
Для организации перемещения данных удобно использовать так называемые комбинированные типы данных. Это сложный тип данных, определяемый пользователем с помощью операторов:
TYPE имя_типа
элемент AS тип
[элемент AS тип]
. . .
END TYPE
Здесь: имя типа – имя пользовательского типа данных
элемент – имя элемента пользовательского типа
тип – указатель типа данных языка (INTEGER, LONG, SINGLE, DOUBL, STRING). Тип STRING задается в форме STRING* число_знаков_в_переменной.
Пример. Положим, структура файла данных о сотрудниках некоторой организации состоит из двух полей: символьного поля фамилий длиной до 12 букв (STRING*12) и целочисленного поля зарплаты (INTEGER). После определения пользовательского типа SOTR можно указать конкретные переменные и массивы – здесь массив ORG(50) и переменная А.
Обращение к элементам такой структуры должно осуществляться по составному имени, включающему имя переменной и через точку – имя элемента структуры. Например, имя ORG(1).FAM указывает на первый элемент массива ORG типа FAM. Здесь же показаны операторы присваивания и печати.
TYPE sotr
fam AS STRING*12
zar AS INTEGER
END TYPE
DIM org(50) AS sotr, a AS sotr
org(1).fam="Петров": org(1).zar=900: a.fam="Петров": a.zar=900
PRINT org(1).fam, org(1).zar
PRINT a.fam; a.zar
Именно переменная пользовательского типа должна быть указана в операторах PUT и GET.
Пример. Рассмотрим технику работы с файлом прямого доступа. Положим, следует повысить зарплату сотрудникам организации, получающим менее 850 руб. на определенный, задаваемый в момент просмотра данных, процент. Программа состоит из трех разделов. В первом – из массива S в файл KADR.DAT заносятся исходные данные. Во втором – просматриваются данные обо всех сотрудниках, получающих меньше 850. Каждому их них руководитель подразделения назначает (или не назначает) процент увеличения зарплаты. Если процент указан, предъявляется новая зарплата и, при нажатии любой клавиши, обработка данных продолжается. В третьем разделе программы на экран выводятся обновленные данные из файла.
Иванов N отдела: 123 Зарплата: 800
Укажите % повышение зарплаты =20 Будет – 960
Для продолжения нажмите любую клавишу
Программа работы с файлом прямого доступа
TYPE kadr 'определение пользовательского типа данных
fam AS STRING * 12 'фамилия
ot AS INTEGER 'N отдела
zar AS LONG 'зарплата
END TYPE
n=6 'число сотрудников
DIM s(n) AS kadr 'объявление массива записей для ввода
DIM w AS kadr 'комбинированная переменная для вывода
DATA "Иванов",123, 800, "Петров", 564, 780, "Сидоров", 123,950
DATA "Ильин", 123, 700, "Семина", 564, 600, "Коваль", 123,900
READ s(1).fam, s(1).ot, s(1).zar, s(2).fam, s(2).ot, s(2).zar
READ s(3).fam, s(3).ot, s(3).zar, s(4).fam, s(4).ot, s(4).zar
READ s(5).fam, s(5).ot, s(5).zar, s(6).fam, s(6).ot, s(6).zar
OPEN "kadr.dat" FOR RANDOM AS 1 'открытие файла KADR.DAT
FOR i=1 TO n 'просмотр и запись данных в файл из массива S
PRINT s(i).fam, s(i).ot, s(i).zar
PUT #1, i, s(i)
NEXT
FOR i = 1 TO n 'анализ данных в файле
GET #1,i,w 'чтение данных из файла в переменную W
IF w.zar<850 THEN 'если зарплата <850
CLS
LOCATE 6, 20'
'выводятся данные о сотруднике
PRINT w.fam;” N отдела:”; w.ot;” Зарплата:”; w.zar
LOCATE 8, 20'
'определяется процент увеличения зарплаты
INPUT "Укажите % повышение зарплаты =", x'
IF x > 0 THEN 'если процент задан
w.zar=INT(w.zar*(1+x/100)) 'вычисляется новая зарплата
LOCATE 8, 55'
PRINT "Будет -"; w.zar 'вывод новой зарплаты
LOCATE 12, 23'
PRINT "Для продолжения нажмите любую клавишу"
SLEEP' 'пауза для просмотра
PUT #1, i, w 'запоминание нового значения
END IF
END IF
NEXT
CLS 'просмотр новых данных
PRINT "Новые данные"
FOR i=1 TO n'
GET #1,i,w: PRINT w.fam, w.ot, w.zar'
NEXT
CLOSE
Задачи для самостоятельного решения. Программа должна выполнять действия по обслуживанию файла (ввод, редактирование, удаление записей), а также по анализу содержащихся данных, возможно с вводом некоторых параметров с терминала.
1. Создать файл, содержащий сведения о количестве изделий, собранных рабочими завода за неделю. Каждая запись содержит поля: фамилия сборщика, количество изделий, собранных им ежедневно в течение пяти дней недели, т.е. в понедельник, вторник и т.д.
Написать программу, выдающую информацию: фамилию сборщика и общее число деталей, собранных им за неделю; фамилию сборщика, собравшего наибольшее число изделий и день, когда это произошло.
2. Создать файл, содержащий сведения о телефонных абонентах. Каждая запись имеет поля: фамилия абонента, номер телефона, год установки.
Написать программу, выдающую:
– по вводимой фамилии абонента сообщается номер его телефона;
– определяется количество установленных телефонов с любого, вводимого с терминала, года.
3. Создать файл, содержащий сведения о сдаче студентами сессии. Структура записи: номер группы, фамилия студента, оценки по четырем экзаменам и трем зачетам в форме "з" (зачет) и "н" (незачет).
Написать программу, выдающую:
– фамилии неуспевающих студентов с указанием номера группы и числа задолженностей;
– средний балл каждого студента и группы в целом.