Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Паскаль, Turbo Pascal, PascalABC.NET
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 08.06.2020, 07:34   #1
ichi
Форумчанин
 
Регистрация: 14.03.2012
Сообщений: 138
По умолчанию [Turbo Pascal][DosBox] Программа не правильно работает при записи строк в файл

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

Код:
{$M $1000,0,0}
program test2;
uses crt, dos;
var	
	OldText: Procedure;
	filetext: text;
	fname: string;
	str: string;
	
procedure savestringtofile(var f:text; var name, s:string);
begin
	assign(f, name);
	append(f);
	writeln(f, s);   
	close(f);
end;

procedure createfile(var f:text; var name:string);
begin
	assign(f, name);
	rewrite(f);
	close(f);
end;

{$F+}
Procedure Text; Interrupt;
Begin

	savestringtofile(filetext, fname, str);
	
	Inline($9C);
	OldText;
End;
{$F-}

Begin
	fname := 'text.txt';
	str := '1234567890';
	createfile(filetext, fname); 
	GetIntVec($8,@OldText);
	SetIntVec($8,Addr(Text));
	Keep(0);
End.
ichi вне форума Ответить с цитированием
Старый 08.06.2020, 10:40   #2
ViktorR
Старожил
 
Регистрация: 23.10.2010
Сообщений: 2,304
По умолчанию

Совсем не помню, так было давно. Но один вопрос:
есть такая переменная:
Код:
filetext: text;
Есть вызов, в котором эта переменная используется.
Тут:
Код:
savestringtofile(filetext, fname, str);
и тут:
Код:
createfile(filetext, fname);
как указатель на файл.
Но не понятно, где у этой переменной выполняется инициализация?
Если в этой процедуре,
Код:
procedure createfile(var f:text; var name:string);
begin
	assign(f, name);
	rewrite(f);
	close(f);
end;
то что тогда тут делает close(f)?

Или так и должно быть? Моя логика хромает и не могу понять, что тут должно делаться.
Как-то так, ...
ViktorR вне форума Ответить с цитированием
Старый 08.06.2020, 13:24   #3
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,537
По умолчанию

Цитата:
Сообщение от ViktorR Посмотреть сообщение
то что тогда тут делает close(f)?
Или так и должно быть? Моя логика хромает и не могу понять, что тут должно делаться.
Это у ТСа логика хромает. Если перевести на обычную житейскую ситуацию: нужно положить деньги и бриллианты в шкатулку : достаём из сейфа шкатулку, открываем её и... запихиваем обратно в сейф. И потом удивляемся: чёй-то не лезет.
Ясен пень, весь процесс работы с файлом имеет 3 стадии:
- открыли файл (имеющийся) или создали новый;
- поработали с ним: дописали/удалили/поменяли;
- закрыли файл.
Тут даже программером не надо быть, обычная бабка с Комаровки поймёт, что не так, если ей рассказать словами производимые действия.
digitalis вне форума Ответить с цитированием
Старый 08.06.2020, 14:00   #4
ichi
Форумчанин
 
Регистрация: 14.03.2012
Сообщений: 138
По умолчанию

Судя по книгам по Turbo Pascal из Интернет, сначала описывается файловая переменная типа текстовый файл

Цитата:
Сообщение от ichi Посмотреть сообщение
Код:
filetext: text;
Связываем файловую переменную с файлом на жестком диске

Цитата:
Сообщение от ichi Посмотреть сообщение
Код:
assign(f, name);
Работаем с файлом, пишем строку добавляя ее в конец файла

Цитата:
Сообщение от ichi Посмотреть сообщение
Код:
append(f);
writeln(f, s);
закрываем файл

Цитата:
Сообщение от ichi Посмотреть сообщение
Код:
close(f);
Файл создается один раз в процедуре

Цитата:
Сообщение от ViktorR Посмотреть сообщение
Код:
procedure createfile(var f:text; var name:string);
begin
	assign(f, name);
	rewrite(f);
	close(f);
end;
Потом управление передается процедуре прерывания таймера. В ней мы на каждый тик таймера открываем текстовый файл на добавление строки в конец. Потом разрываем файловую переменную с файлом на жестком диске.

Вроде так все работает.

Цитата:
Сообщение от digitalis Посмотреть сообщение
Тут даже программером не надо быть, обычная бабка с Комаровки поймёт, что не так, если ей рассказать словами производимые действия.
Подскажите, пожалуйста, что не так, я что-то не могу понять.

Последний раз редактировалось ichi; 08.06.2020 в 14:02.
ichi вне форума Ответить с цитированием
Старый 08.06.2020, 16:40   #5
ViktorR
Старожил
 
Регистрация: 23.10.2010
Сообщений: 2,304
По умолчанию

Т.е. вы рассчитываете, что после создания файла указатель на файл будет храниться в переменной filetext, и после возвращения из процедуры?
Файловая переменная - это указатель на буфер в ОС.
Буфер создаётся на стадии assign() и инициируется на стадии reset(), append(), rewrit().
После закрытия файла в переменной указатель может быть и будет храниться, вот только этот указатель будет ссылаться на область памяти, которая освобождена командой close(f).
Так что, что там будет твориться и как менеджер ОС будет обрабатывать эту ситуацию - хз.

Если нет, то для чего вам эта переменная?
Для создания файла достаточно передать в процедуру только имя файла.
Как-то так, ...
ViktorR вне форума Ответить с цитированием
Старый 08.06.2020, 18:06   #6
ichi
Форумчанин
 
Регистрация: 14.03.2012
Сообщений: 138
По умолчанию

Цитата:
Сообщение от ViktorR Посмотреть сообщение
Если нет, то для чего вам эта переменная?
Вроде я уже писал зачем нужна эта переменная

Цитата:
Сообщение от ichi Посмотреть сообщение
Цитата:
Сообщение от ichi
Код:
Код:
filetext: text;
Связываем файловую переменную с файлом на жестком диске
Цитата:
Сообщение от ViktorR Посмотреть сообщение
Код:
close(f)
Разрывает файловую переменную с файлом на жестком диске.

Если вы намекаете, что процедуру
Код:
Assign(f, FileName)
достаточно вызвать раз, а потом использовать до конца работы программы, и процедуру
Код:
close(f)
достаточно вызвать раз при выходе из программы, то я уже пробовал так переделать код. Программа работает также как я описал в первом посте.

Вот переделанный код:

Код:
{$M $1000,0,0}
program test2;
uses crt, dos;
var	
	OldText: Procedure;
	filetext: text;
	fname: string;
	str: string;
	
procedure savestringtofile(var f:text; var name, s:string);
begin
	append(f);
	writeln(f, s);   
end;

procedure createfile(var f:text; var name:string);
begin
	rewrite(f);
end;

{$F+}
Procedure Text; Interrupt;
Begin

	savestringtofile(filetext, fname, str);
	
	Inline($9C);
	OldText;
End;
{$F-}

Begin
	fname := 'text.txt';
	str := '1234567890';
	assign(filetext, fname);
	createfile(filetext, fname); 
	GetIntVec($8,@OldText);
	SetIntVec($8,Addr(Text));
	close(filetext);
	Keep(0);
End.
ichi вне форума Ответить с цитированием
Старый 08.06.2020, 18:58   #7
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,285
По умолчанию

Во-первых, мне кажется, что работа с файловой переменной была верна в первом коде. Во-вторых, может быть проблема в том, что процедура обработки прерывания не успевает закончиться до следующего срабатывания прерывания?
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Старый 08.06.2020, 20:07   #8
ViktorR
Старожил
 
Регистрация: 23.10.2010
Сообщений: 2,304
По умолчанию

Цитата:
Сообщение от ichi Посмотреть сообщение
Цитата:
Сообщение от ichi
Код:
Код:
filetext: text;
Связываем файловую переменную с файлом на жестком диске
Ничего вы тут не связываете. Вы определяете переменную, которая будет хранить ссылку на буфер данных. И только.
Буфер данных будет создан при обращении к ОС - процедура assign(f, <имя файла>). В это время и будет заполнена ссылка. Ещё раз - это не привязка к файлу. Непосредственно с файлом ваша программа не работает. Там включается менеджер ОС, который и отслеживает работу вашей программы с буфером.
Я намекаю на то, что эта переменная, при её использовании, должна что-то хранить - ссылку.
Вы её используете, см. мой первый пост, но не инициализируете в нужное время.
close(f) - не разрывает файловую переменную с файлом на диске, а убивает буфер, который был организован ОС при вызове из программы процедуры assign().
Таким образом переменная f может содержать ссылку на буфер, которого нет.
Как всё это работает в режиме прерываний - не знаю.
Как часто выполняются прерывания, как эти прерывания синхронизированы с работой процедур записи, ...
Как-то так, ...
ViktorR вне форума Ответить с цитированием
Старый 11.06.2020, 17:17   #9
ichi
Форумчанин
 
Регистрация: 14.03.2012
Сообщений: 138
По умолчанию

Цитата:
Сообщение от BDA Посмотреть сообщение
Во-первых, мне кажется, что работа с файловой переменной была верна в первом коде. Во-вторых, может быть проблема в том, что процедура обработки прерывания не успевает закончиться до следующего срабатывания прерывания?
Цитата:
Сообщение от ViktorR Посмотреть сообщение
Ничего вы тут не связываете. Вы определяете переменную, которая будет хранить ссылку на буфер данных. И только.
Буфер данных будет создан при обращении к ОС - процедура assign(f, <имя файла>). В это время и будет заполнена ссылка. Ещё раз - это не привязка к файлу. Непосредственно с файлом ваша программа не работает. Там включается менеджер ОС, который и отслеживает работу вашей программы с буфером.
Я намекаю на то, что эта переменная, при её использовании, должна что-то хранить - ссылку.
Вы её используете, см. мой первый пост, но не инициализируете в нужное время.
close(f) - не разрывает файловую переменную с файлом на диске, а убивает буфер, который был организован ОС при вызове из программы процедуры assign().
Таким образом переменная f может содержать ссылку на буфер, которого нет.
Как всё это работает в режиме прерываний - не знаю.
Как часто выполняются прерывания, как эти прерывания синхронизированы с работой процедур записи, ...
Всем спасибо за ответы. Программа заработала как надо. Тестировал программу 10 минут, все это время программа нормально записывала строку в файл.

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

Кому интересно, вот код с внесенными уже изменениями:

Код:
{$M $1000,0,0}
program test2;
uses crt, dos;
var	
	OldText: Procedure;
	filetext: text;
	fname: string;
	str: string;
	t: word;
	
function GetIOErrorCode:integer;
begin
	GetIOErrorCode := IOResult;
end;
	
function ConvIOErrorCodeToStrMsg(ioerrorcode:integer):string;
begin
	case ioerrorcode of 
		0: ConvIOErrorCodeToStrMsg := 'Error not found';
		3: ConvIOErrorCodeToStrMsg := 'Path not found';
		4: ConvIOErrorCodeToStrMsg := 'Too many open files';
		5: ConvIOErrorCodeToStrMsg := 'File access denied';
		12: ConvIOErrorCodeToStrMsg := 'Invalid file access code';
		16: ConvIOErrorCodeToStrMsg := 'Cannot remove current directory';
		100: ConvIOErrorCodeToStrMsg := 'Disk read error';
		101: ConvIOErrorCodeToStrMsg := 'Disk write error';
		102: ConvIOErrorCodeToStrMsg := 'File not assigned';
		103: ConvIOErrorCodeToStrMsg := 'File not open';
		104: ConvIOErrorCodeToStrMsg := 'File not open for input';
		105: ConvIOErrorCodeToStrMsg := 'File not open for output';
		106: ConvIOErrorCodeToStrMsg := 'Invalid numeric format';
		152: ConvIOErrorCodeToStrMsg := 'Drive not ready';
	end;
end;	

procedure savestringtofile(var f:text; var name, s:string);
begin
	writeln;
	{$I-}
	assign(f, name);
	append(f);
	writeln(f, s);
	close(f);
	write('Message savestringtofile procedure: ' + ConvIOErrorCodeToStrMsg(GetIOErrorCode));
	{$I+}
end;

procedure createfile(var f:text; var name:string);
begin
	writeln;
	{$I-}
	assign(f, name);
	rewrite(f);	
	close(f);
	write('Message createfile procedure: ' + ConvIOErrorCodeToStrMsg(GetIOErrorCode));
	{$I+}
end;

{$F+}
Procedure Text; Interrupt;
Begin
	inc(t, 11);
	if t>=100 then 
	begin
		dec(t, 100);
		savestringtofile(filetext, fname, str);
	end;
	
	Inline($9C);
	OldText;
End;
{$F-}

Begin
	
	fname := 'text.txt';
	str := '1234567890';
	t := 0;
	
	createfile(filetext, fname);
	
	GetIntVec($8,@OldText);
	SetIntVec($8,Addr(Text));

	Keep(0);
End.
ichi вне форума Ответить с цитированием
Старый 12.06.2020, 15:37   #10
ViktorR
Старожил
 
Регистрация: 23.10.2010
Сообщений: 2,304
По умолчанию

А как это будет работать, если ваш код переписать:
Код:
procedure savestringtofile(var f:text; var name, s:string);
begin
	writeln;
	{$I-}
	assign(f, name);
	append(f);
	writeln(f, s);
	close(f);
	write('Message savestringtofile procedure: ' + ConvIOErrorCodeToStrMsg(GetIOErrorCode));
	{$I+}
end;

procedure createfile(var f:text; var name:string);
begin
	writeln;
	{$I-}
	assign(f, name);
	rewrite(f);	
	close(f);
	write('Message createfile procedure: ' + ConvIOErrorCodeToStrMsg(GetIOErrorCode));
	{$I+}
end;
так:
Код:
procedure savestringtofile(var name, s:string);
var f: text;
begin
	writeln;
	assign(f, name);
{$I-}
	append(f);
{$I+}
	write('Message savestringtofile procedure: ' + ConvIOErrorCodeToStrMsg(IOResult));
	writeln(f, s);
	close(f);
end;

procedure createfile(var name:string);
var f: text;
begin
	writeln;
	assign(f, name);
{$I-}
	rewrite(f);
{$I+}	
	write('Message createfile procedure: ' + ConvIOErrorCodeToStrMsg(IOResult));
	close(f);
end;
Соответственно и описание переменной,
Код:
filetext: text;
и её присутствие в вызовах не нужно.
Ошибка ввода/вывода возникает в моменты инициализации работы с файлом: reset(f), append(f), rewrite(f).
Если файл был открыт, то он будет и закрыт - close(f).
assign(f,<file_name>) - это обращение к ОС за получением буфера. Но это вроде всегда без проблем.
На этой процедуре наличие/отсутствие файла не проверяется.
Как-то так, ...
ViktorR вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[Turbo Pascal][DosBox] Как все таки правильно работать с видеопамятью на прямую в текстовом режиме? ichi Паскаль, Turbo Pascal, PascalABC.NET 0 19.04.2020 20:30
Записи. Записи с вариантами. Turbo Pascal Marksman_SwAt Помощь студентам 7 07.05.2014 19:27
Программа, которая запрашивает символы и записывает их в файл до пары одинаковых символов ( Turbo Pascal ) bikmai4ik Помощь студентам 4 05.12.2013 13:57
Не правильно считает.(turbo Pascal) spezzA Паскаль, Turbo Pascal, PascalABC.NET 0 15.06.2011 17:08
Turbo C и Dosbox chester997 Общие вопросы C/C++ 2 02.10.2010 13:01