Ошибка ввода программа завершена program1 pas строка 6

Midass

0 / 0 / 0

Регистрация: 10.09.2015

Сообщений: 34

1

Ошибка ввода — программа завершена

15.09.2015, 19:58. Показов 5188. Ответов 6

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Пишет: »*Ошибка ввода. Программа завершена (Program3.pas, строка 6)

Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
program primer;
var
  y,x:real;
begin
  writeln('Введите число x');
  readln(x);
   if (x>-5) or (x<>0) then
      begin
    y:=1/x;
    writeln(' x=',x,' y=',y);
      end
         else
    if (x<-10) then
       begin
     y:=sqr(x);
     writeln(' x=',x,' y=',y);
       end
          else begin y:=y+1;
     writeln(' x=',x,' y=',y); end
end.



0



ФедосеевПавел

Модератор

Эксперт по электронике

8324 / 4223 / 1602

Регистрация: 01.02.2015

Сообщений: 13,154

Записей в блоге: 4

15.09.2015, 21:25

2

Ваш отформатированный код

Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
program primer;
 
var
  y, x: real;
begin
  writeln('Введите число x');
  readln(x);
  if (x > -5) or (x <> 0) then
  begin
    y := 1 / x;
    writeln(' x=', x, ' y=', y);
  end
  else
  if (x < -10) then
  begin
    y := sqr(x);
    writeln(' x=', x, ' y=', y);
  end
  else
  begin
    y := y + 1;
    writeln(' x=', x, ' y=', y);
  end;
end.

Очевидно, что будут выполнятся только ветка » if (x > -5) or (x <> 0) then».
А сообщения «»*Ошибка ввода. Программа завершена (Program3.pas, строка 6)» — не было.
Что вы вводите?



1



Почетный модератор

64289 / 47588 / 32739

Регистрация: 18.05.2008

Сообщений: 115,181

15.09.2015, 21:30

3

Цитата
Сообщение от ФедосеевПавел
Посмотреть сообщение

Что вы вводите?

Нужно условие задачи глянуть, тут лажа написана…



1



0 / 0 / 0

Регистрация: 10.09.2015

Сообщений: 34

15.09.2015, 21:41

 [ТС]

4

Вот условие:

Виды функций:

https://www.cyberforum.ru/cgi-bin/latex.cgi?<br />
Y=begin{cases}frac1X&text{, if }x>-5, xneq 0\ X^2&text{, if }x<-10\ sqrt{|X|+1}&text{, otherwise}end{cases}<br />

Исходные данные:

X=-18.76; X=-3.57; X=-7.15.



0



Модератор

Эксперт по электронике

8324 / 4223 / 1602

Регистрация: 01.02.2015

Сообщений: 13,154

Записей в блоге: 4

15.09.2015, 21:50

5

if (x > -5)

or

and (x <> 0) then



1



Puporev

Почетный модератор

64289 / 47588 / 32739

Регистрация: 18.05.2008

Сообщений: 115,181

15.09.2015, 21:50

6

Лучший ответ Сообщение было отмечено Памирыч как решение

Решение

Если как написано на картинке, то так.

Pascal
1
2
3
4
5
6
7
8
9
10
11
function y(x:real):real;
begin
if x<-10 then y:=x*x
else if(x>-5)and(x<>0)then y:=1/x
else y:=sqrt(abs(x)+1);
end;
begin
writeln('При х=-18.75 y=',y(-18.75):0:2);
writeln('При х=-3.57 y=',y(-3.57):0:2);
writeln('При х=-7.15 y=',y(-7.15):0:2);
end.



1



Модератор

Эксперт по электронике

8324 / 4223 / 1602

Регистрация: 01.02.2015

Сообщений: 13,154

Записей в блоге: 4

15.09.2015, 21:51

7

И ещё — в ветках if достаточно вычислять. Вывод writeln — можно сделать после вычисления перед последним end. Как это показано у Puporev.



1



1
Out of memory
Выход за границы памяти
Компилятор выполняется вне допустимых границ памяти. Имеется ряд возможных решений проблемы:

§ Если в меню Options?Linker?Link Buffer, установлен параметр Memory, переключите его в значение Disk.

§ Возможно программа слишком велика, чтобы компилироваться в таком объеме памяти. Следует разбить ее на два или более модуля.

2
Identifier expected
Не указан идентификатор
В этом месте должен находиться идентификатор.

3
Unknown identifier
Неизвестный идентификатор
Этот идентификатор не был описан.

4
Duplicate identifier
Повторный идентификатор
Идентификатор уже представляет имя программы, модуля, константы, переменной, типа, процедуры и функции, описанных в текущем блоке.

5
Syntax  error
Синтаксическая ошибка
В исходном тексте найден неверный символ.

6
Error in real constant
Ошибка в вещественной константе
 

7
Error in integer constant
Ошибка в целой константе
 

8
String constant exceeds line
Строковая константа превышает размеры строки
Вероятно, отсутствует кавычка в конце строковой константы.

10
Unexpected end of file
Неожиданный конец файла
Причины:

§ несоответствующее количество begin и end (не забудьте, что оператор case также заканчивается словом end);

§ включаемый файл заканчивается в середине раздела операторов. Каждый раздел операторов должен целиком помещаться в одном файле;

§ незаконченный комментарий.

11
Line too long
Строка слишком длинная
Максимальная длина строки может равняться 126 символам. Возможно, отсутствует апостроф в конце строковой константы.

12
Type identifier expected
Нужен идентификатор типа
Не указан типа идентификатора, как это должно быть.

13
Too many open files
Слишком много открытых файлов
Файл CONFIG.SYS не содержит параметра FILES=xx или этот параметр указывает слишком много файлов. Следует увеличить число файлов.

14
Invalid file name
Неверное имя файла
Имя файла неверно или указывает несуществующий путь.

15
File not found
Файл не найден
Файл не может быть найден ни в текущем каталоге, ни в каком-либо другом исследуемом каталоге, предназначенном для этого типа файлов.

16
Disk full
Диск заполнен
Удалите некоторые файлы или воспользуйтесь новым диском (если речь идет о сменном носителе).

17
Invalid compiler directive
Неправильная директива компилятора
Возможно, неверная буква в директиве компилятора, один из параметров директивы компилятора неверный или используется глобальная директива компилятора, когда компиляция тела программы уже началась.

18
Too many files
Слишком много файлов
В компиляции программы или программного модуля участвует слишком много  файлов. Следует объединить включаемые файлы или сделать короче имена файлов.

19
Undefined type in pointer definition
Неопределенный тип в определении ссылки
Была осуществлена ссылка на тип в приведенном ранее описании указателя, но этот тип не был описан.

20
Variable identifier expected
Нужен идентификатор переменной
Идентификатор не описывает переменную, как это должно быть.

21
Error in type
Ошибка в определении типа
Определение типа не может начинаться с этого символа.

22
Structure too large
Слишком большая структура
Максимально допустимый размер структурного типа 65 535 байт.

23
Set base type of range
Базовый тип множества выходит за допустимые границы
Базовый тип множества должен представлять собой отрезок типа с границами в пределах от 0 до 255 или перечислимого типа, допускающим не более чем 256 значений.

24
File components may not be files or objects
Элементы файла не могут быть файлами или объектами
Тип компоненты файлового типа не может быть объектным или файловым типом и не может быть структурным типом с компонентами файлового или объектного типа: конструкции file of file или file of object не допускаются.

25
Invalid string length
Неверная длина строки
Длина строки должна находиться в диапазоне от 1 до 255.

26
Type mismatch
Несоответствие типов
Причины:

§ несовместимые типы переменной и выражения в операторе присваивания;

§ несовместимые типы фактического и формального параметров в обращении к процедуре или функции;

§ тип выражения, несовместимый с типом индекса при индексировании массива;

§ несовместимые типы операндов в выражении.

27
Invalid subrange base type
Неправильный базовый тип интервального типа
Допустимыми являются все порядковые типы.

28
Lower bound greater than upper bound
Нижняя граница больше верхней
В описании диапазона нижняя граница больше, чем верхняя.

29
Ordinal type expected
Нужен порядковый тип
Вещественные, строковые, структурные и ссылочные типы в данном случае  не допускаются.

30
Integer constant expected
Нужна целая константа
 

31
Constant expected
Нужна константа
 

32
Integer or real constant expected
Нужна целая или вещественная константа
 

33
Pointer type identifier expected
Нужен идентификатор типа указателя
Данный идентификатор не обозначает тип указателя, как это требуется.

34
Invalid function result type
Неправильный тип результата функции
Правильными типами результата функции являются все простые типы, а также строковые и ссылочные типы.

35
Label identifier expected
Нужен идентификатор метки
Метка не обозначена с помощью идентификатора, как это требуется.

36
BEGIN expected
Нужен BEGIN
 

37
END expected
Нужен END
Следует проверить соответствие ключевых слов BEGIN и END.

38
Integer expression expected
Нужно выражение типа INTEGER
Предыдущее выражение должно иметь целочисленный тип INTEGER

39
Ordinal expression expected
Нужно выражение порядкового типа
Предшествующее выражение должно иметь порядковый тип.

40
Boolean expression expected
Нужно выражение типа BOOLEAN
Предшествующее выражение должно иметь тип BOOLEAN

41
Operand types do not math operator
Типы операндов не соответствуют оператору
Данный оператор не может быть применен к операндам этого типа, например, нельзя ‘A’ разделить на ‘2’.

42
Error in expression
Ошибка в выражении
Данный идентификатор не может участвовать в выражении указанным образом.

43
Illegal assignment
Неверное присваивание
§ Нетипизированным файлам и переменным нельзя присваивать значения.

§ Идентификатору функции можно присваивать значения только внутри раздела операторов данной функции.

44
Field identifier expected
Нужен идентификатор поля
Данный идентификатор не является полем предшествующей переменной типа «запись».

45
Object file too large
Объектный файл слишком большой
Нельзя компоновать файлы .obj, превышающие 64 Кбайт.

46
Undefined external
Не определена внешняя процедура
Внешняя процедура или функция не имеет соответствующего определения Public в объектном файле. Убедитесь, что вы указали все объектные файлы в директивах   {$L имя_файла}, и проверьте написание идентификаторов процедуры или функции в файле .asm.

47
Invalid object file record
Неправильная запись объектного файла
Файл .obj содержит неверную объектную запись. Убедитесь, что данный файл является действительно файлом .obj.

48
Code segment too large
Сегмент кода слишком большой
Максимальный размер кода программы или программного модуля равняется 65 520 байт. Если вы компилируете программный модуль, разбейте его на два или более программных модулей.

49
Data segment too large
Сегмент данных слишком велик
Максимальный размер сегмента данных равен 65 520 байт, включая данные, описываемые используемыми программными модулями. Если вам нужно большее количество глобальных данных, опишите большие структуры с помощью указателей и выделяйте для них память динамически с помощью процедуры New.

50
DO expected
Нужен оператор DO
 

51
Invalid PUBLIC definition
Неверное определение PUBLIC
§ Две или более директивы PUBLIC на языке ассемблера определяют один и тот же идентификатор.

§ Объектный файл .obj определяет идентификаторы PUBLIC, которые не находятся в сегменте CODE.

52
Invalid EXTRN definition
Неверное определение EXTRN
§ На идентификатор имеется ссылка в директиве EXTRN на языке ассемблера, но он не описан в программе или модуле на Паскале или в интерфейсной части какого-либо из используемых модулей.

§ Идентификатор обозначает абсолютную переменную.

§ Идентификатор обозначает процедуру или функцию типа inline.

53
Too many EXTRN definition
Слишком много определений EXTRN
Невозможно обработать файлы .obj, если имеется более чем 256 EXTRN.

54
OF expected
Требуется OF
 

55
INTERFACE expected
Требуется интерфейсный раздел
 

56
Invalid relocatable reference
Недопустимая перемещаемая ссылка
§ Файл .obj содержит данные и перемещаемые ссылки в сегментах, отличных от CODE. Например, вы пытаетесь описать инициализированные переменные в сегменте DATA.

§ Файл .com содержит ссылки с размерами в байтах на перемещаемые идентификаторы. Такая ошибка происходит в случае, если вы используете операторы HIGH и DOWN с перемещаемыми идентификаторами или если вы ссылаетесь в директивах DB на перемещаемые идентификаторы.

§ Операнд ссылается на перемещаемый идентификатор, который не был определен в сегменте CODE или в сегменте DATA.

§ Операнд ссылается на процедуру EXTRN или функцию EXTRN со смещением, например CALL SortProc+8.

57
Then expected
Требуется THEN
В нужном месте отсутствует слово then.

58
TO or DOWNTO expected
Требуется TO или DOWNTO
В нужном месте отсутствует ключевое слово TO или DOWNTO.

59
Undefined forward
Не определено опережающее описание
§ Процедура или функция были описаны в интерфейсном разделе программного модуля, но их определение отсутствует в разделе реализации.

§ Процедуры или функции были описаны с помощью описания forward, но их определение не найдено.

61
Invalid typecast
Неверное преобразование типа
§ Размеры ссылки на переменную и тип результата отличаются друг от друга при изменении типа переменной.

§ Вы пытаетесь осуществить приведение типа выражения, когда разрешается только ссылка на переменную, процедуру или функцию.

62
Division by zero
Деление на нуль
Предшествующая операция пытается выполнить деление на нуль.

63
Invalid file type
Неверный файловый тип
Данный файловый тип не обслуживается процедурой обработки файлов. Например, вы пытаетесь использовать процедуру Readln для типизированного файла или процедуру Seek для текстового.

64
Cannot Read or Write variables of this type
Нельзя считать или записать переменные данного типа
Процедуры Read и Readln могут считывать переменные символьного, целого, вещественного и строкового типа.

65
Pointer variable expected
Нужно использовать переменную-указатель
Предыдущая переменная должна иметь тип «указатель».

66
String variable expected
Нужна строковая переменная
Предшествующая переменная должна иметь строковый тип.

67
String expression expected
Нужно выражение строкового типа
Предшествующее выражение должно иметь строковый тип.

68
Circular unit reference
Циклическая ссылка на модуль
Два модуля не могут ссылаться друг на друга в разделе interface, но могут это делать в разделе implementation. Переупорядочите операторы uses таким образом, чтобы циклические ссылки имели место только в разделе implementation.

69
Unit name mismatch
Несоответствие имен программных модулей
Имя программного модуля, найденное в файле .tpu, не соответствует имени, указанному в операторе uses.

70
Unit version mismatch
Несоответствие версий программных модулей
Один или несколько программных модулей, используемых данной программой, были изменены после их компиляции. Воспользуйтесь командой Compile?Make или Compile?Build в интегрированной интерактивной среде программирования, что позволит автоматически скомпилировать программные модули, нуждающиеся в перекомпиляции.

71
Internal stack overflow
Переполнение внутреннего стека
Внутренний стек компилятора исчерпан из-за слишком большого уровня вложенности операторов. Переорганизуйте исходный код и уменьшите уровень вложенности. Например, переместите внутренние уровни вложенных операторов в отдельную процедуру.

72
Unit file format error
Ошибка формата файла программного модуля
Файле .tpu является недействительным. Возможно, он создан с помощью старой версии Turbo Pascal или Borland Pascal. В этом случае нужно перекомпилировать исходный код модуля и создать новый модуль.

73
Implementation expected
Требуется раздел реализации
Ключевое слово Implementation отсутствует там, где оно должно быть. Возможно, вы включили реализацию процедуры, функции или метода в интерфейсную часть модуля.

74
Constant and case types do not math
Типы констант и выражения оператора Case не соответствуют друг другу
Тип константы оператора Case несовместим с выражением селектора в операторе выбора

75
Record variable expected
Нужна переменная типа запись
Предшествующая переменная должна иметь тип «запись».

76
Constant out of range
Константа выходит за допустимые границы
§ Вы пытаетесь указать массив с константами, нарушающими границы.

§ Вы пытаетесь присвоить константу вне диапазона переменной.

§ Вы пытаетесь передать константу вне диапазона в качестве параметра процедуре или функции.

77
File variable expected
Нужна файловая переменная
Предшествующая переменная должна иметь файловый тип.

78
Pointer expression expected
Нужно выражение типа указатель
Предшествующая переменная должна иметь ссылочный тип.

79
Integer or real expression expected
Нужно выражение типа real  или integer
Предшествующее выражение должно иметь тип real  или integer.

80
Label not within current block
Метка не находится внутри текущего блока
Оператор goto не может ссылаться на метку, находящуюся вне текущего блока.

81
Label already defined
Метка уже определена
Данная метка уже помечает оператор.

82
Undefined label in processing statement part
Неопределенная метка в предшествующем разделе операторов
Данная метка была описана, и на нее осуществлялась ссылка в предшествующем разделе операторов, но она не определена.

83
Invalid @ argument
Недействительный аргумент оператора @
Действительными аргументами являются ссылки на переменные и идентификаторы процедур или функций.

84
Unit expected
Нужно ключевое слово Unit
Не указано ключевое слово Unit, как это требуется.

85
« expected
Нужно указать «;»
Не указана, где это требуется, точка с запятой.

86
«:» expected
Нужно указать «:»
Не указана, где это требуется, двоеточие.

87
«,» expected
Нужно указать «,»
Не указана, где это требуется, запятая.

88
«(» expected
Нужно указать «(»
Не указана, где это требуется, открывающаяся круглая скобка.

89
«)» expected
Нужно указать «)»
Не указана, где это требуется, закрывающаяся круглая скобка.

90
«=» expected
Нужно указать «=»
Нужно указать знак равенства.

91
«:=» expected
Нужно указать «:=»
Требуется использовать операцию присваивания.

92
« or «(.» expected
Нужно «[» or «(.»
Требуется указать квадратную скобку или «(. ».

93
« or «.expected
Нужно «]» or «.)»
Требуется указать квадратную скобку или «.) ».

94
« expected
Нужно «.»
Требуется указать точку. Убедитесь, что тип не используется как переменная или что именем программы не переопределяется важный идентификатор другого модуля.

95
«..» expected
Нужно «..»
Требуется указать точки. Там, где это нужно, не указан диапазон.

96
Too many variables
Слишком много переменных
Общий размер глобальных переменных, описанных в программе или программном модуле, не может превышать 64 Кбайт.

Размер локальных переменных, описанных в программе или функции, не может превышать 64 Кбайт.

97
Invalid for control variable
Недопустимая управляющая переменная оператора for
Управляющая переменная оператора for должна быть переменной перечисляемого типа, определенной в разделе описаний текущей подпрограммы.

98
Integer variable expected
Нужна переменная целого типа
Предшествующая переменная должна иметь тип integer.

99
Files are not allowed here
Здесь не допускаются файлы
Типизированная константа не может иметь файловый тип.

100
String length mismatch
Несоответствие длины
Длина строковой константы не соответствует количеству элементов символьного массива.

101
Invalid ordering of fields
Неверный порядок полей
Поля в константе типа «запись» должны указываться в порядке их описания.

102
String constant expected
Нужна константа строкового типа
 

103
Integer or real variable expected
Нужна переменная типа integer или real
Предшествующая переменная должна иметь целый или вещественный тип.

104
Character expression
 
Ожидается символьные выражения

105
Compilation aborted
 
Компиляция прервана

106
Error in statement
 
Ошибка в операторе

107
Error in type
 
Ошибка в типе

108
Expected
 
Ожидается имя

109
Invalid floating point operation
 
 Неправильная операция для вещественных операндов

110
 Ordinal variable expected
 
Ожидается переменная целого или символьного типа

111
 Too many symbols 
 
Слишком много символов

112
Undefined type
 
Неопределенный тип

113
Abnormal program termination
 
Ненормальное окончание программы

114
Ctrl-Break to quit
 
нажмите CTRL и Break для входа

115
Disk is write-protected
 
Диск защищен от записи

116
Disk read error
 
Ошибка записи на диск

117
Disk write error
 
Ошибка записи на диск

118
Drive not ready
 
дисковод не готов (нет дискеты)

119
Error on execute 
 
Ошибка исполнения

120
Floating point overflow
 
Вещественное переполнение

121
Hardware failure
 
Ошибка оборудования

122
Heap overflow error
 
Не хватает основной памяти

123
I/O checking
 
Ошибка ввода/вывода

124
Invalid Breakpoint
 
Неправильная точка останова

125
Invalid format specifier
 
Неправильный формат

126
No debug info
 
Не задана информация для отладки

127
Not enough memory
 
Не хватает памяти

128
Press any key
 
Нажмите любую клавишу

129
Program terminated
 
Исполнение программы прекращено

130
Range check error
 
Выход индекса за пределы массива

131
Runtime error
 
Ошибка во время исполнения

132
Stack overflow error
 
Ошибка по переполнению стека

133
Too many breakpoints
 
Слишком много точек останова

134
Type EXIT to return to Turbo Pascal
 
Введите Exit для возврата в Турбо Паскаль

135
User Break
 
Пользователь прервал исполнение программы



العربية (ar)




English (en)

español (es)

suomi (fi)
français (fr)



日本語 (ja)






русский (ru)






中文(中国大陆)‎ (zh_CN)
中文(台灣)‎ (zh_TW)

Введение

Каждый программист должен знать, как работать с файлами. Файлы используются для сохранения данных, т. е. в качестве хранилища данных, таким образом, что они могут быть получены в любой момент, без их воссоздания. Файлы можно использовать для сохранения пользовательских настроек, журналов ошибок, измерение или вычисление результатов, и многое другое. В данном разделе описываются основы использования файлов.

Процедурный стиль

Это довольно старый стиль, использующейся ещё во времена, когда Pascal не был объектно-ориентированным языком. Суть его в том, что задается тип файла, определяющий, какие будут храниться в нем данные. Для этого, используется конструкция вида: file of <тип данных>, где <тип данных> — название типа, который хранит в себе файл. Помимо стандартных типов (integer, extended, char и т.д.), существует особый тип — TextFile. Он определят, что каждая строка заканчивается специальным(ми) символом(ами) конца строки (См. LineEnding). Эти файлы могут быть открыты и отредактированы внутри среды Lazarus или в любом другом текстовом редакторе.

Ниже представлены примеры создания собственных типов файлов:

...
type
  TIntegerFile  = file of integer;  // Позволяет писать только целые числа в файл
  TExtendedFile = file of extended; // Позволяет писать только дробные цифры в файл
  TCharFile     = file of char;     // Позволяет писать только одиночные символы в файл

Обработка ошибок ввода/вывода

Параметр компилятора обработки ошибок ввода/вывода указывает, как должна вести себя программа при возникновении ошибки в процессе работы с файлами: вызвать исключение или хранить результат операции ввода/вывода в специальной переменной IOResult.

Это задаётся с помощью специальной директивы компилятора:

{$I+} // В случаи ошибки будет вызвано исключение EInOutError (по умолчанию)
{$I-} // Подавлять ошибки ввода-вывода: проверьте переменную IOResult для получения кода ошибки.

В случаи подавления ошибок ввода-вывода ({$I-}) результат операции с файлом будет храниться в переменной IOResult типа cardinal (числовой тип). Каждое число, хранимое в IOResult определяет тип возникшей ошибки(подробнее: [1]).

Процедуры работы с файлами

Эти процедуры и функции находятся в модуле system. Для более подробной информации смотрите документацию FPC:

ссылка на модуль 'System'.
  • AssignFile (не допускайте использование процедуры Assign) — Связывает переменную с файлом
  • Append — Открывает существующий файл для записи данных в конец и их редактирования
  • BlockRead — Чтение данных из не типизированного файла в память
  • BlockWrite — Запись данных из памяти в не типизированный файл
  • CloseFile (не допускайте использование процедуры Close) — Закрыть открытый файл
  • EOF — Проверка наличия конца файла
  • Erase — Стереть файл с диска
  • FilePos — Получить позицию в файле
  • FileSize — Получить размер файла
  • Flush — Записать файловый буфер на диск
  • IOResult — Возвращает результат последней операции вводавывода
  • Read — Считать из текстового файла
  • ReadLn — Считать из текстового файла и перейти к следующей строке
  • Reset — Открыть файл для чтения
  • Rewrite — Создать и открыть файл для записи
  • Seek — Изменить позицию в файле
  • SeekEOF — Переместить позицию в файле в его конец
  • SeekEOLn — Переместить позицию в файле в конец строки
  • Truncate — Удалить все данные, после текущей позиции
  • Write — Записать переменную в файл
  • WriteLn — Записать переменную в текстовый файл и перейти к новой строке

Пример

Пример работы с текстовым файлом (тип TextFile):

program CreateFile;

uses
 Sysutils;

const
  C_FNAME = 'textfile.txt';

var
  tfOut: TextFile;

begin
  // Связываем имя файла с переменной
  AssignFile(tfOut, C_FNAME);

  // Использовать исключение для перехвата ошибок (это по умолчанию и указывать не обязательно)
  {$I+}

  // Для обработки исключений, используем блок try/except
  try
    // Создать файл, записать текст и закрыть его.
    rewrite(tfOut);

    writeln(tfOut, 'Пример текстового файла!');
    writeln(tfOut, 'Пример записи числа: ', 42);

    CloseFile(tfOut);

  except
    // Если ошибка - отобразить её
    on E: EInOutError do
      writeln('Ошибка обработки файла. Детали: ', E.ClassName, '/', E.Message);
  end;

  // Выводим результат операции и ожидаем нажатие Enter
  writeln('Файл ', C_FNAME, ' создан. Нажмите ВВОД для выхода.');
  readln;
end.

Теперь откройте файл в любом текстовом редакторе и вы увидите, что пример текста, записан в нем!
Вы можете проверить работу обработки ошибок, установив атрибут файла «только для чтения» и снова запустив программу.

Обратите внимание, что в примере используется блок try/except. Данный способ позволяет выполнять несколько операций с файлами и использовать обработку исключений.
Вы также можете использовать режим {$I-}, но тогда вам придется проверять переменную IOResult после каждой операции с файлами для контроля ошибок.

Ниже приведен пример записи текста в конец файла:

program AppendToFile;

uses
 Sysutils;

const
  C_FNAME = 'textfile.txt';

var
  tfOut: TextFile;

begin
  // Связываем имя файла с переменной
  AssignFile(tfOut, C_FNAME);

  // Для обработки исключений, используем блок try/except
  try
    // Открыть файл для записи в конец, записать текст и закрыть его.
    append(tfOut);

    writeln(tfOut, 'Ещё пример текстового файла!');
    writeln(tfOut, 'Результат 6 * 7 = ', 6 * 7);

    CloseFile(tfOut);

  except
    on E: EInOutError do
     writeln('Ошибка обработки файла. Детали: ', E.Message);
  end;

  // Выводим результат операции и ожидаем нажатие Enter
  writeln('Файл ', C_FNAME, ' возможно содержит больше текста. Нажмите ВВОД для выхода.');
  readln;
end.

Чтение текстового файла:

program ReadFile;

uses
 Sysutils;

const
  C_FNAME = 'textfile.txt';

var
  tfIn: TextFile;
  s: string;

begin
  // Вывод некой информации
  writeln('Чтение содержимого файла: ', C_FNAME);
  writeln('=========================================');

  // Связываем имя файла с переменной
  AssignFile(tfIn, C_FNAME);

  // Для обработки исключений, используем блок try/except
  try
    // Открыть файл для чтения
    reset(tfIn);

    // Считываем строки, пока не закончится файл
    while not eof(tfIn) do
    begin
      readln(tfIn, s);
      writeln(s);
    end;

    // Готово. Закрываем файл.
    CloseFile(tfIn);

  except
    on E: EInOutError do
     writeln('Ошибка обработки файла. Детали: ', E.Message);
  end;

  // Выводим результат операции и ожидаем нажатие Enter
  writeln('=========================================');
  writeln('Файл ', C_FNAME, ' считан. Нажмите ВВОД для выхода.');
  readln;
end.

Объектный стиль

В дополнение к старому методу обработки файлов, упомянутому выше процедурному стилю, существует новая система, которая использует концепции потоков (данных) на более высоком уровне абстракции. Это означает, что данные могут считываться или записываться в любом месте (диск, память, аппаратные порты и т. д.) через один универсальный интерфейс.

Кроме того, большинство классов обработки строк, могут иметь возможность загружать/сохранять содержимое из/в файл. Эти методы обычно называются SaveToFile и LoadFromFile.

Двоичные файлы

Для прямого доступа к файлам, так же удобно использовать класс TFileStream. Этот класс представляет собой инкапсуляцию системных процедур FileOpen, FileCreate, FileRead, FileWrite, FileSeek и FileClose, расположенных в модуле SysUtils.

Процедуры ввода-вывода

В приведенном ниже примере обратите внимание, что обработка действий с файлом, расположена внутри блока try..except. Поэтому обработка ошибок происходит так же, как в случаи использования процедур работы с файлами в классическом Pascal.

program WriteBinaryData;
{$mode objfpc}

uses
  Classes, Sysutils;

const
  C_FNAME = 'binarydata.bin';

var
  fsOut    : TFileStream;
  ChrBuffer: array[0..2] of char;

begin
  // Создать некоторые случайные данные, которые будут храниться в файле
  ChrBuffer[0] := 'A';
  ChrBuffer[1] := 'B';
  ChrBuffer[2] := 'C';

  // Перехват ошибок в случае, если файл не может быть создан
  try
    // Создать экземпляр потока файла, записать в него данные и уничтожить его, чтобы предотвратить утечки памяти
    fsOut := TFileStream.Create( C_FNAME, fmCreate);
    fsOut.Write(ChrBuffer, sizeof(ChrBuffer));
    fsOut.Free;


  // Обработка ошибки
  except
    on E:Exception do
      writeln('Файл ', C_FNAME, ' не создан, так как: ', E.Message);
  end;

  // Выводим результат операции
  writeln('Файл ', C_FNAME, ' создан. Нажмите ВВОД для выхода.');
  //Ожидаем нажатие Enter
  readln;
end.

Вы так же можете загрузить весь файл в память, если его размер существенно меньше, чем имеющийся системной памяти. Если файл превышает размер системной памяти, то ваша операционная система начнет использовать файл подкачки, снижая скорость работы с файлом.

program ReadBinaryDataInMemoryForAppend;
{$mode objfpc}

uses
  Classes, Sysutils;

const
  C_FNAME = 'binarydata.bin';

var
  msApp: TMemoryStream;

begin
  // Создаем поток в памяти
  msApp := TMemoryStream.Create;

  // Перехват ошибок в случае их возникновения
  try
    // Считать данные в память
    msApp.LoadFromFile(C_FNAME);

    // Переходим в конец данных
    msApp.Seek(0, soEnd);

    // Запись неких данных в поток
    msApp.WriteByte(68);
    msApp.WriteAnsiString('Некий текст');
    msApp.WriteDWord(671202);

    // Запись данных на диск (файл будет перезаписан)
    msApp.SaveToFile(C_FNAME);

  // Обработка ошибки
  except
    on E:Exception do
      writeln('Файл ', C_FNAME, ' не удалось считать или записать, так как: ', E.Message);
  end;

  // Освобождаем память и уничтожаем объект
  msApp.Free;

  // Выводим результат операции и ожидаем нажатие Enter
  writeln('Файл ', C_FNAME, ' дописан. Нажмите ВВОД для выхода.');
  readln;
end.

Для работы с файлами большого объёма, рекомендуется использовать буфер, например в 4096 байт.

var
  TotalBytesRead, BytesRead : Int64;
  Buffer : array [0..4095] of byte;  // или, array [0..4095] of char
  FileStream : TFileStream;

try
  FileStream := TFileStream.Create;
  FileStream.Position := 0;  // Установим позицию в начало файла
  while TotalBytesRead <= FileStream.Size do  // Пока объем считанных данных меньше размера файла
  begin
    BytesRead := FileStream.Read(Buffer,sizeof(Buffer));  // Считать 4096 байт данных
    inc(TotalBytesRead, BytesRead);                       // Увеличиваем TotalByteRead на размер буфера, т.е. 4096 байт
    // Что-то делаем с буфером данных
  end;

Копирование файла

Теперь,зная методы работы с файлами, мы можем реализовать простую функцию копирования файла, скажем FileCopy.(такой функции нет в FreePascal, хотя Lazarus её имеет copyfile):

program FileCopyDemo;
// Пример функции FileCopy

{$mode objfpc}

uses
  classes;

const
  fSource = 'test.txt';
  fTarget = 'test.bak';

function FileCopy(Source, Target: string): boolean;
// Копируем файл с путем в Source в файл с путем Target.
// Кэшируем весь файл в память.
// В случаи успеха возвращаем true, в случаи ошибки - false.
var
  MemBuffer: TMemoryStream;
begin
  result := false;
  MemBuffer := TMemoryStream.Create;
  try
    MemBuffer.LoadFromFile(Source);
    MemBuffer.SaveToFile(Target); 
    result := true
  except
    //Подавляем исключение; результатом функции является значение false по умолчанию
  end;
  // Очистка
  MemBuffer.Free
end;

// Пример использования
begin
  If FileCopy(fSource, fTarget)
    then writeln('Файл ', fSource, ' скопирован в ', ftarget)
    else writeln('Файл ', fSource, ' не скопирован в ', ftarget);
  readln()
end.

Обработка текстовых файлов (TStringList)

Для текстовых файлов можно использовать класс TStringList, чтобы загрузить весь файл в память и иметь легкий доступ к его строкам. Вы также можете записать StringList обратно в файл:

program StringListDemo;
{$mode objfpc}

uses
  Classes, SysUtils;

const
  C_FNAME = 'textfile.txt';

var
  slInfo: TStringList;

begin
  // Создаем TStringList для обработки текстового файла
  slInfo := TStringList.Create;

  // Для обработки исключений, используем блок try/except
  try
    // Загружаем файл в память
    slInfo.LoadFromFile(C_FNAME);

    // Добавляем некие строки
    slInfo.Add('Некая строка');
    slInfo.Add('Ещё одна строка.');
    slInfo.Add('Всё, хватит.');
    slInfo.Add('Сейчас ' + DateTimeToStr(now));

    // Записать содержимое на диск, заменив исходное содержимое
    slInfo.SaveToFile(C_FNAME);

  except
    // Обработка ошибки
    on E: EInOutError do
      writeln('Произошла ошибка обработки файла. Причина: ', E.Message);
  end;

  // Очистка
  slInfo.Free;

  // Выводим результат операции и ожидаем нажатие Enter
  writeln('Файл ', C_FNAME, ' обновлен. Нажмите ВВОД для выхода.');
  readln;
end.

Демо: сохранить одну строку в файл

Для того, чтобы сохранить одну строку в файл, вы можете воспользоваться процедурой, описанной ниже.

program SaveStringToPathDemo;
{$mode objfpc}

uses
  Classes, sysutils;

const
  C_FNAME = 'textstringtofile.txt';

// SaveStringToFile: функция для хранения строк текста в файле на диске.
//   Если результат функции равен True, то строка была написана
//   Иначе произошла ошибка
function SaveStringToFile(theString, filePath: AnsiString): boolean;
var
  fsOut: TFileStream;
begin
  // По умолчанию результат неудачный
  result := false;

  // Записать данную строку в файл, перехватывая ошибки в процессе записи.
  try
    fsOut := TFileStream.Create(filePath, fmCreate);
    fsOut.Write(theString[1], length(theString));
    fsOut.Free;

    // На данном этапе известно, что запись прошла успешно.
    result := true

  except
    on E:Exception do
      writeln('Строка не записана. Детали: ', E.ClassName, ': ', E.Message);
  end
end;

//
// Основная программа
//
begin
  // Пытаемся сохранить текст в файл и выводим результат операции
  if SaveStringToFile('>> этот текст сохраняется <<', C_FNAME) then
    writeln('Текст успешно записан в файл.')
  else
    writeln('Не удалось сохранить текст в файл.');

  // Ждем нажатия Enter
  readln
end.

Смотрите так же

  • CopyFile — функция Lazarus, которая копирует файл
  • File

7.4 Обработка текстовых файлов в языке Free Pascal

При работе с текстовыми файлами следует учесть следующее:

  1. Действие процедур reset, rewrite, close, rename, erase и функции eof аналогично их действию при работе с компонентными (типизированными) файлами.
  2. Процедуры seek, trunсate и функция filepos не работают с текстовыми файлами.
  3. Можно пользоваться процедурой открытия текстового файла append(f), где f — имя файловой переменной. Эта процедура служит для открытия файла в режиме дозаписи в конец файла. Она применима только к уже физически существующим файлам, открывает и готовит их для добавления информации в конец файла.
  4. Запись и чтение в текстовый файл осуществляются с помощью процедур write, writeln, read, readln следующей структуры:

read ( f, x1, x2, x3,…, xn );

read ( f, x );

readln ( f, x1, x2, x3,…, xn );

readln ( f, x );

write ( f, x1, x2, x3,…, xn );

write ( f, x );

writeln ( f, x1, x2, x3,…, xn );

writeln ( f, x );

В этих операторах f — файловая переменная. В операторах чтения (read, readln) x, x1, x2, x3,…, xn — переменные, в которые происходит чтение из файла. В операторах записи write, writeln x, x1, x2, x3,…, xn — переменные или константы, информация из которых записывается в файл.

Есть ряд особенностей при работе операторов write, writeln, read, readln с текстовыми файлами. Имена переменных могут быть целого, вещественного, символьного и строкового типа. Перед записью данных в текстовый файл с помощью процедуры write происходит их преобразование в тип string. Действие оператора writeln отличается тем, что после указанных переменных и констант в файл записывается символ «конец строки».

При чтении данных из текстового файла с помощью процедур read, readln происходит преобразование из строкового типа к нужному типу данных. Если преобразование невозможно, то генерируется код ошибки, значение которого можно узнать, обратившись к функции IOResult. Компилятор Free Pascal позволяет генерировать код программы в двух режимах: с проверкой корректности ввода-вывода и без неё.

В программу может быть включен ключ режима компиляции. Кроме того, предусмотрен перевод контроля ошибок ввода-вывода из одного состояния в другое:

  • {$I+} — режим проверки ошибок ввода-вывода включён;
  • {$I-} — режим проверки ошибок ввода-вывода отключён.

По умолчанию, как правило, действует режим {$I+}. Можно многократно включать и выключать режимы, создавая области с контролем ввода и без него. Все ключи компиляции описаны в приложении.

При включённом режиме проверки любая ошибка ввода-вывода будет фатальной, программа прервётся, выдав номер ошибки.

Если убрать режим проверки, то при возникновении ошибки ввода-вывода программа не будет останавливаться, а продолжит работу со следующего оператора. Результат операции ввода-вывода будет неопределён.

Для опроса кода ошибки лучше пользоваться специальной функцией IOResult, но необходимо помнить, что опросить её можно только один раз после каждой операции ввода или вывода: она обнуляет своё значение при каждом вызове. IOResult возвращает целое число, соответствующее коду последней ошибки ввода-вывода. Если IOResult=0, то при вводе-выводе ошибок не было, иначе IOResult возвращает код ошибки. Некоторые коды ошибок приведены в табл. 7.9.

Таблица
7.9.
Коды ошибок операций ввода-вывода

Код ошибки Описание
2 файл не найден
3 путь не найден
4 слишком много открытых файлов
5 отказано в доступе
12 неверный режим доступа
15 неправильный номер диска
16 нельзя удалять текущую директорию
100 ошибка при чтении с диска
101 ошибка при записи на диск
102 не применена процедура AssignFile
103 файл не открыт
104 файл не открыт для ввода
105 файл не открыт для вывода
106 неверный номер
150 диск защищён от записи

Рассмотрим несколько практических примеров обработки ошибок ввода-вывода:

  1. При открытии проверить, существует ли заданный файл и возможно ли чтение данных из него.
    assign ( f, ’ abc. dat ’ );
    {$I-}
    reset ( f );
    {$I+}
    if IOResult<>0 then
    writeln ( ’файл не найден или не читается ’ )
    else
    begin
    read ( f,... );
    close ( f );
    end;
    
  2. Проверить, является ли вводимое с клавиатуры число целым.
    var i : integer;
    begin
    {$I-}
    repeat
    write ( ’введите целое число  i ’ );
    readln ( i );
    until ( IOResult =0);
    {$I+}
    {Этот цикл повторяется до тех пор, пока не будет введено целое число.}
    end.
    

При работе с текстовым файлом необходимо помнить специальные правила чтения значений переменных:

  • Когда вводятся числовые значения, два числа считаются разделёнными, если между ними есть хотя бы один пробел, или символ табуляции, или символ конца строки.
  • При вводе строк начало текущей строки идёт сразу за последним, введённым до этого символом. Вводится количество символов, равное объявленной длине строки. Если при чтении встретился символ «конец строки», то работа с этой строкой заканчивается. Сам символ конца строки является разделителем и в переменную никогда не считывается.
  • Процедура readln считывает значения текущей строки файла, курсор переводится в новую строку файла, и дальнейший ввод осуществляется с неё.

В качестве примера работы с текстовыми файлами рассмотрим следующую задачу.

ЗАДАЧА 7.8. В текстовом файле abc.txt находятся матрицы A(N, M ) и B(N, M ) и их размеры. Найти матрицу C = A + B, которую дописать в файл abc.txt.

Сначала создадим текстовый файл abc.txt следующей структуры: в первой строке через пробел хранятся размеры матрицы (числа N и M), затем построчно хранятся матрицы A и B.

Файл abc.txt

Рис.
7.14.
Файл abc.txt

На рис. 7.14 приведён пример файла abc.txt, в котором хранятся матрицы A(4,5) и B(4,5).

Текст консольного приложения решения задачи 7.8 с комментариями приведён ниже.

program Project1;
{$mode objfpc}{$H+}
uses
	Classes, SysUtils
	{ you can add units after this };
var
	f : Text;
	i, j, N,M: word;
	a, b, c : array [ 1.. 1000, 1.. 1000 ] of real;
begin
//Связываем файловую переменную f с файлом на диске.
	AssignFile ( f, ’ abc. t x t ’ );
//Открываем файл в режиме чтения.
	Reset ( f );
//Считываем из первой строки файла abc.txt значения N и M.
	Read( f,N,M);
//Последовательно считываем элементы матрицы А из файла.
	for i :=1 to N do
	for j :=1 to M do
	read ( f, a [ i, j ] );
//Последовательно считываем элементы матрицы B из файла.
	for i :=1 to N do
	for j :=1 to M do
	read ( f, b [ i, j ] );
//Формируем матрицу C=A+B.
	for i :=1 to N do
	for j :=1 to M do
	c [ i, j ] : = a [ i, j ]+b [ i ] [ j ];
//Закрываем файл f.
	CloseFile ( f );
//Открываем файл в режиме дозаписи.
	Append( f );
//Дозапись матрицы C в файл.
	for i :=1 to N do
	begin
		for j :=1 to M do
//Дописываем в файл очередной элемент матрицы и пробел в
//текстовый файл.
		write ( f, c [ i, j ] : 1 : 2, ’   ’ );
//По окончании вывода строки матрицы переходим на новую
//строку в текстовом файле.
		writeln ( f );
	end;
//Закрываем файл.
	CloseFile ( f );
end.

После работы программы файл abc.txt будет примерно таким, как показано на рис. 7.15.

Файл abc.txt после дозаписи матрицы C

Рис.
7.15.
Файл abc.txt после дозаписи матрицы C

Компилятор Турбо Паскаля позволяет генерировать выполнимый код в двух режимах: с проверкой корректности ввода-вывода и без нее. В среде программирования этот режим включается в меню

— 262 —

Options/Compiler/IO-checking. При включении в программу ключ режима компиляции обозначается как

{$I+} — режим проверки включен;

{$I-} — режим отключен.

По умолчанию, как правило, действует режим $I+. Этот ключ компиляции имеет локальную сферу влияния. Можно многократно включать и выключать режим, вставляя в текст программы конструкции {$I+} и {SI-}, тем самым создавая области с контролем ввода-вывода и без него.

При включенном режиме проверки любая ошибка ввода-вывода будет фатальной: программа прервется, выдав номер ошибки. Возможные номера ошибок ввода-вывода находятся в диапазоне от 2 до 200 ( от 2 до 99 — это коды ошибок DOS, от 100 до 149 — ошибки, диагностируемые самой программой, и от 150 до 200 — критические аппаратные ошибки). Расшифровка кодов ошибок с краткими комментариями приведена в табл. 12.6 в конце этого раздела.

Если отключить режим проверки, то при возникновении ошибки ввода-вывода программа уже не будет прерываться, а продолжит работу со следующего оператора. Результат операции ввода-вывода, вызвавшей ошибку, будет неопределен. При этом код ошибки будет сохранен в предопределенной системной переменной InOutRes. Однако для опроса этого кода лучше пользоваться специальной функцией Турбо Паскаля.

Дополнительные функции работы с файлами

Модуль
System

ChDir

Выполняет
смену текущего каталога

MkDir

Создает
подкаталог

RmDir

Удаляет
подкаталог (пустой)

GetDir

Получить
текущий каталог на заданном диске

Модуль
DOS

DiskFree

Число
свободных байтов на диске

DiskSize

Размер
диска в байтах

GetFAttr

Получение
атрибутов неоткрытого файла

SetFAttr

Задание
атрибутов неоткрытого файла

FSplit

Получение
составных частей имени файла

FExpand

Формирование
полного имени файла

FSearch

Поиск
файла в списке католога

FindFirst

Поиск
в указанном или текущем каталоге
первого файла, соответствующего
заданному шаблону и атрибутам

FindNext

Поиск
следующего файла, соответствующего
шаблону и атрибутам, заданным в
последнем обращении к FindFirst

Прототипы
процедур FindFirst
и FindNext
имеют вид:

FindFirst(Path:
String; Attrib: Word; Var SR: SearchRec);

FindNext(Var
SR:
SearchRec);

Для
работы с этими подпрограммами требуются
следующие предопределенные описания:

  1. Константы

Const

ReadOnly
= $01; только
для чтения

Hidden = $02; скрытый

SysFile =
$04; системный (непереносимый)

Volume ID = $08; метка
диска

Directory =
$10; подкаталог

Archive = $20; архивный

AnyFile = $3F; сумма
всех предыдущих

Эти атрибуты можно
складывать или вычитать (из anyfile).

  1. Переменная
    DOSError.
    Она используется для анализа ошибок
    MS
    DOS.
    Значение этой переменной, равное нулю,
    соответствует отсутствию ошибки. Смысл
    некоторых ненулевых кодов следующий:

2
– файл не найден

3
– маршрут не найден

5
– доступ к файлу запрещен

6
– неправильная обработка

8
– недостаточно памяти

10
– неверные установки значений параметров
среды

11
– неправильный формат

18
– файлов нет

При
работе процедуры FindFirst
возможны ошибки с номерами 2 и 18, а при
работе FindNext
– только 18.

3)
Тип

Type

SearchRec
= record

Fill: array[1..21] of byte; {системное поле}

attr: byte; {байт атрибутов}

time: longint; {время
создания}

size: longint; {размер
файла}

name: string[12]; {имя файла}

end;

Поля
переменной этого типа содержат информацию
о последнем файле, найденном с помощью
FindFirst
и FindNext.

Процедура
FindFirst
при заданных имени файла и атрибутах
должна вызываться лишь один раз. Она
записывает в поля переданной ей переменной
SR
типа SearchRec
информацию о первом найденном файле,
удовлетворяющем заданным условиям. Эта
информация в дальнейшем будет
использоваться процедурой FindNext,
которая всегда вызывается после FindFirst
и заполняет поля переменной SR
информацией о следующем найденном
файле.

Контроль
работы этих процедур ведется с помощью
переменной DOSError:
если файла нет, то DOSError<>0.

Обработка ошибок ввода-вывода

Все рассмотренные
ранее программы были написаны так, что
возможные ошибки ввода-вывода
игнорировались. Однако реально это не
так. В ТР стандартной реакцией на наличие
ошибок в вашей программе является
следующее: ваша программа аварийно
завершается и выдает сообщение:

Runtime
error
<номер> <смещение>.

Такое сообщение
буде полезно вам как программистам при
поиске места и причины ошибки в программе.
Однако показывать такое сообщение
пользователю вашей программы будет не
совсем дружественно.

Для того, чтобы
ваша программа из-за ошибки аварийно
не завершалась и для того, чтобы не
пугать пользователей непонятными им
сообщениями, вам необходимо перехватить
инициативу по обработке ошибок у системы
и писать собственные обработчики ошибок
стадии выполнения (исключений). Традиционно
обработка ошибок в программах
осуществляется с помощью установки
флагов

случае ошибки) и последующего анализа
этих флагов. Для перехвата ошибок
ввода-вывода на Паскале необходимо:

  1. Специальным
    образом оформить каждый фрагмент
    программы, которые потенциально могут
    вызвать ошибку. К таким фрагментам
    относятся — открытие файда, чтение из
    файла, запись в файл.

  2. При наличии такого
    специального оформления необходимо
    по завершению фрагмента проверить:
    была ошибка или нет. Если была, то вы
    должны выполнить ее обработку (хотя бы
    вывести свое сообщение).

Пример:

reset(f);

при попытки открытия
файла физически файл может отсутствовать
на диске. Этот оператор в программе
является потенциальным источником
ошибки.

Специальное
оформление потенциально опасных участков
программы состоит в том, что
вы должны
как бы завернуть каждый опасный участок
в специальный код: выше
и ниже опасного фрагмента программы

вы должны
расположить две директивы компилятора:

{$I-}
— указывает на то, что необходимо
отключить системный контроль ошибок

reset(f);

{$I+}
— указывает на то, что необходимо включить
системный контроль ошибок

При наличии
директивы компилятора {$I-}
даже при наличии ошибок в/в программа
аварийно не завершается и ход выполнения
программы не нарушается.

Замечание:
По умолчанию действует директива {$i+}.

Контроль ошибок
в/в производится с помощью функции
IOResult
. Если ошибка имеет место, то значение
этой функции отлично от нуля. Поэтому
типичный шаблон обработки ошибки
ввода-вывода имеет вид:

If
IOResult
<> 0 Then
{обработка ошибки};

Обычно обработка
ошибки сводится к сообщению об ошибки
и завершению вашей программы (с помощью
процедуры HALT
или EXIT).

Замечание:
Опросить функцию IOResult
можно лишь
один раз

после каждой операции ввода-вывода,
т.к. она обнуляет свое значение перед
каждым вызовом. Поэтому целесообразно
сохранять значение, возвращенное
IOResult,
в специально выделенной переменной.

Пример.

{$I-}

reset(f);

{$I+}

If
IOResult <> 0

then
begin

Writeln(‘Ошибка
открытия
файла’);

Halt;

end;

Соседние файлы в папке WORD

  • #

    15.04.2015439.06 Кб306.docx

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

В этом разделе обсуждаются разнообразные,
важные в практическом отношении, примемы
программирования.

1. Обработка ошибок ввода-вывода

В одном из предыдущих разделов был рассмотрен
фрагмент программы, демонстрирующий контроль за
вводимой информацией и не допускающий ввод
некорректных данных. Повторим здесь этот
фрагмент:

PROGRAM CheckInputData_1;
USES CRT;
VAR
  x : Real;
BEGIN
  ClrScr;
  REPEAT
    Write(‘Введите число в интервале от 0 до
100: ‘);
    Read(x);
    if not((x>=0)and(x<=100))
      then writeln(‘Ошибка при вводе
числа!’);
  UNTIL (x>=0)and(x<=100);
  …
  …
END.

Приведенная программа не допускает ввода числа
меньше нуля или больше ста. А что произойдет, если
вместо числа ввести (случайно) какой-либо иной
символ? Скорее всего это приведет к
возникновению фатальной (т.е. ведущий к
прекращению работы программы) ошибки
ввода-вывода:
Error 106: Invalid numeric format. Этого можно избежать, если
воспользоваться приемом, описанным ниже.

Сначала немного теории. Компилятор
языка Турбо Паскаль позволяет генерировать
выполнимый (машинный
) код в
дух режимах: с проверкой корректности
ввода-вывода и без нее. В среде программирования
этот режим включается в меню
Options – Compiler –
I/O Checking
. Режимом компиляции
можно управлять непосредственно в тексте
программы с помощью ключа компиляции
$I

{$I+} – режим проверки включен;
{$I-} – режим отключен.

По умолчанию, как правило, действует режим $I+. Этот ключ компиляции имеет
локальную сферу влияния. Можно многократно
включать и выключать режим, вставляя в текст
программы конструкции
{$I+} и {$I-},
тем самым создавая области с
контролем ввода-вывода и без него.

При включенном режиме проверки любая ошибка
ввода-вывода будет фатальной: программа
прервется, выдав номер ошибки. Если отключить
режим проверки, то при возникновении ошибки
ввода-вывода программа уже не будет прерываться,
а продолжит работу со следующего оператора.
Результат операции ввода-вывода, вызвавший
ошибку, будет неопределен. При этом код ошибки
будет сохранен и в последствии его можно узнать с
помощью специальной функции
IOResult. Эта функция возвращает целое число,
соответствующее коду последней ошибки
ввода-вывода. Если же операция ввода-вывода
прошла без сбоев, то функция вернет значение
0. Опросить функцию IOResult можно только один раз, ибо она
обнуляет свое значение при каждом вызове. Обычно
это обходят запоминанием значения функции в
какой-либо переменной.

Итак, для того чтобы рассмотренная выше
программа не давала сбоев при вводе, необходимо
отключить режим проверки ошибок
ввода-вывода на время работы
процедуры
Read, а затем
проанализировать значение функции
IOResult:

PROGRAM CheckInputData_2;
USES CRT;
VAR
    x : Real;

  err : Integer;
BEGIN
  ClrScr;
  REPEAT
  Write(‘Введите число в интервале от 0 до 100: ‘);

  {$I-}
    Read(x);

  {$I+}
  err := IOResult;
  if not((x>=0) and (x<=100)) or (err<>0)
    then writeln(‘Ошибка при вводе числа!’);
  UNTIL (x>=0) and (x<=100) and (err=0);
  …
  …
END.

Возможность управлять режимом обработки
ошибок и наличие функции
IOResult
позволяет писать программы, никогда не дающие
сбоев при вводе или выводе данных и при работе с
файлами.

2. Управление программой с помощью меню

При написании больших и не очень больших
программ, выполняющих различные действия,
полезно сделать так, чтобы у пользователя была
возможность выбрать тот или иной режим работы с
программой. Например, если программа направлена
на решение некоторой физической задачи, то она
может иметь по крайней мере три режима работы: 1)
ввод и модификация параметров задачи; 2)
собственно вычисления; 3) представление
результатов (например, построение графиков
рассчитанных зависимостей). Организация выбора
режимов работы может быть сделана с помощью меню.
Меню, в данном случае, — это перечень команд или
режимов работы, которые можно выбрать тем или
иным способом. В простейшем случае, меню может
быть представлено на экране нумерованным
списком. Выбор того или иного пункта
меню осуществляется вводом числа,
соответствующего номеру пункта. В более сложных
случаях выбор пункта меню может осуществляться
перемещением (с помощью клавиатуры или “мыши”)
курсора-подсветки, а активизация выбранного
пункта – нажатием на клавишу “
Enter” или щелчком кнопки мыши.

Рассмотрим в качестве примера структуру
программы, содержащей простейшее меню в виде
нумерованного списка.

PROGRAM Example_of_Menu;
USES CRT;
VAR Ch : Char;

PROCEDURE ChangeParam;
BEGIN
END;



PROCEDURE Calculation;
BEGIN
END;


PROCEDURE ShowGraphic;
BEGIN
END;

BEGIN
  repeat
    ClrScr;
    GotoXY(30,2);
    Write(‘НАЗВАНИЕ ПРОГРАММЫ’);
    GotoXY(28,6);
    Write(‘- Меню режимов работы -’);
    GotoXY(20,8);  Write(‘1 — Ввод и изменение
параметров’);
    GotoXY(20,10); Write(‘2 — Вычисление’);
    GotoXY(20,12); Write(‘3 — Построение графика’);
    GotoXY(20,14); Write(‘4 — Завершение работы’);
    GotoXY(15,18);
    Write(‘Для выбора режима работы нажмите
клавишу [1..4]: ’);
    repeat
      Ch := ReadKey;
    until Ch in [’1’,’2’,’3’,’4’];
    case Ch of
     ‘1’ : ChangeParam;
     ‘2’ : Calculation;
     ’3’ : ShowGraphic;
     ’4’ : Halt;


    end; {case}
  until false;

END.

Права на материал принадлежат их авторам
Вернуться на главную страницу

раздел
const
?

раздел
type
?

раздел
begin … end ?

раздел
program ?

  1. Какие
    из комментариев неправильны :

{Программа
для вычисления}

(*
Это тоже комментарий *)

{{
Комментарий в комментарии }}

(*
{ Другой вариант }*)

{
(* Следующий
вариант
*) }

(*
(* Возможный
вариант
*) *)

  1. Для
    чего используется слово uses
    ?

  1. такого
    слова нет в языке Паскаль

  2. это
    пользовательский идентификатор

  3. с
    его помощью подключают стандартные
    модули

  4. это
    стандартная константа

  5. это
    описание процедуры

  1. В
    разделе процедур и функций описываются
    :

    1. только
      стандартные процедуры

    2. только
      пользовательские процедуры

    3. и
      стандартные, и пользовательские

    4. такого
      раздела в программе не может быть

  1. Наберите
    и откомпилируйте простейшую программу
    :

Program
MyProg;

begin

Writeln
(5*6);

Writeln(‘
Привет
‘);

end.

Каков
будет результат ее выполнения ?

  1. Где
    ошибки (их три) в следующей программе
    ?

Program
Ошибки;

begin

Summa
:= 6+8;

end;

  1. Где
    ошибки (их три) в следующей программе
    ?

Program
Ошибки1;

{{
Программа с ошибками }}

begin

var
X: integer;

X:=
6+8;

Write
(X);

end.

  1. Где
    ошибка в следующей программе ?

Program
Oshibka;

uses
;

{(*
Программа с ошибкой *)}

begin

end.

  1. Где
    ошибка в следующей программе ?

Program
Summa;

var
X, Y, Сумма
: integer;

begin

Writeln(‘
Введите
Х
‘);

Readln
(X);

Writeln(‘
Введите
Y ‘);

Readln
(Y);

Сумма:=Х+Y;

Writeln(Сумма);

end.

Глава 3

Операторы языка
ПАСКАЛЬ

3.1 ВВОД-ВЫВОД
ДАННЫХ

Часто
первыми действиями, выполняемыми
программой, являются действия по вводу
и выводу данных.

В
вод
данных
– передача информации от
внешнего носителя в оперативную память
для обработки.

Основные
устройства ввода — клавиатура и дисковый
файл. Программа получает входные данные
из файла Input и помещает
результат обработки в файл Output.
Стандартно файлу Input
назначена клавиатура, файлу Output
– экран терминала.

Для
ввода и вывода данных в языке Паскаль
предусмотрены следующие процедуры
ввода-вывода: Read, Readln, Write, Writeln. Часто
эти процедуры называют операторами.

3.1.1 Процедура
чтения Read

Обеспечивает
ввод числовых данных, символов, строк
для их последующей обработки.

Формат:

Read
(а1, а2, а3, …,а
n)
;

Readln;

Readln
(а1, а2, а3, …,а
n)
;

где
а1, а2, а3, …,аn
– переменные допустимых типов
данных integer, real, char, string.

Третий
оператор эквивалентен первым двум,
выполненным последовательно. Значения
набираются на клавиатуре через пробел
и высвечиваются на экране. После набора
данных для одной процедуры нажимается
Enter.

Значения
переменных должны вводиться в строгом
соответствии с синтаксисом языка
Паскаль. Если элемент ввода типа integer,
а набирается с клавиатуры значение
типа char – возникает ошибка
ввода-вывода.

Пример:

Var
x : integer;

y
: real;

z
: boolean;

…..

Read
(x, y, z) ;

С
клавиатуры можно ввести

32
-1.8
true

Типовые
ошибки при вводе:

3.2
-1.8 true {В
качестве х введено
действительное значение}

х
= 32 {В качестве х
введено символьное значение}

32
-1,8 true {В
качестве у введено
символьное значение}

В
случае несоответствия типа введенных
данных типу переменной, значение которой
вводится с клавиатуры, программа
завершает работу и на экране выводится
сообщение об ошибке ввода-вывода. Если
программа запущена из среды Turbo Pascal –
Error 106 Invalid numeric format
(Неверный числовой формат).

Если
в программе несколько процедур Read,
данные вводятся потоком, т.е. после
считывания значений переменных для
одной процедуры, данные для следующей
процедуры набираются в той же строке.

Например,

Read
(x, y);

Read
(z);

С
клавиатуры можно ввести данные через
пробел на одной строке

32
-1.8
true

Процедура
чтения Readln аналогична Read.
Единственное отличие состоит в том,
что если в программе несколько процедур
Readln, то после считывания значений
переменных для одной процедуры Readln,
данные для следующей процедуры будут
считываться с начала новой строки.

Например,

Readln(x,
y);

Read(z);

С
клавиатуры ввели данные через пробел
на одной строке

32
-1.8
true {Значение
переменной z
считываться не будет}

Инструкция
Readln при вводе с клавиатуры
предпочтительней Read, т.к. полностью
освобождает буфер клавиатуры – рабочую
область памяти, в которой временно
хранятся введенные с клавиатуры символы.
Инструкция Read оставляет в буфере
клавиатуры код клавиши Enter, которой
завершает процесс.

Процедура
Readln без переменных обычно записывается
в конце программы и служит для создания
паузы, которая длится до нажатия клавиши
Enter. В противном случае по окончании
программы окно с текстом программы
закроет экран с полученным результатом.

3.1.2 Процедура
записи Write

В
ывод

данных – передача информации после
обработки из оперативной памяти на
внешнее устройство (экран, принтер,
файл на диске).

Обеспечивает
вывод числовых данных, символов, строк
и булевских значений.

Формат:

Write
(а1, а2, а3, …,а
n)
;

Writeln;

Writeln
(а1, а2, а3, …,а
n)
;

где
а1, а2, а3, …,аn
– выражение типа integer, byte, real,
char, boolean.

Инструкции
Write и Writeln предназначены для
вывода констант различных типов,
значений переменных или выражений.
Число параметров – произвольное. Данные
выводятся на экран.

Из
констант наиболее часто выводятся
строки текста (строковые константы
заключаются в апострофы). Если в
конструкции вывода записано выражение,
оно сначала будет вычислено, а затем
выполнен вывод полученного результата.

Процедура
Writeln аналогична Write, отличие
заключается в том, что после вывода
последней переменной из списка, курсор
автоматически переходит в начало новой
строки. Инструкция Writeln без параметров
переводит курсор в начало следующей
строки, что позволяет, например, отделять
результаты работы программы друг от
друга пустыми строками.

ФОРМАТ ВЫВОДА

В
операторах вывода имеется возможность
записи выражения, определяющего ширину
поля вывода для каждой выводимой
переменной или константы:

Write(y1:n:m,
y2:n:m, …);

Writeln(y1:n:m,
y2:n:m, …);

где
y1,
y2,…
— выражение, переменная или
константа;

n
– определяет общую ширину поля
вывода;

m
– определяет
место под дробную часть.

Если
заданное n
мало, при выводе ширина поля будет
увеличена, если мало m
– то производится округление.

Кроме
того, в операторах вывода можно задавать
количество пробелов. Для этого необходимо
записать оператор вывода в виде:

Write
(‘ ‘ :
q);

где
q
— константа целого типа, указывающая
число пробелов.

Примеры:

  • x
    целое число

х
– выводится десятичное представление
величины х, начиная
с позиции расположения курсора

Значение
x

Выражение

Результат

123

Write(x)

123

896

Write(x,x)

896896

х
:
n
– выводится десятичное представление
величины х в крайние
правые позиции поля шириной n

Значение
x

Выражение

Результат

123

Write(x:5)

_
_ 123

4

Write(x*х:7)

_
_ _ _ _16

  • R
    вещественное
    число

R
– в поле шириной 16 символов выводится
десятичное представление величины R
в формате с плавающей точкой:

±
#.# # # # # # # # # # E ± # #

Значение
R

Выражение

Результат

123.432

Write(R)

_
1.2343200000Е+02

-0.25

Write(R)


2.5000000000Е-01

200

Write(R/2)

_
1.0000000000Е+02

R
:
n
– в крайние правые позиции поля
шириной n
символов выводится десятичное
представление величины R
в формате с плавающей точкой (минимальная
длина поля вывода 8 символов для
отрицательного значения и 7 символов
для положительного значения R,
после десятичной точки выводится по
крайней мере одна цифра):

Значение
R

Выражение

Результат

123.432

Write(R:12)

1.234320Е+02

-0.25

Write(R:9)

-2.50Е-01

R
:
n:
m
– в крайние правые позиции поля
шириной n
символов выводится десятичное
представление величины R
в формате с фиксированной точкой,
после десятичной точки выводится m
цифр, представляющих дробную часть.
Если m=0,
ни десятичная точка, ни дробная часть
не выводятся.

Значение
R

Выражение

Результат

123.432

Write(R:8:4)

123.4320

-0.25

Write(R:7:1)

_
_ _- 0.3

200

Write(R:3:0)

200

  • Ch
    – выражение символьного типа

Ch
– начиная с ткущей позиции курсора
выводится значение Ch

Значение
Ch

Выражение

Результат

‘123’

Write(Ch)

123

‘No’

Write(Ch)

No

‘?!’

Write(Ch,
Ch)

?!?!

Ch
:
n
– в крайние правые позиции поля
шириной n
символов выводится значение Ch

Значение
Ch

Выражение

Результат

‘123’

Write(Ch:5)

_
_ 123

‘?!’

Write(Ch:3,
Ch:5)

_
?! _ _ _?!

  • S
    – выражение строкового типа

S
– начиная с позиции расположения
курсора выводится значение S

Значение
S

Выражение

Результат

‘DAY
NEDELY’

Write(S)

DAY
NEDELY

‘No’

Write(S,
S)

NoNo

S
:
n
– в крайние правые позиции поля
шириной n
символов выводится значение S

Значение
S

Выражение

Результат

‘DAY
NEDELY’’

Write(S:12)

_
_DAY NEDELY

‘No’

Write(S:3,
S:5)

_No
_ _ _ No

  • В
    – выражение логического типа

В
– начиная с текущей позиции курсора
значение В выводится
True
или False

Значение
В

Выражение

Результат

True

Write(В)

True

False

Write(В,
not В)

FalseTrue

В
:
n
– в крайние правые позиции поля
шириной n
символов выводится результат True
или False булевского
выражения В

Значение
В

Выражение

Результат

True

Write(В:5)

_
True

False

Write(В:6,
not В:5)

_
False_ True

Пример
программы с использованием Write:

Var
A: integer;

B,
C, D: real;

begin

А:=2;
В:=5.8;

Write(A:3,’
’:2); Writeln(B:4:2);

C:=A+B;

D:=A*B;

Writeln;

Writeln(‘Сумма
‘, ‘ C=‘,
C:3:1);

Writeln(‘Произведение
‘, ‘ D=‘, D);

end.

Результат
выполнения:

_
_ 2_ _5.80

Сумма
C=5.8

Произведение
D=1.1600000000Е+01

3.2 ОПЕРАТОРЫ

Основная
часть программы на языке Паскаль
представляет собой последовательность
операторов, разделенных точкой с
запятой.

О
ператором

называется предложение языка
программирования, задающее полное
описание некоторого действия, которое
необходимо выполнить.

Операторы
языка Паскаль можно разделить на простые
и структурные.

Операторы,
не содержащие никаких других операторов,
называются простыми:

  • оператор
    присваивания

  • оператор
    безусловного перехода

  • оператор
    вызова процедуры

  • пустой
    оператор

Структурные
(сложные) – представляют собой
конструкции, содержащие простые
операторы.

3.2.1 Простые
операторы

Неописанная переменная

begin
  S := 1; // Неизвестное имя S
end.

Все используемые переменные должны быть предварительно описаны с помощью ключевого слова var (внутри блока begin/end или, что обычно хуже, в разделе описаний вначале программы).

Отсутствующая ;

begin
  var S: integer 
  S := 1;         // Компилятор здесь скажет: Ожидалась ; — имеется ввиду предыдущая строка!
end.
begin
  var S := 1 
  S := S + 1  // Аналогично: проблема на предыдущей строке, а на текущей нет, потому что после неё идёт end.
end.

Очень частая ошибка у начинающих. Курсор, как правило, позиционируется в начале следующей строки.

Несовместимость типов при присваивании

begin
  var S: integer := 1.3; // Нельзя преобразовать тип real к integer
end.

Безболезненно можно присваивать только данные одного типа. Если данные — разных типов, то в редких случаях можно преобразовать данные одного типа в данные другого. Например, целое можно преобразовать в вещественное, а символ — в строку. Обратные преобразования не допускаются.

Чтобы не ошибаться в подобных простых случаях в Паскале есть следующая краткая форма объявления и инициализации переменной:

begin
  var S := 1.3; // Тип real будет выведен компилятором автоматически
end.

Отсутствие закрывающего апострофа литеральной строки

begin
  var x := 2;   // x получает тип integer
  var y := 3;   // y получает тип integer
  writeln('Результат сложения равен =, x + y); // Не хватает закрывающего апострофа
end.

Закрыть апостроф надо на той же строке, где расположен открывающий апостроф

Ошибки расстановки запятых и апострофов при выводе строк и выражений

begin
  var x := 2;   // x получает тип integer
  var y := 3;   // y получает тип integer
  writeln(x, '+,' y, '=', x+y); // Неверная расстановка запятых и апострофов
end.

Слишком много запятых и апострофов рядом, потому начинающие часто путаются :)
Надо уяснить правила:

  • запятые разделяют разные элементы вывода
  • все, что находится в апострофах, будет выведено на экран без изменений

Ошибка ввода

begin
  var x: integer;
  read(x); // введите блаблабла и посмотрите, что получится
end.

Это — ошибка во время выполнения. Программа пытается преобразовать введенную строку в число, не может это сделать и завершается с ошибкой.

Аналогичный фрагмент в более современном и предпочтительном синтаксисе:

begin
  var x := ReadInteger;
end.

Ошибка неинициализированной переменной

begin
  var x: integer;
  // Забыли инициализировать или ввести x
  var r := x * x;  // r получает тип integer
  writeln('Квадрат числа ', x, ' = ', r);
end.

Перед использованием любую переменную надо ввести или присвоить ей начальное значение. Это действие называется инициализацией переменной.

Деление на 0

begin
  var x := 0;
  var c := 666 div x; // Здесь происходит деление на 0
end.

Если во время выполнения программа выполнит деление на 0, то она завершится с ошибкой.

Корень из отрицательного числа

begin
  writeln(sqrt(-1)); // Корень из отрицательного числа 
end.

В обычном Паскале возникает ошибка времени выполнения.
В PascalABC.NET выводится NaN — Not a Number

Ссылки

  • Программы для начинающих
  • Сайт PascalABC.NET: Программы и алгоритмы для начинающих

  • Ошибка ввода проверьте введенную информацию варфрейм
  • Ошибка ввода полиса 16 что означает
  • Ошибка ввода пинкода пинкод неукомплектован
  • Ошибка ввода пин кода пин код не укомплектован 1с
  • Ошибка ввода отсутствует исполняющее ядро для расширения имени файла vbs